]> git.openstreetmap.org Git - rails.git/blob - vendor/assets/iD/iD.js
Merge remote-tracking branch 'upstream/pull/3445'
[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$1m =
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$S = function (exec) {
23           try {
24             return !!exec();
25           } catch (error) {
26             return true;
27           }
28         };
29
30         var fails$R = fails$S;
31
32         // Detect IE8's incomplete defineProperty implementation
33         var descriptors = !fails$R(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 call$q = Function.prototype.call;
39
40         var functionCall = call$q.bind ? call$q.bind(call$q) : function () {
41           return call$q.apply(call$q, arguments);
42         };
43
44         var objectPropertyIsEnumerable = {};
45
46         var $propertyIsEnumerable$2 = {}.propertyIsEnumerable;
47         // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
48         var getOwnPropertyDescriptor$5 = Object.getOwnPropertyDescriptor;
49
50         // Nashorn ~ JDK8 bug
51         var NASHORN_BUG = getOwnPropertyDescriptor$5 && !$propertyIsEnumerable$2.call({ 1: 2 }, 1);
52
53         // `Object.prototype.propertyIsEnumerable` method implementation
54         // https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
55         objectPropertyIsEnumerable.f = NASHORN_BUG ? function propertyIsEnumerable(V) {
56           var descriptor = getOwnPropertyDescriptor$5(this, V);
57           return !!descriptor && descriptor.enumerable;
58         } : $propertyIsEnumerable$2;
59
60         var createPropertyDescriptor$7 = function (bitmap, value) {
61           return {
62             enumerable: !(bitmap & 1),
63             configurable: !(bitmap & 2),
64             writable: !(bitmap & 4),
65             value: value
66           };
67         };
68
69         var FunctionPrototype$3 = Function.prototype;
70         var bind$h = FunctionPrototype$3.bind;
71         var call$p = FunctionPrototype$3.call;
72         var callBind = bind$h && bind$h.bind(call$p);
73
74         var functionUncurryThis = bind$h ? function (fn) {
75           return fn && callBind(call$p, fn);
76         } : function (fn) {
77           return fn && function () {
78             return call$p.apply(fn, arguments);
79           };
80         };
81
82         var uncurryThis$X = functionUncurryThis;
83
84         var toString$n = uncurryThis$X({}.toString);
85         var stringSlice$c = uncurryThis$X(''.slice);
86
87         var classofRaw$1 = function (it) {
88           return stringSlice$c(toString$n(it), 8, -1);
89         };
90
91         var global$1l = global$1m;
92         var uncurryThis$W = functionUncurryThis;
93         var fails$Q = fails$S;
94         var classof$e = classofRaw$1;
95
96         var Object$5 = global$1l.Object;
97         var split$4 = uncurryThis$W(''.split);
98
99         // fallback for non-array-like ES3 and non-enumerable old V8 strings
100         var indexedObject = fails$Q(function () {
101           // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
102           // eslint-disable-next-line no-prototype-builtins -- safe
103           return !Object$5('z').propertyIsEnumerable(0);
104         }) ? function (it) {
105           return classof$e(it) == 'String' ? split$4(it, '') : Object$5(it);
106         } : Object$5;
107
108         var global$1k = global$1m;
109
110         var TypeError$o = global$1k.TypeError;
111
112         // `RequireObjectCoercible` abstract operation
113         // https://tc39.es/ecma262/#sec-requireobjectcoercible
114         var requireObjectCoercible$e = function (it) {
115           if (it == undefined) throw TypeError$o("Can't call method on " + it);
116           return it;
117         };
118
119         // toObject with fallback for non-array-like ES3 strings
120         var IndexedObject$4 = indexedObject;
121         var requireObjectCoercible$d = requireObjectCoercible$e;
122
123         var toIndexedObject$c = function (it) {
124           return IndexedObject$4(requireObjectCoercible$d(it));
125         };
126
127         // `IsCallable` abstract operation
128         // https://tc39.es/ecma262/#sec-iscallable
129         var isCallable$r = function (argument) {
130           return typeof argument == 'function';
131         };
132
133         var isCallable$q = isCallable$r;
134
135         var isObject$s = function (it) {
136           return typeof it == 'object' ? it !== null : isCallable$q(it);
137         };
138
139         var global$1j = global$1m;
140         var isCallable$p = isCallable$r;
141
142         var aFunction = function (argument) {
143           return isCallable$p(argument) ? argument : undefined;
144         };
145
146         var getBuiltIn$b = function (namespace, method) {
147           return arguments.length < 2 ? aFunction(global$1j[namespace]) : global$1j[namespace] && global$1j[namespace][method];
148         };
149
150         var uncurryThis$V = functionUncurryThis;
151
152         var objectIsPrototypeOf = uncurryThis$V({}.isPrototypeOf);
153
154         var getBuiltIn$a = getBuiltIn$b;
155
156         var engineUserAgent = getBuiltIn$a('navigator', 'userAgent') || '';
157
158         var global$1i = global$1m;
159         var userAgent$7 = engineUserAgent;
160
161         var process$4 = global$1i.process;
162         var Deno = global$1i.Deno;
163         var versions = process$4 && process$4.versions || Deno && Deno.version;
164         var v8 = versions && versions.v8;
165         var match, version$1;
166
167         if (v8) {
168           match = v8.split('.');
169           // in old Chrome, versions of V8 isn't V8 = Chrome / 10
170           // but their correct versions are not interesting for us
171           version$1 = match[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1]);
172         }
173
174         // BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0`
175         // so check `userAgent` even if `.v8` exists, but 0
176         if (!version$1 && userAgent$7) {
177           match = userAgent$7.match(/Edge\/(\d+)/);
178           if (!match || match[1] >= 74) {
179             match = userAgent$7.match(/Chrome\/(\d+)/);
180             if (match) version$1 = +match[1];
181           }
182         }
183
184         var engineV8Version = version$1;
185
186         /* eslint-disable es/no-symbol -- required for testing */
187
188         var V8_VERSION$3 = engineV8Version;
189         var fails$P = fails$S;
190
191         // eslint-disable-next-line es/no-object-getownpropertysymbols -- required for testing
192         var nativeSymbol = !!Object.getOwnPropertySymbols && !fails$P(function () {
193           var symbol = Symbol();
194           // Chrome 38 Symbol has incorrect toString conversion
195           // `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances
196           return !String(symbol) || !(Object(symbol) instanceof Symbol) ||
197             // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
198             !Symbol.sham && V8_VERSION$3 && V8_VERSION$3 < 41;
199         });
200
201         /* eslint-disable es/no-symbol -- required for testing */
202
203         var NATIVE_SYMBOL$3 = nativeSymbol;
204
205         var useSymbolAsUid = NATIVE_SYMBOL$3
206           && !Symbol.sham
207           && typeof Symbol.iterator == 'symbol';
208
209         var global$1h = global$1m;
210         var getBuiltIn$9 = getBuiltIn$b;
211         var isCallable$o = isCallable$r;
212         var isPrototypeOf$9 = objectIsPrototypeOf;
213         var USE_SYMBOL_AS_UID$1 = useSymbolAsUid;
214
215         var Object$4 = global$1h.Object;
216
217         var isSymbol$6 = USE_SYMBOL_AS_UID$1 ? function (it) {
218           return typeof it == 'symbol';
219         } : function (it) {
220           var $Symbol = getBuiltIn$9('Symbol');
221           return isCallable$o($Symbol) && isPrototypeOf$9($Symbol.prototype, Object$4(it));
222         };
223
224         var global$1g = global$1m;
225
226         var String$6 = global$1g.String;
227
228         var tryToString$5 = function (argument) {
229           try {
230             return String$6(argument);
231           } catch (error) {
232             return 'Object';
233           }
234         };
235
236         var global$1f = global$1m;
237         var isCallable$n = isCallable$r;
238         var tryToString$4 = tryToString$5;
239
240         var TypeError$n = global$1f.TypeError;
241
242         // `Assert: IsCallable(argument) is true`
243         var aCallable$a = function (argument) {
244           if (isCallable$n(argument)) return argument;
245           throw TypeError$n(tryToString$4(argument) + ' is not a function');
246         };
247
248         var aCallable$9 = aCallable$a;
249
250         // `GetMethod` abstract operation
251         // https://tc39.es/ecma262/#sec-getmethod
252         var getMethod$7 = function (V, P) {
253           var func = V[P];
254           return func == null ? undefined : aCallable$9(func);
255         };
256
257         var global$1e = global$1m;
258         var call$o = functionCall;
259         var isCallable$m = isCallable$r;
260         var isObject$r = isObject$s;
261
262         var TypeError$m = global$1e.TypeError;
263
264         // `OrdinaryToPrimitive` abstract operation
265         // https://tc39.es/ecma262/#sec-ordinarytoprimitive
266         var ordinaryToPrimitive$1 = function (input, pref) {
267           var fn, val;
268           if (pref === 'string' && isCallable$m(fn = input.toString) && !isObject$r(val = call$o(fn, input))) return val;
269           if (isCallable$m(fn = input.valueOf) && !isObject$r(val = call$o(fn, input))) return val;
270           if (pref !== 'string' && isCallable$m(fn = input.toString) && !isObject$r(val = call$o(fn, input))) return val;
271           throw TypeError$m("Can't convert object to primitive value");
272         };
273
274         var shared$5 = {exports: {}};
275
276         var isPure = false;
277
278         var global$1d = global$1m;
279
280         // eslint-disable-next-line es/no-object-defineproperty -- safe
281         var defineProperty$b = Object.defineProperty;
282
283         var setGlobal$3 = function (key, value) {
284           try {
285             defineProperty$b(global$1d, key, { value: value, configurable: true, writable: true });
286           } catch (error) {
287             global$1d[key] = value;
288           } return value;
289         };
290
291         var global$1c = global$1m;
292         var setGlobal$2 = setGlobal$3;
293
294         var SHARED = '__core-js_shared__';
295         var store$4 = global$1c[SHARED] || setGlobal$2(SHARED, {});
296
297         var sharedStore = store$4;
298
299         var store$3 = sharedStore;
300
301         (shared$5.exports = function (key, value) {
302           return store$3[key] || (store$3[key] = value !== undefined ? value : {});
303         })('versions', []).push({
304           version: '3.19.1',
305           mode: 'global',
306           copyright: '© 2021 Denis Pushkarev (zloirock.ru)'
307         });
308
309         var global$1b = global$1m;
310         var requireObjectCoercible$c = requireObjectCoercible$e;
311
312         var Object$3 = global$1b.Object;
313
314         // `ToObject` abstract operation
315         // https://tc39.es/ecma262/#sec-toobject
316         var toObject$j = function (argument) {
317           return Object$3(requireObjectCoercible$c(argument));
318         };
319
320         var uncurryThis$U = functionUncurryThis;
321         var toObject$i = toObject$j;
322
323         var hasOwnProperty$3 = uncurryThis$U({}.hasOwnProperty);
324
325         // `HasOwnProperty` abstract operation
326         // https://tc39.es/ecma262/#sec-hasownproperty
327         var hasOwnProperty_1 = Object.hasOwn || function hasOwn(it, key) {
328           return hasOwnProperty$3(toObject$i(it), key);
329         };
330
331         var uncurryThis$T = functionUncurryThis;
332
333         var id$2 = 0;
334         var postfix = Math.random();
335         var toString$m = uncurryThis$T(1.0.toString);
336
337         var uid$5 = function (key) {
338           return 'Symbol(' + (key === undefined ? '' : key) + ')_' + toString$m(++id$2 + postfix, 36);
339         };
340
341         var global$1a = global$1m;
342         var shared$4 = shared$5.exports;
343         var hasOwn$l = hasOwnProperty_1;
344         var uid$4 = uid$5;
345         var NATIVE_SYMBOL$2 = nativeSymbol;
346         var USE_SYMBOL_AS_UID = useSymbolAsUid;
347
348         var WellKnownSymbolsStore$1 = shared$4('wks');
349         var Symbol$3 = global$1a.Symbol;
350         var symbolFor = Symbol$3 && Symbol$3['for'];
351         var createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol$3 : Symbol$3 && Symbol$3.withoutSetter || uid$4;
352
353         var wellKnownSymbol$t = function (name) {
354           if (!hasOwn$l(WellKnownSymbolsStore$1, name) || !(NATIVE_SYMBOL$2 || typeof WellKnownSymbolsStore$1[name] == 'string')) {
355             var description = 'Symbol.' + name;
356             if (NATIVE_SYMBOL$2 && hasOwn$l(Symbol$3, name)) {
357               WellKnownSymbolsStore$1[name] = Symbol$3[name];
358             } else if (USE_SYMBOL_AS_UID && symbolFor) {
359               WellKnownSymbolsStore$1[name] = symbolFor(description);
360             } else {
361               WellKnownSymbolsStore$1[name] = createWellKnownSymbol(description);
362             }
363           } return WellKnownSymbolsStore$1[name];
364         };
365
366         var global$19 = global$1m;
367         var call$n = functionCall;
368         var isObject$q = isObject$s;
369         var isSymbol$5 = isSymbol$6;
370         var getMethod$6 = getMethod$7;
371         var ordinaryToPrimitive = ordinaryToPrimitive$1;
372         var wellKnownSymbol$s = wellKnownSymbol$t;
373
374         var TypeError$l = global$19.TypeError;
375         var TO_PRIMITIVE$1 = wellKnownSymbol$s('toPrimitive');
376
377         // `ToPrimitive` abstract operation
378         // https://tc39.es/ecma262/#sec-toprimitive
379         var toPrimitive$3 = function (input, pref) {
380           if (!isObject$q(input) || isSymbol$5(input)) return input;
381           var exoticToPrim = getMethod$6(input, TO_PRIMITIVE$1);
382           var result;
383           if (exoticToPrim) {
384             if (pref === undefined) pref = 'default';
385             result = call$n(exoticToPrim, input, pref);
386             if (!isObject$q(result) || isSymbol$5(result)) return result;
387             throw TypeError$l("Can't convert object to primitive value");
388           }
389           if (pref === undefined) pref = 'number';
390           return ordinaryToPrimitive(input, pref);
391         };
392
393         var toPrimitive$2 = toPrimitive$3;
394         var isSymbol$4 = isSymbol$6;
395
396         // `ToPropertyKey` abstract operation
397         // https://tc39.es/ecma262/#sec-topropertykey
398         var toPropertyKey$5 = function (argument) {
399           var key = toPrimitive$2(argument, 'string');
400           return isSymbol$4(key) ? key : key + '';
401         };
402
403         var global$18 = global$1m;
404         var isObject$p = isObject$s;
405
406         var document$3 = global$18.document;
407         // typeof document.createElement is 'object' in old IE
408         var EXISTS$1 = isObject$p(document$3) && isObject$p(document$3.createElement);
409
410         var documentCreateElement$2 = function (it) {
411           return EXISTS$1 ? document$3.createElement(it) : {};
412         };
413
414         var DESCRIPTORS$n = descriptors;
415         var fails$O = fails$S;
416         var createElement$1 = documentCreateElement$2;
417
418         // Thank's IE8 for his funny defineProperty
419         var ie8DomDefine = !DESCRIPTORS$n && !fails$O(function () {
420           // eslint-disable-next-line es/no-object-defineproperty -- requied for testing
421           return Object.defineProperty(createElement$1('div'), 'a', {
422             get: function () { return 7; }
423           }).a != 7;
424         });
425
426         var DESCRIPTORS$m = descriptors;
427         var call$m = functionCall;
428         var propertyIsEnumerableModule$2 = objectPropertyIsEnumerable;
429         var createPropertyDescriptor$6 = createPropertyDescriptor$7;
430         var toIndexedObject$b = toIndexedObject$c;
431         var toPropertyKey$4 = toPropertyKey$5;
432         var hasOwn$k = hasOwnProperty_1;
433         var IE8_DOM_DEFINE$1 = ie8DomDefine;
434
435         // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
436         var $getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor;
437
438         // `Object.getOwnPropertyDescriptor` method
439         // https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
440         objectGetOwnPropertyDescriptor.f = DESCRIPTORS$m ? $getOwnPropertyDescriptor$1 : function getOwnPropertyDescriptor(O, P) {
441           O = toIndexedObject$b(O);
442           P = toPropertyKey$4(P);
443           if (IE8_DOM_DEFINE$1) try {
444             return $getOwnPropertyDescriptor$1(O, P);
445           } catch (error) { /* empty */ }
446           if (hasOwn$k(O, P)) return createPropertyDescriptor$6(!call$m(propertyIsEnumerableModule$2.f, O, P), O[P]);
447         };
448
449         var objectDefineProperty = {};
450
451         var global$17 = global$1m;
452         var isObject$o = isObject$s;
453
454         var String$5 = global$17.String;
455         var TypeError$k = global$17.TypeError;
456
457         // `Assert: Type(argument) is Object`
458         var anObject$n = function (argument) {
459           if (isObject$o(argument)) return argument;
460           throw TypeError$k(String$5(argument) + ' is not an object');
461         };
462
463         var global$16 = global$1m;
464         var DESCRIPTORS$l = descriptors;
465         var IE8_DOM_DEFINE = ie8DomDefine;
466         var anObject$m = anObject$n;
467         var toPropertyKey$3 = toPropertyKey$5;
468
469         var TypeError$j = global$16.TypeError;
470         // eslint-disable-next-line es/no-object-defineproperty -- safe
471         var $defineProperty$1 = Object.defineProperty;
472
473         // `Object.defineProperty` method
474         // https://tc39.es/ecma262/#sec-object.defineproperty
475         objectDefineProperty.f = DESCRIPTORS$l ? $defineProperty$1 : function defineProperty(O, P, Attributes) {
476           anObject$m(O);
477           P = toPropertyKey$3(P);
478           anObject$m(Attributes);
479           if (IE8_DOM_DEFINE) try {
480             return $defineProperty$1(O, P, Attributes);
481           } catch (error) { /* empty */ }
482           if ('get' in Attributes || 'set' in Attributes) throw TypeError$j('Accessors not supported');
483           if ('value' in Attributes) O[P] = Attributes.value;
484           return O;
485         };
486
487         var DESCRIPTORS$k = descriptors;
488         var definePropertyModule$7 = objectDefineProperty;
489         var createPropertyDescriptor$5 = createPropertyDescriptor$7;
490
491         var createNonEnumerableProperty$b = DESCRIPTORS$k ? function (object, key, value) {
492           return definePropertyModule$7.f(object, key, createPropertyDescriptor$5(1, value));
493         } : function (object, key, value) {
494           object[key] = value;
495           return object;
496         };
497
498         var redefine$h = {exports: {}};
499
500         var uncurryThis$S = functionUncurryThis;
501         var isCallable$l = isCallable$r;
502         var store$2 = sharedStore;
503
504         var functionToString$1 = uncurryThis$S(Function.toString);
505
506         // this helper broken in `core-js@3.4.1-3.4.4`, so we can't use `shared` helper
507         if (!isCallable$l(store$2.inspectSource)) {
508           store$2.inspectSource = function (it) {
509             return functionToString$1(it);
510           };
511         }
512
513         var inspectSource$4 = store$2.inspectSource;
514
515         var global$15 = global$1m;
516         var isCallable$k = isCallable$r;
517         var inspectSource$3 = inspectSource$4;
518
519         var WeakMap$1 = global$15.WeakMap;
520
521         var nativeWeakMap = isCallable$k(WeakMap$1) && /native code/.test(inspectSource$3(WeakMap$1));
522
523         var shared$3 = shared$5.exports;
524         var uid$3 = uid$5;
525
526         var keys$3 = shared$3('keys');
527
528         var sharedKey$4 = function (key) {
529           return keys$3[key] || (keys$3[key] = uid$3(key));
530         };
531
532         var hiddenKeys$6 = {};
533
534         var NATIVE_WEAK_MAP = nativeWeakMap;
535         var global$14 = global$1m;
536         var uncurryThis$R = functionUncurryThis;
537         var isObject$n = isObject$s;
538         var createNonEnumerableProperty$a = createNonEnumerableProperty$b;
539         var hasOwn$j = hasOwnProperty_1;
540         var shared$2 = sharedStore;
541         var sharedKey$3 = sharedKey$4;
542         var hiddenKeys$5 = hiddenKeys$6;
543
544         var OBJECT_ALREADY_INITIALIZED = 'Object already initialized';
545         var TypeError$i = global$14.TypeError;
546         var WeakMap = global$14.WeakMap;
547         var set$4, get$5, has;
548
549         var enforce = function (it) {
550           return has(it) ? get$5(it) : set$4(it, {});
551         };
552
553         var getterFor = function (TYPE) {
554           return function (it) {
555             var state;
556             if (!isObject$n(it) || (state = get$5(it)).type !== TYPE) {
557               throw TypeError$i('Incompatible receiver, ' + TYPE + ' required');
558             } return state;
559           };
560         };
561
562         if (NATIVE_WEAK_MAP || shared$2.state) {
563           var store$1 = shared$2.state || (shared$2.state = new WeakMap());
564           var wmget = uncurryThis$R(store$1.get);
565           var wmhas = uncurryThis$R(store$1.has);
566           var wmset = uncurryThis$R(store$1.set);
567           set$4 = function (it, metadata) {
568             if (wmhas(store$1, it)) throw new TypeError$i(OBJECT_ALREADY_INITIALIZED);
569             metadata.facade = it;
570             wmset(store$1, it, metadata);
571             return metadata;
572           };
573           get$5 = function (it) {
574             return wmget(store$1, it) || {};
575           };
576           has = function (it) {
577             return wmhas(store$1, it);
578           };
579         } else {
580           var STATE = sharedKey$3('state');
581           hiddenKeys$5[STATE] = true;
582           set$4 = function (it, metadata) {
583             if (hasOwn$j(it, STATE)) throw new TypeError$i(OBJECT_ALREADY_INITIALIZED);
584             metadata.facade = it;
585             createNonEnumerableProperty$a(it, STATE, metadata);
586             return metadata;
587           };
588           get$5 = function (it) {
589             return hasOwn$j(it, STATE) ? it[STATE] : {};
590           };
591           has = function (it) {
592             return hasOwn$j(it, STATE);
593           };
594         }
595
596         var internalState = {
597           set: set$4,
598           get: get$5,
599           has: has,
600           enforce: enforce,
601           getterFor: getterFor
602         };
603
604         var DESCRIPTORS$j = descriptors;
605         var hasOwn$i = hasOwnProperty_1;
606
607         var FunctionPrototype$2 = Function.prototype;
608         // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
609         var getDescriptor = DESCRIPTORS$j && Object.getOwnPropertyDescriptor;
610
611         var EXISTS = hasOwn$i(FunctionPrototype$2, 'name');
612         // additional protection from minified / mangled / dropped function names
613         var PROPER = EXISTS && (function something() { /* empty */ }).name === 'something';
614         var CONFIGURABLE = EXISTS && (!DESCRIPTORS$j || (DESCRIPTORS$j && getDescriptor(FunctionPrototype$2, 'name').configurable));
615
616         var functionName = {
617           EXISTS: EXISTS,
618           PROPER: PROPER,
619           CONFIGURABLE: CONFIGURABLE
620         };
621
622         var global$13 = global$1m;
623         var isCallable$j = isCallable$r;
624         var hasOwn$h = hasOwnProperty_1;
625         var createNonEnumerableProperty$9 = createNonEnumerableProperty$b;
626         var setGlobal$1 = setGlobal$3;
627         var inspectSource$2 = inspectSource$4;
628         var InternalStateModule$9 = internalState;
629         var CONFIGURABLE_FUNCTION_NAME$2 = functionName.CONFIGURABLE;
630
631         var getInternalState$7 = InternalStateModule$9.get;
632         var enforceInternalState$1 = InternalStateModule$9.enforce;
633         var TEMPLATE = String(String).split('String');
634
635         (redefine$h.exports = function (O, key, value, options) {
636           var unsafe = options ? !!options.unsafe : false;
637           var simple = options ? !!options.enumerable : false;
638           var noTargetGet = options ? !!options.noTargetGet : false;
639           var name = options && options.name !== undefined ? options.name : key;
640           var state;
641           if (isCallable$j(value)) {
642             if (String(name).slice(0, 7) === 'Symbol(') {
643               name = '[' + String(name).replace(/^Symbol\(([^)]*)\)/, '$1') + ']';
644             }
645             if (!hasOwn$h(value, 'name') || (CONFIGURABLE_FUNCTION_NAME$2 && value.name !== name)) {
646               createNonEnumerableProperty$9(value, 'name', name);
647             }
648             state = enforceInternalState$1(value);
649             if (!state.source) {
650               state.source = TEMPLATE.join(typeof name == 'string' ? name : '');
651             }
652           }
653           if (O === global$13) {
654             if (simple) O[key] = value;
655             else setGlobal$1(key, value);
656             return;
657           } else if (!unsafe) {
658             delete O[key];
659           } else if (!noTargetGet && O[key]) {
660             simple = true;
661           }
662           if (simple) O[key] = value;
663           else createNonEnumerableProperty$9(O, key, value);
664         // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
665         })(Function.prototype, 'toString', function toString() {
666           return isCallable$j(this) && getInternalState$7(this).source || inspectSource$2(this);
667         });
668
669         var objectGetOwnPropertyNames = {};
670
671         var ceil$1 = Math.ceil;
672         var floor$8 = Math.floor;
673
674         // `ToIntegerOrInfinity` abstract operation
675         // https://tc39.es/ecma262/#sec-tointegerorinfinity
676         var toIntegerOrInfinity$b = function (argument) {
677           var number = +argument;
678           // eslint-disable-next-line no-self-compare -- safe
679           return number !== number || number === 0 ? 0 : (number > 0 ? floor$8 : ceil$1)(number);
680         };
681
682         var toIntegerOrInfinity$a = toIntegerOrInfinity$b;
683
684         var max$4 = Math.max;
685         var min$9 = Math.min;
686
687         // Helper for a popular repeating case of the spec:
688         // Let integer be ? ToInteger(index).
689         // If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length).
690         var toAbsoluteIndex$8 = function (index, length) {
691           var integer = toIntegerOrInfinity$a(index);
692           return integer < 0 ? max$4(integer + length, 0) : min$9(integer, length);
693         };
694
695         var toIntegerOrInfinity$9 = toIntegerOrInfinity$b;
696
697         var min$8 = Math.min;
698
699         // `ToLength` abstract operation
700         // https://tc39.es/ecma262/#sec-tolength
701         var toLength$c = function (argument) {
702           return argument > 0 ? min$8(toIntegerOrInfinity$9(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991
703         };
704
705         var toLength$b = toLength$c;
706
707         // `LengthOfArrayLike` abstract operation
708         // https://tc39.es/ecma262/#sec-lengthofarraylike
709         var lengthOfArrayLike$g = function (obj) {
710           return toLength$b(obj.length);
711         };
712
713         var toIndexedObject$a = toIndexedObject$c;
714         var toAbsoluteIndex$7 = toAbsoluteIndex$8;
715         var lengthOfArrayLike$f = lengthOfArrayLike$g;
716
717         // `Array.prototype.{ indexOf, includes }` methods implementation
718         var createMethod$6 = function (IS_INCLUDES) {
719           return function ($this, el, fromIndex) {
720             var O = toIndexedObject$a($this);
721             var length = lengthOfArrayLike$f(O);
722             var index = toAbsoluteIndex$7(fromIndex, length);
723             var value;
724             // Array#includes uses SameValueZero equality algorithm
725             // eslint-disable-next-line no-self-compare -- NaN check
726             if (IS_INCLUDES && el != el) while (length > index) {
727               value = O[index++];
728               // eslint-disable-next-line no-self-compare -- NaN check
729               if (value != value) return true;
730             // Array#indexOf ignores holes, Array#includes - not
731             } else for (;length > index; index++) {
732               if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
733             } return !IS_INCLUDES && -1;
734           };
735         };
736
737         var arrayIncludes = {
738           // `Array.prototype.includes` method
739           // https://tc39.es/ecma262/#sec-array.prototype.includes
740           includes: createMethod$6(true),
741           // `Array.prototype.indexOf` method
742           // https://tc39.es/ecma262/#sec-array.prototype.indexof
743           indexOf: createMethod$6(false)
744         };
745
746         var uncurryThis$Q = functionUncurryThis;
747         var hasOwn$g = hasOwnProperty_1;
748         var toIndexedObject$9 = toIndexedObject$c;
749         var indexOf$1 = arrayIncludes.indexOf;
750         var hiddenKeys$4 = hiddenKeys$6;
751
752         var push$a = uncurryThis$Q([].push);
753
754         var objectKeysInternal = function (object, names) {
755           var O = toIndexedObject$9(object);
756           var i = 0;
757           var result = [];
758           var key;
759           for (key in O) !hasOwn$g(hiddenKeys$4, key) && hasOwn$g(O, key) && push$a(result, key);
760           // Don't enum bug & hidden keys
761           while (names.length > i) if (hasOwn$g(O, key = names[i++])) {
762             ~indexOf$1(result, key) || push$a(result, key);
763           }
764           return result;
765         };
766
767         // IE8- don't enum bug keys
768         var enumBugKeys$3 = [
769           'constructor',
770           'hasOwnProperty',
771           'isPrototypeOf',
772           'propertyIsEnumerable',
773           'toLocaleString',
774           'toString',
775           'valueOf'
776         ];
777
778         var internalObjectKeys$1 = objectKeysInternal;
779         var enumBugKeys$2 = enumBugKeys$3;
780
781         var hiddenKeys$3 = enumBugKeys$2.concat('length', 'prototype');
782
783         // `Object.getOwnPropertyNames` method
784         // https://tc39.es/ecma262/#sec-object.getownpropertynames
785         // eslint-disable-next-line es/no-object-getownpropertynames -- safe
786         objectGetOwnPropertyNames.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
787           return internalObjectKeys$1(O, hiddenKeys$3);
788         };
789
790         var objectGetOwnPropertySymbols = {};
791
792         // eslint-disable-next-line es/no-object-getownpropertysymbols -- safe
793         objectGetOwnPropertySymbols.f = Object.getOwnPropertySymbols;
794
795         var getBuiltIn$8 = getBuiltIn$b;
796         var uncurryThis$P = functionUncurryThis;
797         var getOwnPropertyNamesModule$2 = objectGetOwnPropertyNames;
798         var getOwnPropertySymbolsModule$2 = objectGetOwnPropertySymbols;
799         var anObject$l = anObject$n;
800
801         var concat$3 = uncurryThis$P([].concat);
802
803         // all object keys, includes non-enumerable and symbols
804         var ownKeys$1 = getBuiltIn$8('Reflect', 'ownKeys') || function ownKeys(it) {
805           var keys = getOwnPropertyNamesModule$2.f(anObject$l(it));
806           var getOwnPropertySymbols = getOwnPropertySymbolsModule$2.f;
807           return getOwnPropertySymbols ? concat$3(keys, getOwnPropertySymbols(it)) : keys;
808         };
809
810         var hasOwn$f = hasOwnProperty_1;
811         var ownKeys = ownKeys$1;
812         var getOwnPropertyDescriptorModule$3 = objectGetOwnPropertyDescriptor;
813         var definePropertyModule$6 = objectDefineProperty;
814
815         var copyConstructorProperties$2 = function (target, source) {
816           var keys = ownKeys(source);
817           var defineProperty = definePropertyModule$6.f;
818           var getOwnPropertyDescriptor = getOwnPropertyDescriptorModule$3.f;
819           for (var i = 0; i < keys.length; i++) {
820             var key = keys[i];
821             if (!hasOwn$f(target, key)) defineProperty(target, key, getOwnPropertyDescriptor(source, key));
822           }
823         };
824
825         var fails$N = fails$S;
826         var isCallable$i = isCallable$r;
827
828         var replacement = /#|\.prototype\./;
829
830         var isForced$5 = function (feature, detection) {
831           var value = data[normalize$1(feature)];
832           return value == POLYFILL ? true
833             : value == NATIVE ? false
834             : isCallable$i(detection) ? fails$N(detection)
835             : !!detection;
836         };
837
838         var normalize$1 = isForced$5.normalize = function (string) {
839           return String(string).replace(replacement, '.').toLowerCase();
840         };
841
842         var data = isForced$5.data = {};
843         var NATIVE = isForced$5.NATIVE = 'N';
844         var POLYFILL = isForced$5.POLYFILL = 'P';
845
846         var isForced_1 = isForced$5;
847
848         var global$12 = global$1m;
849         var getOwnPropertyDescriptor$4 = objectGetOwnPropertyDescriptor.f;
850         var createNonEnumerableProperty$8 = createNonEnumerableProperty$b;
851         var redefine$g = redefine$h.exports;
852         var setGlobal = setGlobal$3;
853         var copyConstructorProperties$1 = copyConstructorProperties$2;
854         var isForced$4 = isForced_1;
855
856         /*
857           options.target      - name of the target object
858           options.global      - target is the global object
859           options.stat        - export as static methods of target
860           options.proto       - export as prototype methods of target
861           options.real        - real prototype method for the `pure` version
862           options.forced      - export even if the native feature is available
863           options.bind        - bind methods to the target, required for the `pure` version
864           options.wrap        - wrap constructors to preventing global pollution, required for the `pure` version
865           options.unsafe      - use the simple assignment of property instead of delete + defineProperty
866           options.sham        - add a flag to not completely full polyfills
867           options.enumerable  - export as enumerable property
868           options.noTargetGet - prevent calling a getter on target
869           options.name        - the .name of the function if it does not match the key
870         */
871         var _export = function (options, source) {
872           var TARGET = options.target;
873           var GLOBAL = options.global;
874           var STATIC = options.stat;
875           var FORCED, target, key, targetProperty, sourceProperty, descriptor;
876           if (GLOBAL) {
877             target = global$12;
878           } else if (STATIC) {
879             target = global$12[TARGET] || setGlobal(TARGET, {});
880           } else {
881             target = (global$12[TARGET] || {}).prototype;
882           }
883           if (target) for (key in source) {
884             sourceProperty = source[key];
885             if (options.noTargetGet) {
886               descriptor = getOwnPropertyDescriptor$4(target, key);
887               targetProperty = descriptor && descriptor.value;
888             } else targetProperty = target[key];
889             FORCED = isForced$4(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced);
890             // contained in target
891             if (!FORCED && targetProperty !== undefined) {
892               if (typeof sourceProperty == typeof targetProperty) continue;
893               copyConstructorProperties$1(sourceProperty, targetProperty);
894             }
895             // add a flag to not completely full polyfills
896             if (options.sham || (targetProperty && targetProperty.sham)) {
897               createNonEnumerableProperty$8(sourceProperty, 'sham', true);
898             }
899             // extend global
900             redefine$g(target, key, sourceProperty, options);
901           }
902         };
903
904         var $$1e = _export;
905         var global$11 = global$1m;
906         var uncurryThis$O = functionUncurryThis;
907
908         var Date$1 = global$11.Date;
909         var getTime$2 = uncurryThis$O(Date$1.prototype.getTime);
910
911         // `Date.now` method
912         // https://tc39.es/ecma262/#sec-date.now
913         $$1e({ target: 'Date', stat: true }, {
914           now: function now() {
915             return getTime$2(new Date$1());
916           }
917         });
918
919         var uncurryThis$N = functionUncurryThis;
920         var redefine$f = redefine$h.exports;
921
922         var DatePrototype$1 = Date.prototype;
923         var INVALID_DATE = 'Invalid Date';
924         var TO_STRING$1 = 'toString';
925         var un$DateToString = uncurryThis$N(DatePrototype$1[TO_STRING$1]);
926         var getTime$1 = uncurryThis$N(DatePrototype$1.getTime);
927
928         // `Date.prototype.toString` method
929         // https://tc39.es/ecma262/#sec-date.prototype.tostring
930         if (String(new Date(NaN)) != INVALID_DATE) {
931           redefine$f(DatePrototype$1, TO_STRING$1, function toString() {
932             var value = getTime$1(this);
933             // eslint-disable-next-line no-self-compare -- NaN check
934             return value === value ? un$DateToString(this) : INVALID_DATE;
935           });
936         }
937
938         function _typeof(obj) {
939           "@babel/helpers - typeof";
940
941           if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
942             _typeof = function (obj) {
943               return typeof obj;
944             };
945           } else {
946             _typeof = function (obj) {
947               return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
948             };
949           }
950
951           return _typeof(obj);
952         }
953
954         function _classCallCheck$1(instance, Constructor) {
955           if (!(instance instanceof Constructor)) {
956             throw new TypeError("Cannot call a class as a function");
957           }
958         }
959
960         function _defineProperties$1(target, props) {
961           for (var i = 0; i < props.length; i++) {
962             var descriptor = props[i];
963             descriptor.enumerable = descriptor.enumerable || false;
964             descriptor.configurable = true;
965             if ("value" in descriptor) descriptor.writable = true;
966             Object.defineProperty(target, descriptor.key, descriptor);
967           }
968         }
969
970         function _createClass$1(Constructor, protoProps, staticProps) {
971           if (protoProps) _defineProperties$1(Constructor.prototype, protoProps);
972           if (staticProps) _defineProperties$1(Constructor, staticProps);
973           return Constructor;
974         }
975
976         function _defineProperty(obj, key, value) {
977           if (key in obj) {
978             Object.defineProperty(obj, key, {
979               value: value,
980               enumerable: true,
981               configurable: true,
982               writable: true
983             });
984           } else {
985             obj[key] = value;
986           }
987
988           return obj;
989         }
990
991         function _slicedToArray(arr, i) {
992           return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
993         }
994
995         function _toConsumableArray(arr) {
996           return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
997         }
998
999         function _arrayWithoutHoles(arr) {
1000           if (Array.isArray(arr)) return _arrayLikeToArray(arr);
1001         }
1002
1003         function _arrayWithHoles(arr) {
1004           if (Array.isArray(arr)) return arr;
1005         }
1006
1007         function _iterableToArray(iter) {
1008           if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
1009         }
1010
1011         function _iterableToArrayLimit(arr, i) {
1012           var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
1013
1014           if (_i == null) return;
1015           var _arr = [];
1016           var _n = true;
1017           var _d = false;
1018
1019           var _s, _e;
1020
1021           try {
1022             for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
1023               _arr.push(_s.value);
1024
1025               if (i && _arr.length === i) break;
1026             }
1027           } catch (err) {
1028             _d = true;
1029             _e = err;
1030           } finally {
1031             try {
1032               if (!_n && _i["return"] != null) _i["return"]();
1033             } finally {
1034               if (_d) throw _e;
1035             }
1036           }
1037
1038           return _arr;
1039         }
1040
1041         function _unsupportedIterableToArray(o, minLen) {
1042           if (!o) return;
1043           if (typeof o === "string") return _arrayLikeToArray(o, minLen);
1044           var n = Object.prototype.toString.call(o).slice(8, -1);
1045           if (n === "Object" && o.constructor) n = o.constructor.name;
1046           if (n === "Map" || n === "Set") return Array.from(o);
1047           if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
1048         }
1049
1050         function _arrayLikeToArray(arr, len) {
1051           if (len == null || len > arr.length) len = arr.length;
1052
1053           for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
1054
1055           return arr2;
1056         }
1057
1058         function _nonIterableSpread() {
1059           throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
1060         }
1061
1062         function _nonIterableRest() {
1063           throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
1064         }
1065
1066         function _createForOfIteratorHelper(o, allowArrayLike) {
1067           var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
1068
1069           if (!it) {
1070             if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
1071               if (it) o = it;
1072               var i = 0;
1073
1074               var F = function () {};
1075
1076               return {
1077                 s: F,
1078                 n: function () {
1079                   if (i >= o.length) return {
1080                     done: true
1081                   };
1082                   return {
1083                     done: false,
1084                     value: o[i++]
1085                   };
1086                 },
1087                 e: function (e) {
1088                   throw e;
1089                 },
1090                 f: F
1091               };
1092             }
1093
1094             throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
1095           }
1096
1097           var normalCompletion = true,
1098               didErr = false,
1099               err;
1100           return {
1101             s: function () {
1102               it = it.call(o);
1103             },
1104             n: function () {
1105               var step = it.next();
1106               normalCompletion = step.done;
1107               return step;
1108             },
1109             e: function (e) {
1110               didErr = true;
1111               err = e;
1112             },
1113             f: function () {
1114               try {
1115                 if (!normalCompletion && it.return != null) it.return();
1116               } finally {
1117                 if (didErr) throw err;
1118               }
1119             }
1120           };
1121         }
1122
1123         var $$1d = _export;
1124         var global$10 = global$1m;
1125
1126         // `globalThis` object
1127         // https://tc39.es/ecma262/#sec-globalthis
1128         $$1d({ global: true }, {
1129           globalThis: global$10
1130         });
1131
1132         var global$$ = global$1m;
1133
1134         var path$1 = global$$;
1135
1136         var wellKnownSymbolWrapped = {};
1137
1138         var wellKnownSymbol$r = wellKnownSymbol$t;
1139
1140         wellKnownSymbolWrapped.f = wellKnownSymbol$r;
1141
1142         var path = path$1;
1143         var hasOwn$e = hasOwnProperty_1;
1144         var wrappedWellKnownSymbolModule$1 = wellKnownSymbolWrapped;
1145         var defineProperty$a = objectDefineProperty.f;
1146
1147         var defineWellKnownSymbol$4 = function (NAME) {
1148           var Symbol = path.Symbol || (path.Symbol = {});
1149           if (!hasOwn$e(Symbol, NAME)) defineProperty$a(Symbol, NAME, {
1150             value: wrappedWellKnownSymbolModule$1.f(NAME)
1151           });
1152         };
1153
1154         var defineWellKnownSymbol$3 = defineWellKnownSymbol$4;
1155
1156         // `Symbol.iterator` well-known symbol
1157         // https://tc39.es/ecma262/#sec-symbol.iterator
1158         defineWellKnownSymbol$3('iterator');
1159
1160         var internalObjectKeys = objectKeysInternal;
1161         var enumBugKeys$1 = enumBugKeys$3;
1162
1163         // `Object.keys` method
1164         // https://tc39.es/ecma262/#sec-object.keys
1165         // eslint-disable-next-line es/no-object-keys -- safe
1166         var objectKeys$4 = Object.keys || function keys(O) {
1167           return internalObjectKeys(O, enumBugKeys$1);
1168         };
1169
1170         var DESCRIPTORS$i = descriptors;
1171         var definePropertyModule$5 = objectDefineProperty;
1172         var anObject$k = anObject$n;
1173         var toIndexedObject$8 = toIndexedObject$c;
1174         var objectKeys$3 = objectKeys$4;
1175
1176         // `Object.defineProperties` method
1177         // https://tc39.es/ecma262/#sec-object.defineproperties
1178         // eslint-disable-next-line es/no-object-defineproperties -- safe
1179         var objectDefineProperties = DESCRIPTORS$i ? Object.defineProperties : function defineProperties(O, Properties) {
1180           anObject$k(O);
1181           var props = toIndexedObject$8(Properties);
1182           var keys = objectKeys$3(Properties);
1183           var length = keys.length;
1184           var index = 0;
1185           var key;
1186           while (length > index) definePropertyModule$5.f(O, key = keys[index++], props[key]);
1187           return O;
1188         };
1189
1190         var getBuiltIn$7 = getBuiltIn$b;
1191
1192         var html$2 = getBuiltIn$7('document', 'documentElement');
1193
1194         /* global ActiveXObject -- old IE, WSH */
1195
1196         var anObject$j = anObject$n;
1197         var defineProperties$2 = objectDefineProperties;
1198         var enumBugKeys = enumBugKeys$3;
1199         var hiddenKeys$2 = hiddenKeys$6;
1200         var html$1 = html$2;
1201         var documentCreateElement$1 = documentCreateElement$2;
1202         var sharedKey$2 = sharedKey$4;
1203
1204         var GT = '>';
1205         var LT = '<';
1206         var PROTOTYPE$2 = 'prototype';
1207         var SCRIPT = 'script';
1208         var IE_PROTO$1 = sharedKey$2('IE_PROTO');
1209
1210         var EmptyConstructor = function () { /* empty */ };
1211
1212         var scriptTag = function (content) {
1213           return LT + SCRIPT + GT + content + LT + '/' + SCRIPT + GT;
1214         };
1215
1216         // Create object with fake `null` prototype: use ActiveX Object with cleared prototype
1217         var NullProtoObjectViaActiveX = function (activeXDocument) {
1218           activeXDocument.write(scriptTag(''));
1219           activeXDocument.close();
1220           var temp = activeXDocument.parentWindow.Object;
1221           activeXDocument = null; // avoid memory leak
1222           return temp;
1223         };
1224
1225         // Create object with fake `null` prototype: use iframe Object with cleared prototype
1226         var NullProtoObjectViaIFrame = function () {
1227           // Thrash, waste and sodomy: IE GC bug
1228           var iframe = documentCreateElement$1('iframe');
1229           var JS = 'java' + SCRIPT + ':';
1230           var iframeDocument;
1231           iframe.style.display = 'none';
1232           html$1.appendChild(iframe);
1233           // https://github.com/zloirock/core-js/issues/475
1234           iframe.src = String(JS);
1235           iframeDocument = iframe.contentWindow.document;
1236           iframeDocument.open();
1237           iframeDocument.write(scriptTag('document.F=Object'));
1238           iframeDocument.close();
1239           return iframeDocument.F;
1240         };
1241
1242         // Check for document.domain and active x support
1243         // No need to use active x approach when document.domain is not set
1244         // see https://github.com/es-shims/es5-shim/issues/150
1245         // variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346
1246         // avoid IE GC bug
1247         var activeXDocument;
1248         var NullProtoObject = function () {
1249           try {
1250             activeXDocument = new ActiveXObject('htmlfile');
1251           } catch (error) { /* ignore */ }
1252           NullProtoObject = typeof document != 'undefined'
1253             ? document.domain && activeXDocument
1254               ? NullProtoObjectViaActiveX(activeXDocument) // old IE
1255               : NullProtoObjectViaIFrame()
1256             : NullProtoObjectViaActiveX(activeXDocument); // WSH
1257           var length = enumBugKeys.length;
1258           while (length--) delete NullProtoObject[PROTOTYPE$2][enumBugKeys[length]];
1259           return NullProtoObject();
1260         };
1261
1262         hiddenKeys$2[IE_PROTO$1] = true;
1263
1264         // `Object.create` method
1265         // https://tc39.es/ecma262/#sec-object.create
1266         var objectCreate = Object.create || function create(O, Properties) {
1267           var result;
1268           if (O !== null) {
1269             EmptyConstructor[PROTOTYPE$2] = anObject$j(O);
1270             result = new EmptyConstructor();
1271             EmptyConstructor[PROTOTYPE$2] = null;
1272             // add "__proto__" for Object.getPrototypeOf polyfill
1273             result[IE_PROTO$1] = O;
1274           } else result = NullProtoObject();
1275           return Properties === undefined ? result : defineProperties$2(result, Properties);
1276         };
1277
1278         var wellKnownSymbol$q = wellKnownSymbol$t;
1279         var create$a = objectCreate;
1280         var definePropertyModule$4 = objectDefineProperty;
1281
1282         var UNSCOPABLES = wellKnownSymbol$q('unscopables');
1283         var ArrayPrototype$1 = Array.prototype;
1284
1285         // Array.prototype[@@unscopables]
1286         // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
1287         if (ArrayPrototype$1[UNSCOPABLES] == undefined) {
1288           definePropertyModule$4.f(ArrayPrototype$1, UNSCOPABLES, {
1289             configurable: true,
1290             value: create$a(null)
1291           });
1292         }
1293
1294         // add a key to Array.prototype[@@unscopables]
1295         var addToUnscopables$6 = function (key) {
1296           ArrayPrototype$1[UNSCOPABLES][key] = true;
1297         };
1298
1299         var iterators = {};
1300
1301         var fails$M = fails$S;
1302
1303         var correctPrototypeGetter = !fails$M(function () {
1304           function F() { /* empty */ }
1305           F.prototype.constructor = null;
1306           // eslint-disable-next-line es/no-object-getprototypeof -- required for testing
1307           return Object.getPrototypeOf(new F()) !== F.prototype;
1308         });
1309
1310         var global$_ = global$1m;
1311         var hasOwn$d = hasOwnProperty_1;
1312         var isCallable$h = isCallable$r;
1313         var toObject$h = toObject$j;
1314         var sharedKey$1 = sharedKey$4;
1315         var CORRECT_PROTOTYPE_GETTER$1 = correctPrototypeGetter;
1316
1317         var IE_PROTO = sharedKey$1('IE_PROTO');
1318         var Object$2 = global$_.Object;
1319         var ObjectPrototype$4 = Object$2.prototype;
1320
1321         // `Object.getPrototypeOf` method
1322         // https://tc39.es/ecma262/#sec-object.getprototypeof
1323         var objectGetPrototypeOf = CORRECT_PROTOTYPE_GETTER$1 ? Object$2.getPrototypeOf : function (O) {
1324           var object = toObject$h(O);
1325           if (hasOwn$d(object, IE_PROTO)) return object[IE_PROTO];
1326           var constructor = object.constructor;
1327           if (isCallable$h(constructor) && object instanceof constructor) {
1328             return constructor.prototype;
1329           } return object instanceof Object$2 ? ObjectPrototype$4 : null;
1330         };
1331
1332         var fails$L = fails$S;
1333         var isCallable$g = isCallable$r;
1334         var getPrototypeOf$4 = objectGetPrototypeOf;
1335         var redefine$e = redefine$h.exports;
1336         var wellKnownSymbol$p = wellKnownSymbol$t;
1337
1338         var ITERATOR$a = wellKnownSymbol$p('iterator');
1339         var BUGGY_SAFARI_ITERATORS$1 = false;
1340
1341         // `%IteratorPrototype%` object
1342         // https://tc39.es/ecma262/#sec-%iteratorprototype%-object
1343         var IteratorPrototype$2, PrototypeOfArrayIteratorPrototype, arrayIterator;
1344
1345         /* eslint-disable es/no-array-prototype-keys -- safe */
1346         if ([].keys) {
1347           arrayIterator = [].keys();
1348           // Safari 8 has buggy iterators w/o `next`
1349           if (!('next' in arrayIterator)) BUGGY_SAFARI_ITERATORS$1 = true;
1350           else {
1351             PrototypeOfArrayIteratorPrototype = getPrototypeOf$4(getPrototypeOf$4(arrayIterator));
1352             if (PrototypeOfArrayIteratorPrototype !== Object.prototype) IteratorPrototype$2 = PrototypeOfArrayIteratorPrototype;
1353           }
1354         }
1355
1356         var NEW_ITERATOR_PROTOTYPE = IteratorPrototype$2 == undefined || fails$L(function () {
1357           var test = {};
1358           // FF44- legacy iterators case
1359           return IteratorPrototype$2[ITERATOR$a].call(test) !== test;
1360         });
1361
1362         if (NEW_ITERATOR_PROTOTYPE) IteratorPrototype$2 = {};
1363
1364         // `%IteratorPrototype%[@@iterator]()` method
1365         // https://tc39.es/ecma262/#sec-%iteratorprototype%-@@iterator
1366         if (!isCallable$g(IteratorPrototype$2[ITERATOR$a])) {
1367           redefine$e(IteratorPrototype$2, ITERATOR$a, function () {
1368             return this;
1369           });
1370         }
1371
1372         var iteratorsCore = {
1373           IteratorPrototype: IteratorPrototype$2,
1374           BUGGY_SAFARI_ITERATORS: BUGGY_SAFARI_ITERATORS$1
1375         };
1376
1377         var defineProperty$9 = objectDefineProperty.f;
1378         var hasOwn$c = hasOwnProperty_1;
1379         var wellKnownSymbol$o = wellKnownSymbol$t;
1380
1381         var TO_STRING_TAG$4 = wellKnownSymbol$o('toStringTag');
1382
1383         var setToStringTag$a = function (it, TAG, STATIC) {
1384           if (it && !hasOwn$c(it = STATIC ? it : it.prototype, TO_STRING_TAG$4)) {
1385             defineProperty$9(it, TO_STRING_TAG$4, { configurable: true, value: TAG });
1386           }
1387         };
1388
1389         var IteratorPrototype$1 = iteratorsCore.IteratorPrototype;
1390         var create$9 = objectCreate;
1391         var createPropertyDescriptor$4 = createPropertyDescriptor$7;
1392         var setToStringTag$9 = setToStringTag$a;
1393         var Iterators$4 = iterators;
1394
1395         var returnThis$1 = function () { return this; };
1396
1397         var createIteratorConstructor$2 = function (IteratorConstructor, NAME, next) {
1398           var TO_STRING_TAG = NAME + ' Iterator';
1399           IteratorConstructor.prototype = create$9(IteratorPrototype$1, { next: createPropertyDescriptor$4(1, next) });
1400           setToStringTag$9(IteratorConstructor, TO_STRING_TAG, false);
1401           Iterators$4[TO_STRING_TAG] = returnThis$1;
1402           return IteratorConstructor;
1403         };
1404
1405         var global$Z = global$1m;
1406         var isCallable$f = isCallable$r;
1407
1408         var String$4 = global$Z.String;
1409         var TypeError$h = global$Z.TypeError;
1410
1411         var aPossiblePrototype$1 = function (argument) {
1412           if (typeof argument == 'object' || isCallable$f(argument)) return argument;
1413           throw TypeError$h("Can't set " + String$4(argument) + ' as a prototype');
1414         };
1415
1416         /* eslint-disable no-proto -- safe */
1417
1418         var uncurryThis$M = functionUncurryThis;
1419         var anObject$i = anObject$n;
1420         var aPossiblePrototype = aPossiblePrototype$1;
1421
1422         // `Object.setPrototypeOf` method
1423         // https://tc39.es/ecma262/#sec-object.setprototypeof
1424         // Works with __proto__ only. Old v8 can't work with null proto objects.
1425         // eslint-disable-next-line es/no-object-setprototypeof -- safe
1426         var objectSetPrototypeOf = Object.setPrototypeOf || ('__proto__' in {} ? function () {
1427           var CORRECT_SETTER = false;
1428           var test = {};
1429           var setter;
1430           try {
1431             // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
1432             setter = uncurryThis$M(Object.getOwnPropertyDescriptor(Object.prototype, '__proto__').set);
1433             setter(test, []);
1434             CORRECT_SETTER = test instanceof Array;
1435           } catch (error) { /* empty */ }
1436           return function setPrototypeOf(O, proto) {
1437             anObject$i(O);
1438             aPossiblePrototype(proto);
1439             if (CORRECT_SETTER) setter(O, proto);
1440             else O.__proto__ = proto;
1441             return O;
1442           };
1443         }() : undefined);
1444
1445         var $$1c = _export;
1446         var call$l = functionCall;
1447         var FunctionName$1 = functionName;
1448         var isCallable$e = isCallable$r;
1449         var createIteratorConstructor$1 = createIteratorConstructor$2;
1450         var getPrototypeOf$3 = objectGetPrototypeOf;
1451         var setPrototypeOf$6 = objectSetPrototypeOf;
1452         var setToStringTag$8 = setToStringTag$a;
1453         var createNonEnumerableProperty$7 = createNonEnumerableProperty$b;
1454         var redefine$d = redefine$h.exports;
1455         var wellKnownSymbol$n = wellKnownSymbol$t;
1456         var Iterators$3 = iterators;
1457         var IteratorsCore = iteratorsCore;
1458
1459         var PROPER_FUNCTION_NAME$4 = FunctionName$1.PROPER;
1460         var CONFIGURABLE_FUNCTION_NAME$1 = FunctionName$1.CONFIGURABLE;
1461         var IteratorPrototype = IteratorsCore.IteratorPrototype;
1462         var BUGGY_SAFARI_ITERATORS = IteratorsCore.BUGGY_SAFARI_ITERATORS;
1463         var ITERATOR$9 = wellKnownSymbol$n('iterator');
1464         var KEYS = 'keys';
1465         var VALUES = 'values';
1466         var ENTRIES = 'entries';
1467
1468         var returnThis = function () { return this; };
1469
1470         var defineIterator$3 = function (Iterable, NAME, IteratorConstructor, next, DEFAULT, IS_SET, FORCED) {
1471           createIteratorConstructor$1(IteratorConstructor, NAME, next);
1472
1473           var getIterationMethod = function (KIND) {
1474             if (KIND === DEFAULT && defaultIterator) return defaultIterator;
1475             if (!BUGGY_SAFARI_ITERATORS && KIND in IterablePrototype) return IterablePrototype[KIND];
1476             switch (KIND) {
1477               case KEYS: return function keys() { return new IteratorConstructor(this, KIND); };
1478               case VALUES: return function values() { return new IteratorConstructor(this, KIND); };
1479               case ENTRIES: return function entries() { return new IteratorConstructor(this, KIND); };
1480             } return function () { return new IteratorConstructor(this); };
1481           };
1482
1483           var TO_STRING_TAG = NAME + ' Iterator';
1484           var INCORRECT_VALUES_NAME = false;
1485           var IterablePrototype = Iterable.prototype;
1486           var nativeIterator = IterablePrototype[ITERATOR$9]
1487             || IterablePrototype['@@iterator']
1488             || DEFAULT && IterablePrototype[DEFAULT];
1489           var defaultIterator = !BUGGY_SAFARI_ITERATORS && nativeIterator || getIterationMethod(DEFAULT);
1490           var anyNativeIterator = NAME == 'Array' ? IterablePrototype.entries || nativeIterator : nativeIterator;
1491           var CurrentIteratorPrototype, methods, KEY;
1492
1493           // fix native
1494           if (anyNativeIterator) {
1495             CurrentIteratorPrototype = getPrototypeOf$3(anyNativeIterator.call(new Iterable()));
1496             if (CurrentIteratorPrototype !== Object.prototype && CurrentIteratorPrototype.next) {
1497               if (getPrototypeOf$3(CurrentIteratorPrototype) !== IteratorPrototype) {
1498                 if (setPrototypeOf$6) {
1499                   setPrototypeOf$6(CurrentIteratorPrototype, IteratorPrototype);
1500                 } else if (!isCallable$e(CurrentIteratorPrototype[ITERATOR$9])) {
1501                   redefine$d(CurrentIteratorPrototype, ITERATOR$9, returnThis);
1502                 }
1503               }
1504               // Set @@toStringTag to native iterators
1505               setToStringTag$8(CurrentIteratorPrototype, TO_STRING_TAG, true);
1506             }
1507           }
1508
1509           // fix Array.prototype.{ values, @@iterator }.name in V8 / FF
1510           if (PROPER_FUNCTION_NAME$4 && DEFAULT == VALUES && nativeIterator && nativeIterator.name !== VALUES) {
1511             if (CONFIGURABLE_FUNCTION_NAME$1) {
1512               createNonEnumerableProperty$7(IterablePrototype, 'name', VALUES);
1513             } else {
1514               INCORRECT_VALUES_NAME = true;
1515               defaultIterator = function values() { return call$l(nativeIterator, this); };
1516             }
1517           }
1518
1519           // export additional methods
1520           if (DEFAULT) {
1521             methods = {
1522               values: getIterationMethod(VALUES),
1523               keys: IS_SET ? defaultIterator : getIterationMethod(KEYS),
1524               entries: getIterationMethod(ENTRIES)
1525             };
1526             if (FORCED) for (KEY in methods) {
1527               if (BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME || !(KEY in IterablePrototype)) {
1528                 redefine$d(IterablePrototype, KEY, methods[KEY]);
1529               }
1530             } else $$1c({ target: NAME, proto: true, forced: BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME }, methods);
1531           }
1532
1533           // define iterator
1534           if (IterablePrototype[ITERATOR$9] !== defaultIterator) {
1535             redefine$d(IterablePrototype, ITERATOR$9, defaultIterator, { name: DEFAULT });
1536           }
1537           Iterators$3[NAME] = defaultIterator;
1538
1539           return methods;
1540         };
1541
1542         var toIndexedObject$7 = toIndexedObject$c;
1543         var addToUnscopables$5 = addToUnscopables$6;
1544         var Iterators$2 = iterators;
1545         var InternalStateModule$8 = internalState;
1546         var defineIterator$2 = defineIterator$3;
1547
1548         var ARRAY_ITERATOR = 'Array Iterator';
1549         var setInternalState$8 = InternalStateModule$8.set;
1550         var getInternalState$6 = InternalStateModule$8.getterFor(ARRAY_ITERATOR);
1551
1552         // `Array.prototype.entries` method
1553         // https://tc39.es/ecma262/#sec-array.prototype.entries
1554         // `Array.prototype.keys` method
1555         // https://tc39.es/ecma262/#sec-array.prototype.keys
1556         // `Array.prototype.values` method
1557         // https://tc39.es/ecma262/#sec-array.prototype.values
1558         // `Array.prototype[@@iterator]` method
1559         // https://tc39.es/ecma262/#sec-array.prototype-@@iterator
1560         // `CreateArrayIterator` internal method
1561         // https://tc39.es/ecma262/#sec-createarrayiterator
1562         var es_array_iterator = defineIterator$2(Array, 'Array', function (iterated, kind) {
1563           setInternalState$8(this, {
1564             type: ARRAY_ITERATOR,
1565             target: toIndexedObject$7(iterated), // target
1566             index: 0,                          // next index
1567             kind: kind                         // kind
1568           });
1569         // `%ArrayIteratorPrototype%.next` method
1570         // https://tc39.es/ecma262/#sec-%arrayiteratorprototype%.next
1571         }, function () {
1572           var state = getInternalState$6(this);
1573           var target = state.target;
1574           var kind = state.kind;
1575           var index = state.index++;
1576           if (!target || index >= target.length) {
1577             state.target = undefined;
1578             return { value: undefined, done: true };
1579           }
1580           if (kind == 'keys') return { value: index, done: false };
1581           if (kind == 'values') return { value: target[index], done: false };
1582           return { value: [index, target[index]], done: false };
1583         }, 'values');
1584
1585         // argumentsList[@@iterator] is %ArrayProto_values%
1586         // https://tc39.es/ecma262/#sec-createunmappedargumentsobject
1587         // https://tc39.es/ecma262/#sec-createmappedargumentsobject
1588         Iterators$2.Arguments = Iterators$2.Array;
1589
1590         // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
1591         addToUnscopables$5('keys');
1592         addToUnscopables$5('values');
1593         addToUnscopables$5('entries');
1594
1595         var wellKnownSymbol$m = wellKnownSymbol$t;
1596
1597         var TO_STRING_TAG$3 = wellKnownSymbol$m('toStringTag');
1598         var test$2 = {};
1599
1600         test$2[TO_STRING_TAG$3] = 'z';
1601
1602         var toStringTagSupport = String(test$2) === '[object z]';
1603
1604         var global$Y = global$1m;
1605         var TO_STRING_TAG_SUPPORT$2 = toStringTagSupport;
1606         var isCallable$d = isCallable$r;
1607         var classofRaw = classofRaw$1;
1608         var wellKnownSymbol$l = wellKnownSymbol$t;
1609
1610         var TO_STRING_TAG$2 = wellKnownSymbol$l('toStringTag');
1611         var Object$1 = global$Y.Object;
1612
1613         // ES3 wrong here
1614         var CORRECT_ARGUMENTS = classofRaw(function () { return arguments; }()) == 'Arguments';
1615
1616         // fallback for IE11 Script Access Denied error
1617         var tryGet = function (it, key) {
1618           try {
1619             return it[key];
1620           } catch (error) { /* empty */ }
1621         };
1622
1623         // getting tag from ES6+ `Object.prototype.toString`
1624         var classof$d = TO_STRING_TAG_SUPPORT$2 ? classofRaw : function (it) {
1625           var O, tag, result;
1626           return it === undefined ? 'Undefined' : it === null ? 'Null'
1627             // @@toStringTag case
1628             : typeof (tag = tryGet(O = Object$1(it), TO_STRING_TAG$2)) == 'string' ? tag
1629             // builtinTag case
1630             : CORRECT_ARGUMENTS ? classofRaw(O)
1631             // ES3 arguments fallback
1632             : (result = classofRaw(O)) == 'Object' && isCallable$d(O.callee) ? 'Arguments' : result;
1633         };
1634
1635         var TO_STRING_TAG_SUPPORT$1 = toStringTagSupport;
1636         var classof$c = classof$d;
1637
1638         // `Object.prototype.toString` method implementation
1639         // https://tc39.es/ecma262/#sec-object.prototype.tostring
1640         var objectToString$1 = TO_STRING_TAG_SUPPORT$1 ? {}.toString : function toString() {
1641           return '[object ' + classof$c(this) + ']';
1642         };
1643
1644         var TO_STRING_TAG_SUPPORT = toStringTagSupport;
1645         var redefine$c = redefine$h.exports;
1646         var toString$l = objectToString$1;
1647
1648         // `Object.prototype.toString` method
1649         // https://tc39.es/ecma262/#sec-object.prototype.tostring
1650         if (!TO_STRING_TAG_SUPPORT) {
1651           redefine$c(Object.prototype, 'toString', toString$l, { unsafe: true });
1652         }
1653
1654         var global$X = global$1m;
1655         var classof$b = classof$d;
1656
1657         var String$3 = global$X.String;
1658
1659         var toString$k = function (argument) {
1660           if (classof$b(argument) === 'Symbol') throw TypeError('Cannot convert a Symbol value to a string');
1661           return String$3(argument);
1662         };
1663
1664         var uncurryThis$L = functionUncurryThis;
1665         var toIntegerOrInfinity$8 = toIntegerOrInfinity$b;
1666         var toString$j = toString$k;
1667         var requireObjectCoercible$b = requireObjectCoercible$e;
1668
1669         var charAt$8 = uncurryThis$L(''.charAt);
1670         var charCodeAt$2 = uncurryThis$L(''.charCodeAt);
1671         var stringSlice$b = uncurryThis$L(''.slice);
1672
1673         var createMethod$5 = function (CONVERT_TO_STRING) {
1674           return function ($this, pos) {
1675             var S = toString$j(requireObjectCoercible$b($this));
1676             var position = toIntegerOrInfinity$8(pos);
1677             var size = S.length;
1678             var first, second;
1679             if (position < 0 || position >= size) return CONVERT_TO_STRING ? '' : undefined;
1680             first = charCodeAt$2(S, position);
1681             return first < 0xD800 || first > 0xDBFF || position + 1 === size
1682               || (second = charCodeAt$2(S, position + 1)) < 0xDC00 || second > 0xDFFF
1683                 ? CONVERT_TO_STRING
1684                   ? charAt$8(S, position)
1685                   : first
1686                 : CONVERT_TO_STRING
1687                   ? stringSlice$b(S, position, position + 2)
1688                   : (first - 0xD800 << 10) + (second - 0xDC00) + 0x10000;
1689           };
1690         };
1691
1692         var stringMultibyte = {
1693           // `String.prototype.codePointAt` method
1694           // https://tc39.es/ecma262/#sec-string.prototype.codepointat
1695           codeAt: createMethod$5(false),
1696           // `String.prototype.at` method
1697           // https://github.com/mathiasbynens/String.prototype.at
1698           charAt: createMethod$5(true)
1699         };
1700
1701         var charAt$7 = stringMultibyte.charAt;
1702         var toString$i = toString$k;
1703         var InternalStateModule$7 = internalState;
1704         var defineIterator$1 = defineIterator$3;
1705
1706         var STRING_ITERATOR = 'String Iterator';
1707         var setInternalState$7 = InternalStateModule$7.set;
1708         var getInternalState$5 = InternalStateModule$7.getterFor(STRING_ITERATOR);
1709
1710         // `String.prototype[@@iterator]` method
1711         // https://tc39.es/ecma262/#sec-string.prototype-@@iterator
1712         defineIterator$1(String, 'String', function (iterated) {
1713           setInternalState$7(this, {
1714             type: STRING_ITERATOR,
1715             string: toString$i(iterated),
1716             index: 0
1717           });
1718         // `%StringIteratorPrototype%.next` method
1719         // https://tc39.es/ecma262/#sec-%stringiteratorprototype%.next
1720         }, function next() {
1721           var state = getInternalState$5(this);
1722           var string = state.string;
1723           var index = state.index;
1724           var point;
1725           if (index >= string.length) return { value: undefined, done: true };
1726           point = charAt$7(string, index);
1727           state.index += point.length;
1728           return { value: point, done: false };
1729         });
1730
1731         // iterable DOM collections
1732         // flag - `iterable` interface - 'entries', 'keys', 'values', 'forEach' methods
1733         var domIterables = {
1734           CSSRuleList: 0,
1735           CSSStyleDeclaration: 0,
1736           CSSValueList: 0,
1737           ClientRectList: 0,
1738           DOMRectList: 0,
1739           DOMStringList: 0,
1740           DOMTokenList: 1,
1741           DataTransferItemList: 0,
1742           FileList: 0,
1743           HTMLAllCollection: 0,
1744           HTMLCollection: 0,
1745           HTMLFormElement: 0,
1746           HTMLSelectElement: 0,
1747           MediaList: 0,
1748           MimeTypeArray: 0,
1749           NamedNodeMap: 0,
1750           NodeList: 1,
1751           PaintRequestList: 0,
1752           Plugin: 0,
1753           PluginArray: 0,
1754           SVGLengthList: 0,
1755           SVGNumberList: 0,
1756           SVGPathSegList: 0,
1757           SVGPointList: 0,
1758           SVGStringList: 0,
1759           SVGTransformList: 0,
1760           SourceBufferList: 0,
1761           StyleSheetList: 0,
1762           TextTrackCueList: 0,
1763           TextTrackList: 0,
1764           TouchList: 0
1765         };
1766
1767         // in old WebKit versions, `element.classList` is not an instance of global `DOMTokenList`
1768         var documentCreateElement = documentCreateElement$2;
1769
1770         var classList$1 = documentCreateElement('span').classList;
1771         var DOMTokenListPrototype$2 = classList$1 && classList$1.constructor && classList$1.constructor.prototype;
1772
1773         var domTokenListPrototype = DOMTokenListPrototype$2 === Object.prototype ? undefined : DOMTokenListPrototype$2;
1774
1775         var global$W = global$1m;
1776         var DOMIterables$1 = domIterables;
1777         var DOMTokenListPrototype$1 = domTokenListPrototype;
1778         var ArrayIteratorMethods = es_array_iterator;
1779         var createNonEnumerableProperty$6 = createNonEnumerableProperty$b;
1780         var wellKnownSymbol$k = wellKnownSymbol$t;
1781
1782         var ITERATOR$8 = wellKnownSymbol$k('iterator');
1783         var TO_STRING_TAG$1 = wellKnownSymbol$k('toStringTag');
1784         var ArrayValues = ArrayIteratorMethods.values;
1785
1786         var handlePrototype$1 = function (CollectionPrototype, COLLECTION_NAME) {
1787           if (CollectionPrototype) {
1788             // some Chrome versions have non-configurable methods on DOMTokenList
1789             if (CollectionPrototype[ITERATOR$8] !== ArrayValues) try {
1790               createNonEnumerableProperty$6(CollectionPrototype, ITERATOR$8, ArrayValues);
1791             } catch (error) {
1792               CollectionPrototype[ITERATOR$8] = ArrayValues;
1793             }
1794             if (!CollectionPrototype[TO_STRING_TAG$1]) {
1795               createNonEnumerableProperty$6(CollectionPrototype, TO_STRING_TAG$1, COLLECTION_NAME);
1796             }
1797             if (DOMIterables$1[COLLECTION_NAME]) for (var METHOD_NAME in ArrayIteratorMethods) {
1798               // some Chrome versions have non-configurable methods on DOMTokenList
1799               if (CollectionPrototype[METHOD_NAME] !== ArrayIteratorMethods[METHOD_NAME]) try {
1800                 createNonEnumerableProperty$6(CollectionPrototype, METHOD_NAME, ArrayIteratorMethods[METHOD_NAME]);
1801               } catch (error) {
1802                 CollectionPrototype[METHOD_NAME] = ArrayIteratorMethods[METHOD_NAME];
1803               }
1804             }
1805           }
1806         };
1807
1808         for (var COLLECTION_NAME$1 in DOMIterables$1) {
1809           handlePrototype$1(global$W[COLLECTION_NAME$1] && global$W[COLLECTION_NAME$1].prototype, COLLECTION_NAME$1);
1810         }
1811
1812         handlePrototype$1(DOMTokenListPrototype$1, 'DOMTokenList');
1813
1814         var FunctionPrototype$1 = Function.prototype;
1815         var apply$9 = FunctionPrototype$1.apply;
1816         var bind$g = FunctionPrototype$1.bind;
1817         var call$k = FunctionPrototype$1.call;
1818
1819         // eslint-disable-next-line es/no-reflect -- safe
1820         var functionApply = typeof Reflect == 'object' && Reflect.apply || (bind$g ? call$k.bind(apply$9) : function () {
1821           return call$k.apply(apply$9, arguments);
1822         });
1823
1824         var classof$a = classofRaw$1;
1825
1826         // `IsArray` abstract operation
1827         // https://tc39.es/ecma262/#sec-isarray
1828         // eslint-disable-next-line es/no-array-isarray -- safe
1829         var isArray$8 = Array.isArray || function isArray(argument) {
1830           return classof$a(argument) == 'Array';
1831         };
1832
1833         var objectGetOwnPropertyNamesExternal = {};
1834
1835         var uncurryThis$K = functionUncurryThis;
1836
1837         var arraySlice$c = uncurryThis$K([].slice);
1838
1839         /* eslint-disable es/no-object-getownpropertynames -- safe */
1840
1841         var classof$9 = classofRaw$1;
1842         var toIndexedObject$6 = toIndexedObject$c;
1843         var $getOwnPropertyNames$1 = objectGetOwnPropertyNames.f;
1844         var arraySlice$b = arraySlice$c;
1845
1846         var windowNames = typeof window == 'object' && window && Object.getOwnPropertyNames
1847           ? Object.getOwnPropertyNames(window) : [];
1848
1849         var getWindowNames = function (it) {
1850           try {
1851             return $getOwnPropertyNames$1(it);
1852           } catch (error) {
1853             return arraySlice$b(windowNames);
1854           }
1855         };
1856
1857         // fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window
1858         objectGetOwnPropertyNamesExternal.f = function getOwnPropertyNames(it) {
1859           return windowNames && classof$9(it) == 'Window'
1860             ? getWindowNames(it)
1861             : $getOwnPropertyNames$1(toIndexedObject$6(it));
1862         };
1863
1864         var uncurryThis$J = functionUncurryThis;
1865         var aCallable$8 = aCallable$a;
1866
1867         var bind$f = uncurryThis$J(uncurryThis$J.bind);
1868
1869         // optional / simple context binding
1870         var functionBindContext = function (fn, that) {
1871           aCallable$8(fn);
1872           return that === undefined ? fn : bind$f ? bind$f(fn, that) : function (/* ...args */) {
1873             return fn.apply(that, arguments);
1874           };
1875         };
1876
1877         var uncurryThis$I = functionUncurryThis;
1878         var fails$K = fails$S;
1879         var isCallable$c = isCallable$r;
1880         var classof$8 = classof$d;
1881         var getBuiltIn$6 = getBuiltIn$b;
1882         var inspectSource$1 = inspectSource$4;
1883
1884         var noop$2 = function () { /* empty */ };
1885         var empty$1 = [];
1886         var construct$1 = getBuiltIn$6('Reflect', 'construct');
1887         var constructorRegExp = /^\s*(?:class|function)\b/;
1888         var exec$6 = uncurryThis$I(constructorRegExp.exec);
1889         var INCORRECT_TO_STRING = !constructorRegExp.exec(noop$2);
1890
1891         var isConstructorModern = function (argument) {
1892           if (!isCallable$c(argument)) return false;
1893           try {
1894             construct$1(noop$2, empty$1, argument);
1895             return true;
1896           } catch (error) {
1897             return false;
1898           }
1899         };
1900
1901         var isConstructorLegacy = function (argument) {
1902           if (!isCallable$c(argument)) return false;
1903           switch (classof$8(argument)) {
1904             case 'AsyncFunction':
1905             case 'GeneratorFunction':
1906             case 'AsyncGeneratorFunction': return false;
1907             // we can't check .prototype since constructors produced by .bind haven't it
1908           } return INCORRECT_TO_STRING || !!exec$6(constructorRegExp, inspectSource$1(argument));
1909         };
1910
1911         // `IsConstructor` abstract operation
1912         // https://tc39.es/ecma262/#sec-isconstructor
1913         var isConstructor$4 = !construct$1 || fails$K(function () {
1914           var called;
1915           return isConstructorModern(isConstructorModern.call)
1916             || !isConstructorModern(Object)
1917             || !isConstructorModern(function () { called = true; })
1918             || called;
1919         }) ? isConstructorLegacy : isConstructorModern;
1920
1921         var global$V = global$1m;
1922         var isArray$7 = isArray$8;
1923         var isConstructor$3 = isConstructor$4;
1924         var isObject$m = isObject$s;
1925         var wellKnownSymbol$j = wellKnownSymbol$t;
1926
1927         var SPECIES$6 = wellKnownSymbol$j('species');
1928         var Array$6 = global$V.Array;
1929
1930         // a part of `ArraySpeciesCreate` abstract operation
1931         // https://tc39.es/ecma262/#sec-arrayspeciescreate
1932         var arraySpeciesConstructor$1 = function (originalArray) {
1933           var C;
1934           if (isArray$7(originalArray)) {
1935             C = originalArray.constructor;
1936             // cross-realm fallback
1937             if (isConstructor$3(C) && (C === Array$6 || isArray$7(C.prototype))) C = undefined;
1938             else if (isObject$m(C)) {
1939               C = C[SPECIES$6];
1940               if (C === null) C = undefined;
1941             }
1942           } return C === undefined ? Array$6 : C;
1943         };
1944
1945         var arraySpeciesConstructor = arraySpeciesConstructor$1;
1946
1947         // `ArraySpeciesCreate` abstract operation
1948         // https://tc39.es/ecma262/#sec-arrayspeciescreate
1949         var arraySpeciesCreate$4 = function (originalArray, length) {
1950           return new (arraySpeciesConstructor(originalArray))(length === 0 ? 0 : length);
1951         };
1952
1953         var bind$e = functionBindContext;
1954         var uncurryThis$H = functionUncurryThis;
1955         var IndexedObject$3 = indexedObject;
1956         var toObject$g = toObject$j;
1957         var lengthOfArrayLike$e = lengthOfArrayLike$g;
1958         var arraySpeciesCreate$3 = arraySpeciesCreate$4;
1959
1960         var push$9 = uncurryThis$H([].push);
1961
1962         // `Array.prototype.{ forEach, map, filter, some, every, find, findIndex, filterReject }` methods implementation
1963         var createMethod$4 = function (TYPE) {
1964           var IS_MAP = TYPE == 1;
1965           var IS_FILTER = TYPE == 2;
1966           var IS_SOME = TYPE == 3;
1967           var IS_EVERY = TYPE == 4;
1968           var IS_FIND_INDEX = TYPE == 6;
1969           var IS_FILTER_REJECT = TYPE == 7;
1970           var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;
1971           return function ($this, callbackfn, that, specificCreate) {
1972             var O = toObject$g($this);
1973             var self = IndexedObject$3(O);
1974             var boundFunction = bind$e(callbackfn, that);
1975             var length = lengthOfArrayLike$e(self);
1976             var index = 0;
1977             var create = specificCreate || arraySpeciesCreate$3;
1978             var target = IS_MAP ? create($this, length) : IS_FILTER || IS_FILTER_REJECT ? create($this, 0) : undefined;
1979             var value, result;
1980             for (;length > index; index++) if (NO_HOLES || index in self) {
1981               value = self[index];
1982               result = boundFunction(value, index, O);
1983               if (TYPE) {
1984                 if (IS_MAP) target[index] = result; // map
1985                 else if (result) switch (TYPE) {
1986                   case 3: return true;              // some
1987                   case 5: return value;             // find
1988                   case 6: return index;             // findIndex
1989                   case 2: push$9(target, value);      // filter
1990                 } else switch (TYPE) {
1991                   case 4: return false;             // every
1992                   case 7: push$9(target, value);      // filterReject
1993                 }
1994               }
1995             }
1996             return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : target;
1997           };
1998         };
1999
2000         var arrayIteration = {
2001           // `Array.prototype.forEach` method
2002           // https://tc39.es/ecma262/#sec-array.prototype.foreach
2003           forEach: createMethod$4(0),
2004           // `Array.prototype.map` method
2005           // https://tc39.es/ecma262/#sec-array.prototype.map
2006           map: createMethod$4(1),
2007           // `Array.prototype.filter` method
2008           // https://tc39.es/ecma262/#sec-array.prototype.filter
2009           filter: createMethod$4(2),
2010           // `Array.prototype.some` method
2011           // https://tc39.es/ecma262/#sec-array.prototype.some
2012           some: createMethod$4(3),
2013           // `Array.prototype.every` method
2014           // https://tc39.es/ecma262/#sec-array.prototype.every
2015           every: createMethod$4(4),
2016           // `Array.prototype.find` method
2017           // https://tc39.es/ecma262/#sec-array.prototype.find
2018           find: createMethod$4(5),
2019           // `Array.prototype.findIndex` method
2020           // https://tc39.es/ecma262/#sec-array.prototype.findIndex
2021           findIndex: createMethod$4(6),
2022           // `Array.prototype.filterReject` method
2023           // https://github.com/tc39/proposal-array-filtering
2024           filterReject: createMethod$4(7)
2025         };
2026
2027         var $$1b = _export;
2028         var global$U = global$1m;
2029         var getBuiltIn$5 = getBuiltIn$b;
2030         var apply$8 = functionApply;
2031         var call$j = functionCall;
2032         var uncurryThis$G = functionUncurryThis;
2033         var DESCRIPTORS$h = descriptors;
2034         var NATIVE_SYMBOL$1 = nativeSymbol;
2035         var fails$J = fails$S;
2036         var hasOwn$b = hasOwnProperty_1;
2037         var isArray$6 = isArray$8;
2038         var isCallable$b = isCallable$r;
2039         var isObject$l = isObject$s;
2040         var isPrototypeOf$8 = objectIsPrototypeOf;
2041         var isSymbol$3 = isSymbol$6;
2042         var anObject$h = anObject$n;
2043         var toObject$f = toObject$j;
2044         var toIndexedObject$5 = toIndexedObject$c;
2045         var toPropertyKey$2 = toPropertyKey$5;
2046         var $toString$3 = toString$k;
2047         var createPropertyDescriptor$3 = createPropertyDescriptor$7;
2048         var nativeObjectCreate = objectCreate;
2049         var objectKeys$2 = objectKeys$4;
2050         var getOwnPropertyNamesModule$1 = objectGetOwnPropertyNames;
2051         var getOwnPropertyNamesExternal = objectGetOwnPropertyNamesExternal;
2052         var getOwnPropertySymbolsModule$1 = objectGetOwnPropertySymbols;
2053         var getOwnPropertyDescriptorModule$2 = objectGetOwnPropertyDescriptor;
2054         var definePropertyModule$3 = objectDefineProperty;
2055         var propertyIsEnumerableModule$1 = objectPropertyIsEnumerable;
2056         var arraySlice$a = arraySlice$c;
2057         var redefine$b = redefine$h.exports;
2058         var shared$1 = shared$5.exports;
2059         var sharedKey = sharedKey$4;
2060         var hiddenKeys$1 = hiddenKeys$6;
2061         var uid$2 = uid$5;
2062         var wellKnownSymbol$i = wellKnownSymbol$t;
2063         var wrappedWellKnownSymbolModule = wellKnownSymbolWrapped;
2064         var defineWellKnownSymbol$2 = defineWellKnownSymbol$4;
2065         var setToStringTag$7 = setToStringTag$a;
2066         var InternalStateModule$6 = internalState;
2067         var $forEach$2 = arrayIteration.forEach;
2068
2069         var HIDDEN = sharedKey('hidden');
2070         var SYMBOL = 'Symbol';
2071         var PROTOTYPE$1 = 'prototype';
2072         var TO_PRIMITIVE = wellKnownSymbol$i('toPrimitive');
2073
2074         var setInternalState$6 = InternalStateModule$6.set;
2075         var getInternalState$4 = InternalStateModule$6.getterFor(SYMBOL);
2076
2077         var ObjectPrototype$3 = Object[PROTOTYPE$1];
2078         var $Symbol = global$U.Symbol;
2079         var SymbolPrototype$1 = $Symbol && $Symbol[PROTOTYPE$1];
2080         var TypeError$g = global$U.TypeError;
2081         var QObject = global$U.QObject;
2082         var $stringify = getBuiltIn$5('JSON', 'stringify');
2083         var nativeGetOwnPropertyDescriptor$2 = getOwnPropertyDescriptorModule$2.f;
2084         var nativeDefineProperty$1 = definePropertyModule$3.f;
2085         var nativeGetOwnPropertyNames = getOwnPropertyNamesExternal.f;
2086         var nativePropertyIsEnumerable = propertyIsEnumerableModule$1.f;
2087         var push$8 = uncurryThis$G([].push);
2088
2089         var AllSymbols = shared$1('symbols');
2090         var ObjectPrototypeSymbols = shared$1('op-symbols');
2091         var StringToSymbolRegistry = shared$1('string-to-symbol-registry');
2092         var SymbolToStringRegistry = shared$1('symbol-to-string-registry');
2093         var WellKnownSymbolsStore = shared$1('wks');
2094
2095         // Don't use setters in Qt Script, https://github.com/zloirock/core-js/issues/173
2096         var USE_SETTER = !QObject || !QObject[PROTOTYPE$1] || !QObject[PROTOTYPE$1].findChild;
2097
2098         // fallback for old Android, https://code.google.com/p/v8/issues/detail?id=687
2099         var setSymbolDescriptor = DESCRIPTORS$h && fails$J(function () {
2100           return nativeObjectCreate(nativeDefineProperty$1({}, 'a', {
2101             get: function () { return nativeDefineProperty$1(this, 'a', { value: 7 }).a; }
2102           })).a != 7;
2103         }) ? function (O, P, Attributes) {
2104           var ObjectPrototypeDescriptor = nativeGetOwnPropertyDescriptor$2(ObjectPrototype$3, P);
2105           if (ObjectPrototypeDescriptor) delete ObjectPrototype$3[P];
2106           nativeDefineProperty$1(O, P, Attributes);
2107           if (ObjectPrototypeDescriptor && O !== ObjectPrototype$3) {
2108             nativeDefineProperty$1(ObjectPrototype$3, P, ObjectPrototypeDescriptor);
2109           }
2110         } : nativeDefineProperty$1;
2111
2112         var wrap$2 = function (tag, description) {
2113           var symbol = AllSymbols[tag] = nativeObjectCreate(SymbolPrototype$1);
2114           setInternalState$6(symbol, {
2115             type: SYMBOL,
2116             tag: tag,
2117             description: description
2118           });
2119           if (!DESCRIPTORS$h) symbol.description = description;
2120           return symbol;
2121         };
2122
2123         var $defineProperty = function defineProperty(O, P, Attributes) {
2124           if (O === ObjectPrototype$3) $defineProperty(ObjectPrototypeSymbols, P, Attributes);
2125           anObject$h(O);
2126           var key = toPropertyKey$2(P);
2127           anObject$h(Attributes);
2128           if (hasOwn$b(AllSymbols, key)) {
2129             if (!Attributes.enumerable) {
2130               if (!hasOwn$b(O, HIDDEN)) nativeDefineProperty$1(O, HIDDEN, createPropertyDescriptor$3(1, {}));
2131               O[HIDDEN][key] = true;
2132             } else {
2133               if (hasOwn$b(O, HIDDEN) && O[HIDDEN][key]) O[HIDDEN][key] = false;
2134               Attributes = nativeObjectCreate(Attributes, { enumerable: createPropertyDescriptor$3(0, false) });
2135             } return setSymbolDescriptor(O, key, Attributes);
2136           } return nativeDefineProperty$1(O, key, Attributes);
2137         };
2138
2139         var $defineProperties = function defineProperties(O, Properties) {
2140           anObject$h(O);
2141           var properties = toIndexedObject$5(Properties);
2142           var keys = objectKeys$2(properties).concat($getOwnPropertySymbols(properties));
2143           $forEach$2(keys, function (key) {
2144             if (!DESCRIPTORS$h || call$j($propertyIsEnumerable$1, properties, key)) $defineProperty(O, key, properties[key]);
2145           });
2146           return O;
2147         };
2148
2149         var $create = function create(O, Properties) {
2150           return Properties === undefined ? nativeObjectCreate(O) : $defineProperties(nativeObjectCreate(O), Properties);
2151         };
2152
2153         var $propertyIsEnumerable$1 = function propertyIsEnumerable(V) {
2154           var P = toPropertyKey$2(V);
2155           var enumerable = call$j(nativePropertyIsEnumerable, this, P);
2156           if (this === ObjectPrototype$3 && hasOwn$b(AllSymbols, P) && !hasOwn$b(ObjectPrototypeSymbols, P)) return false;
2157           return enumerable || !hasOwn$b(this, P) || !hasOwn$b(AllSymbols, P) || hasOwn$b(this, HIDDEN) && this[HIDDEN][P]
2158             ? enumerable : true;
2159         };
2160
2161         var $getOwnPropertyDescriptor = function getOwnPropertyDescriptor(O, P) {
2162           var it = toIndexedObject$5(O);
2163           var key = toPropertyKey$2(P);
2164           if (it === ObjectPrototype$3 && hasOwn$b(AllSymbols, key) && !hasOwn$b(ObjectPrototypeSymbols, key)) return;
2165           var descriptor = nativeGetOwnPropertyDescriptor$2(it, key);
2166           if (descriptor && hasOwn$b(AllSymbols, key) && !(hasOwn$b(it, HIDDEN) && it[HIDDEN][key])) {
2167             descriptor.enumerable = true;
2168           }
2169           return descriptor;
2170         };
2171
2172         var $getOwnPropertyNames = function getOwnPropertyNames(O) {
2173           var names = nativeGetOwnPropertyNames(toIndexedObject$5(O));
2174           var result = [];
2175           $forEach$2(names, function (key) {
2176             if (!hasOwn$b(AllSymbols, key) && !hasOwn$b(hiddenKeys$1, key)) push$8(result, key);
2177           });
2178           return result;
2179         };
2180
2181         var $getOwnPropertySymbols = function getOwnPropertySymbols(O) {
2182           var IS_OBJECT_PROTOTYPE = O === ObjectPrototype$3;
2183           var names = nativeGetOwnPropertyNames(IS_OBJECT_PROTOTYPE ? ObjectPrototypeSymbols : toIndexedObject$5(O));
2184           var result = [];
2185           $forEach$2(names, function (key) {
2186             if (hasOwn$b(AllSymbols, key) && (!IS_OBJECT_PROTOTYPE || hasOwn$b(ObjectPrototype$3, key))) {
2187               push$8(result, AllSymbols[key]);
2188             }
2189           });
2190           return result;
2191         };
2192
2193         // `Symbol` constructor
2194         // https://tc39.es/ecma262/#sec-symbol-constructor
2195         if (!NATIVE_SYMBOL$1) {
2196           $Symbol = function Symbol() {
2197             if (isPrototypeOf$8(SymbolPrototype$1, this)) throw TypeError$g('Symbol is not a constructor');
2198             var description = !arguments.length || arguments[0] === undefined ? undefined : $toString$3(arguments[0]);
2199             var tag = uid$2(description);
2200             var setter = function (value) {
2201               if (this === ObjectPrototype$3) call$j(setter, ObjectPrototypeSymbols, value);
2202               if (hasOwn$b(this, HIDDEN) && hasOwn$b(this[HIDDEN], tag)) this[HIDDEN][tag] = false;
2203               setSymbolDescriptor(this, tag, createPropertyDescriptor$3(1, value));
2204             };
2205             if (DESCRIPTORS$h && USE_SETTER) setSymbolDescriptor(ObjectPrototype$3, tag, { configurable: true, set: setter });
2206             return wrap$2(tag, description);
2207           };
2208
2209           SymbolPrototype$1 = $Symbol[PROTOTYPE$1];
2210
2211           redefine$b(SymbolPrototype$1, 'toString', function toString() {
2212             return getInternalState$4(this).tag;
2213           });
2214
2215           redefine$b($Symbol, 'withoutSetter', function (description) {
2216             return wrap$2(uid$2(description), description);
2217           });
2218
2219           propertyIsEnumerableModule$1.f = $propertyIsEnumerable$1;
2220           definePropertyModule$3.f = $defineProperty;
2221           getOwnPropertyDescriptorModule$2.f = $getOwnPropertyDescriptor;
2222           getOwnPropertyNamesModule$1.f = getOwnPropertyNamesExternal.f = $getOwnPropertyNames;
2223           getOwnPropertySymbolsModule$1.f = $getOwnPropertySymbols;
2224
2225           wrappedWellKnownSymbolModule.f = function (name) {
2226             return wrap$2(wellKnownSymbol$i(name), name);
2227           };
2228
2229           if (DESCRIPTORS$h) {
2230             // https://github.com/tc39/proposal-Symbol-description
2231             nativeDefineProperty$1(SymbolPrototype$1, 'description', {
2232               configurable: true,
2233               get: function description() {
2234                 return getInternalState$4(this).description;
2235               }
2236             });
2237             {
2238               redefine$b(ObjectPrototype$3, 'propertyIsEnumerable', $propertyIsEnumerable$1, { unsafe: true });
2239             }
2240           }
2241         }
2242
2243         $$1b({ global: true, wrap: true, forced: !NATIVE_SYMBOL$1, sham: !NATIVE_SYMBOL$1 }, {
2244           Symbol: $Symbol
2245         });
2246
2247         $forEach$2(objectKeys$2(WellKnownSymbolsStore), function (name) {
2248           defineWellKnownSymbol$2(name);
2249         });
2250
2251         $$1b({ target: SYMBOL, stat: true, forced: !NATIVE_SYMBOL$1 }, {
2252           // `Symbol.for` method
2253           // https://tc39.es/ecma262/#sec-symbol.for
2254           'for': function (key) {
2255             var string = $toString$3(key);
2256             if (hasOwn$b(StringToSymbolRegistry, string)) return StringToSymbolRegistry[string];
2257             var symbol = $Symbol(string);
2258             StringToSymbolRegistry[string] = symbol;
2259             SymbolToStringRegistry[symbol] = string;
2260             return symbol;
2261           },
2262           // `Symbol.keyFor` method
2263           // https://tc39.es/ecma262/#sec-symbol.keyfor
2264           keyFor: function keyFor(sym) {
2265             if (!isSymbol$3(sym)) throw TypeError$g(sym + ' is not a symbol');
2266             if (hasOwn$b(SymbolToStringRegistry, sym)) return SymbolToStringRegistry[sym];
2267           },
2268           useSetter: function () { USE_SETTER = true; },
2269           useSimple: function () { USE_SETTER = false; }
2270         });
2271
2272         $$1b({ target: 'Object', stat: true, forced: !NATIVE_SYMBOL$1, sham: !DESCRIPTORS$h }, {
2273           // `Object.create` method
2274           // https://tc39.es/ecma262/#sec-object.create
2275           create: $create,
2276           // `Object.defineProperty` method
2277           // https://tc39.es/ecma262/#sec-object.defineproperty
2278           defineProperty: $defineProperty,
2279           // `Object.defineProperties` method
2280           // https://tc39.es/ecma262/#sec-object.defineproperties
2281           defineProperties: $defineProperties,
2282           // `Object.getOwnPropertyDescriptor` method
2283           // https://tc39.es/ecma262/#sec-object.getownpropertydescriptors
2284           getOwnPropertyDescriptor: $getOwnPropertyDescriptor
2285         });
2286
2287         $$1b({ target: 'Object', stat: true, forced: !NATIVE_SYMBOL$1 }, {
2288           // `Object.getOwnPropertyNames` method
2289           // https://tc39.es/ecma262/#sec-object.getownpropertynames
2290           getOwnPropertyNames: $getOwnPropertyNames,
2291           // `Object.getOwnPropertySymbols` method
2292           // https://tc39.es/ecma262/#sec-object.getownpropertysymbols
2293           getOwnPropertySymbols: $getOwnPropertySymbols
2294         });
2295
2296         // Chrome 38 and 39 `Object.getOwnPropertySymbols` fails on primitives
2297         // https://bugs.chromium.org/p/v8/issues/detail?id=3443
2298         $$1b({ target: 'Object', stat: true, forced: fails$J(function () { getOwnPropertySymbolsModule$1.f(1); }) }, {
2299           getOwnPropertySymbols: function getOwnPropertySymbols(it) {
2300             return getOwnPropertySymbolsModule$1.f(toObject$f(it));
2301           }
2302         });
2303
2304         // `JSON.stringify` method behavior with symbols
2305         // https://tc39.es/ecma262/#sec-json.stringify
2306         if ($stringify) {
2307           var FORCED_JSON_STRINGIFY = !NATIVE_SYMBOL$1 || fails$J(function () {
2308             var symbol = $Symbol();
2309             // MS Edge converts symbol values to JSON as {}
2310             return $stringify([symbol]) != '[null]'
2311               // WebKit converts symbol values to JSON as null
2312               || $stringify({ a: symbol }) != '{}'
2313               // V8 throws on boxed symbols
2314               || $stringify(Object(symbol)) != '{}';
2315           });
2316
2317           $$1b({ target: 'JSON', stat: true, forced: FORCED_JSON_STRINGIFY }, {
2318             // eslint-disable-next-line no-unused-vars -- required for `.length`
2319             stringify: function stringify(it, replacer, space) {
2320               var args = arraySlice$a(arguments);
2321               var $replacer = replacer;
2322               if (!isObject$l(replacer) && it === undefined || isSymbol$3(it)) return; // IE8 returns string on undefined
2323               if (!isArray$6(replacer)) replacer = function (key, value) {
2324                 if (isCallable$b($replacer)) value = call$j($replacer, this, key, value);
2325                 if (!isSymbol$3(value)) return value;
2326               };
2327               args[1] = replacer;
2328               return apply$8($stringify, null, args);
2329             }
2330           });
2331         }
2332
2333         // `Symbol.prototype[@@toPrimitive]` method
2334         // https://tc39.es/ecma262/#sec-symbol.prototype-@@toprimitive
2335         if (!SymbolPrototype$1[TO_PRIMITIVE]) {
2336           var valueOf = SymbolPrototype$1.valueOf;
2337           // eslint-disable-next-line no-unused-vars -- required for .length
2338           redefine$b(SymbolPrototype$1, TO_PRIMITIVE, function (hint) {
2339             // TODO: improve hint logic
2340             return call$j(valueOf, this);
2341           });
2342         }
2343         // `Symbol.prototype[@@toStringTag]` property
2344         // https://tc39.es/ecma262/#sec-symbol.prototype-@@tostringtag
2345         setToStringTag$7($Symbol, SYMBOL);
2346
2347         hiddenKeys$1[HIDDEN] = true;
2348
2349         var $$1a = _export;
2350         var DESCRIPTORS$g = descriptors;
2351         var global$T = global$1m;
2352         var uncurryThis$F = functionUncurryThis;
2353         var hasOwn$a = hasOwnProperty_1;
2354         var isCallable$a = isCallable$r;
2355         var isPrototypeOf$7 = objectIsPrototypeOf;
2356         var toString$h = toString$k;
2357         var defineProperty$8 = objectDefineProperty.f;
2358         var copyConstructorProperties = copyConstructorProperties$2;
2359
2360         var NativeSymbol = global$T.Symbol;
2361         var SymbolPrototype = NativeSymbol && NativeSymbol.prototype;
2362
2363         if (DESCRIPTORS$g && isCallable$a(NativeSymbol) && (!('description' in SymbolPrototype) ||
2364           // Safari 12 bug
2365           NativeSymbol().description !== undefined
2366         )) {
2367           var EmptyStringDescriptionStore = {};
2368           // wrap Symbol constructor for correct work with undefined description
2369           var SymbolWrapper = function Symbol() {
2370             var description = arguments.length < 1 || arguments[0] === undefined ? undefined : toString$h(arguments[0]);
2371             var result = isPrototypeOf$7(SymbolPrototype, this)
2372               ? new NativeSymbol(description)
2373               // in Edge 13, String(Symbol(undefined)) === 'Symbol(undefined)'
2374               : description === undefined ? NativeSymbol() : NativeSymbol(description);
2375             if (description === '') EmptyStringDescriptionStore[result] = true;
2376             return result;
2377           };
2378
2379           copyConstructorProperties(SymbolWrapper, NativeSymbol);
2380           SymbolWrapper.prototype = SymbolPrototype;
2381           SymbolPrototype.constructor = SymbolWrapper;
2382
2383           var NATIVE_SYMBOL = String(NativeSymbol('test')) == 'Symbol(test)';
2384           var symbolToString$1 = uncurryThis$F(SymbolPrototype.toString);
2385           var symbolValueOf = uncurryThis$F(SymbolPrototype.valueOf);
2386           var regexp = /^Symbol\((.*)\)[^)]+$/;
2387           var replace$8 = uncurryThis$F(''.replace);
2388           var stringSlice$a = uncurryThis$F(''.slice);
2389
2390           defineProperty$8(SymbolPrototype, 'description', {
2391             configurable: true,
2392             get: function description() {
2393               var symbol = symbolValueOf(this);
2394               var string = symbolToString$1(symbol);
2395               if (hasOwn$a(EmptyStringDescriptionStore, symbol)) return '';
2396               var desc = NATIVE_SYMBOL ? stringSlice$a(string, 7, -1) : replace$8(string, regexp, '$1');
2397               return desc === '' ? undefined : desc;
2398             }
2399           });
2400
2401           $$1a({ global: true, forced: true }, {
2402             Symbol: SymbolWrapper
2403           });
2404         }
2405
2406         // eslint-disable-next-line es/no-typed-arrays -- safe
2407         var arrayBufferNative = typeof ArrayBuffer != 'undefined' && typeof DataView != 'undefined';
2408
2409         var redefine$a = redefine$h.exports;
2410
2411         var redefineAll$4 = function (target, src, options) {
2412           for (var key in src) redefine$a(target, key, src[key], options);
2413           return target;
2414         };
2415
2416         var global$S = global$1m;
2417         var isPrototypeOf$6 = objectIsPrototypeOf;
2418
2419         var TypeError$f = global$S.TypeError;
2420
2421         var anInstance$7 = function (it, Prototype) {
2422           if (isPrototypeOf$6(Prototype, it)) return it;
2423           throw TypeError$f('Incorrect invocation');
2424         };
2425
2426         var global$R = global$1m;
2427         var toIntegerOrInfinity$7 = toIntegerOrInfinity$b;
2428         var toLength$a = toLength$c;
2429
2430         var RangeError$b = global$R.RangeError;
2431
2432         // `ToIndex` abstract operation
2433         // https://tc39.es/ecma262/#sec-toindex
2434         var toIndex$2 = function (it) {
2435           if (it === undefined) return 0;
2436           var number = toIntegerOrInfinity$7(it);
2437           var length = toLength$a(number);
2438           if (number !== length) throw RangeError$b('Wrong length or index');
2439           return length;
2440         };
2441
2442         // IEEE754 conversions based on https://github.com/feross/ieee754
2443         var global$Q = global$1m;
2444
2445         var Array$5 = global$Q.Array;
2446         var abs$4 = Math.abs;
2447         var pow$2 = Math.pow;
2448         var floor$7 = Math.floor;
2449         var log$2 = Math.log;
2450         var LN2 = Math.LN2;
2451
2452         var pack = function (number, mantissaLength, bytes) {
2453           var buffer = Array$5(bytes);
2454           var exponentLength = bytes * 8 - mantissaLength - 1;
2455           var eMax = (1 << exponentLength) - 1;
2456           var eBias = eMax >> 1;
2457           var rt = mantissaLength === 23 ? pow$2(2, -24) - pow$2(2, -77) : 0;
2458           var sign = number < 0 || number === 0 && 1 / number < 0 ? 1 : 0;
2459           var index = 0;
2460           var exponent, mantissa, c;
2461           number = abs$4(number);
2462           // eslint-disable-next-line no-self-compare -- NaN check
2463           if (number != number || number === Infinity) {
2464             // eslint-disable-next-line no-self-compare -- NaN check
2465             mantissa = number != number ? 1 : 0;
2466             exponent = eMax;
2467           } else {
2468             exponent = floor$7(log$2(number) / LN2);
2469             if (number * (c = pow$2(2, -exponent)) < 1) {
2470               exponent--;
2471               c *= 2;
2472             }
2473             if (exponent + eBias >= 1) {
2474               number += rt / c;
2475             } else {
2476               number += rt * pow$2(2, 1 - eBias);
2477             }
2478             if (number * c >= 2) {
2479               exponent++;
2480               c /= 2;
2481             }
2482             if (exponent + eBias >= eMax) {
2483               mantissa = 0;
2484               exponent = eMax;
2485             } else if (exponent + eBias >= 1) {
2486               mantissa = (number * c - 1) * pow$2(2, mantissaLength);
2487               exponent = exponent + eBias;
2488             } else {
2489               mantissa = number * pow$2(2, eBias - 1) * pow$2(2, mantissaLength);
2490               exponent = 0;
2491             }
2492           }
2493           for (; mantissaLength >= 8; buffer[index++] = mantissa & 255, mantissa /= 256, mantissaLength -= 8);
2494           exponent = exponent << mantissaLength | mantissa;
2495           exponentLength += mantissaLength;
2496           for (; exponentLength > 0; buffer[index++] = exponent & 255, exponent /= 256, exponentLength -= 8);
2497           buffer[--index] |= sign * 128;
2498           return buffer;
2499         };
2500
2501         var unpack = function (buffer, mantissaLength) {
2502           var bytes = buffer.length;
2503           var exponentLength = bytes * 8 - mantissaLength - 1;
2504           var eMax = (1 << exponentLength) - 1;
2505           var eBias = eMax >> 1;
2506           var nBits = exponentLength - 7;
2507           var index = bytes - 1;
2508           var sign = buffer[index--];
2509           var exponent = sign & 127;
2510           var mantissa;
2511           sign >>= 7;
2512           for (; nBits > 0; exponent = exponent * 256 + buffer[index], index--, nBits -= 8);
2513           mantissa = exponent & (1 << -nBits) - 1;
2514           exponent >>= -nBits;
2515           nBits += mantissaLength;
2516           for (; nBits > 0; mantissa = mantissa * 256 + buffer[index], index--, nBits -= 8);
2517           if (exponent === 0) {
2518             exponent = 1 - eBias;
2519           } else if (exponent === eMax) {
2520             return mantissa ? NaN : sign ? -Infinity : Infinity;
2521           } else {
2522             mantissa = mantissa + pow$2(2, mantissaLength);
2523             exponent = exponent - eBias;
2524           } return (sign ? -1 : 1) * mantissa * pow$2(2, exponent - mantissaLength);
2525         };
2526
2527         var ieee754$2 = {
2528           pack: pack,
2529           unpack: unpack
2530         };
2531
2532         var toObject$e = toObject$j;
2533         var toAbsoluteIndex$6 = toAbsoluteIndex$8;
2534         var lengthOfArrayLike$d = lengthOfArrayLike$g;
2535
2536         // `Array.prototype.fill` method implementation
2537         // https://tc39.es/ecma262/#sec-array.prototype.fill
2538         var arrayFill$1 = function fill(value /* , start = 0, end = @length */) {
2539           var O = toObject$e(this);
2540           var length = lengthOfArrayLike$d(O);
2541           var argumentsLength = arguments.length;
2542           var index = toAbsoluteIndex$6(argumentsLength > 1 ? arguments[1] : undefined, length);
2543           var end = argumentsLength > 2 ? arguments[2] : undefined;
2544           var endPos = end === undefined ? length : toAbsoluteIndex$6(end, length);
2545           while (endPos > index) O[index++] = value;
2546           return O;
2547         };
2548
2549         var global$P = global$1m;
2550         var uncurryThis$E = functionUncurryThis;
2551         var DESCRIPTORS$f = descriptors;
2552         var NATIVE_ARRAY_BUFFER$2 = arrayBufferNative;
2553         var FunctionName = functionName;
2554         var createNonEnumerableProperty$5 = createNonEnumerableProperty$b;
2555         var redefineAll$3 = redefineAll$4;
2556         var fails$I = fails$S;
2557         var anInstance$6 = anInstance$7;
2558         var toIntegerOrInfinity$6 = toIntegerOrInfinity$b;
2559         var toLength$9 = toLength$c;
2560         var toIndex$1 = toIndex$2;
2561         var IEEE754 = ieee754$2;
2562         var getPrototypeOf$2 = objectGetPrototypeOf;
2563         var setPrototypeOf$5 = objectSetPrototypeOf;
2564         var getOwnPropertyNames$4 = objectGetOwnPropertyNames.f;
2565         var defineProperty$7 = objectDefineProperty.f;
2566         var arrayFill = arrayFill$1;
2567         var arraySlice$9 = arraySlice$c;
2568         var setToStringTag$6 = setToStringTag$a;
2569         var InternalStateModule$5 = internalState;
2570
2571         var PROPER_FUNCTION_NAME$3 = FunctionName.PROPER;
2572         var CONFIGURABLE_FUNCTION_NAME = FunctionName.CONFIGURABLE;
2573         var getInternalState$3 = InternalStateModule$5.get;
2574         var setInternalState$5 = InternalStateModule$5.set;
2575         var ARRAY_BUFFER$1 = 'ArrayBuffer';
2576         var DATA_VIEW = 'DataView';
2577         var PROTOTYPE = 'prototype';
2578         var WRONG_LENGTH$1 = 'Wrong length';
2579         var WRONG_INDEX = 'Wrong index';
2580         var NativeArrayBuffer$1 = global$P[ARRAY_BUFFER$1];
2581         var $ArrayBuffer = NativeArrayBuffer$1;
2582         var ArrayBufferPrototype$1 = $ArrayBuffer && $ArrayBuffer[PROTOTYPE];
2583         var $DataView = global$P[DATA_VIEW];
2584         var DataViewPrototype$1 = $DataView && $DataView[PROTOTYPE];
2585         var ObjectPrototype$2 = Object.prototype;
2586         var Array$4 = global$P.Array;
2587         var RangeError$a = global$P.RangeError;
2588         var fill$1 = uncurryThis$E(arrayFill);
2589         var reverse = uncurryThis$E([].reverse);
2590
2591         var packIEEE754 = IEEE754.pack;
2592         var unpackIEEE754 = IEEE754.unpack;
2593
2594         var packInt8 = function (number) {
2595           return [number & 0xFF];
2596         };
2597
2598         var packInt16 = function (number) {
2599           return [number & 0xFF, number >> 8 & 0xFF];
2600         };
2601
2602         var packInt32 = function (number) {
2603           return [number & 0xFF, number >> 8 & 0xFF, number >> 16 & 0xFF, number >> 24 & 0xFF];
2604         };
2605
2606         var unpackInt32 = function (buffer) {
2607           return buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];
2608         };
2609
2610         var packFloat32 = function (number) {
2611           return packIEEE754(number, 23, 4);
2612         };
2613
2614         var packFloat64 = function (number) {
2615           return packIEEE754(number, 52, 8);
2616         };
2617
2618         var addGetter$1 = function (Constructor, key) {
2619           defineProperty$7(Constructor[PROTOTYPE], key, { get: function () { return getInternalState$3(this)[key]; } });
2620         };
2621
2622         var get$4 = function (view, count, index, isLittleEndian) {
2623           var intIndex = toIndex$1(index);
2624           var store = getInternalState$3(view);
2625           if (intIndex + count > store.byteLength) throw RangeError$a(WRONG_INDEX);
2626           var bytes = getInternalState$3(store.buffer).bytes;
2627           var start = intIndex + store.byteOffset;
2628           var pack = arraySlice$9(bytes, start, start + count);
2629           return isLittleEndian ? pack : reverse(pack);
2630         };
2631
2632         var set$3 = function (view, count, index, conversion, value, isLittleEndian) {
2633           var intIndex = toIndex$1(index);
2634           var store = getInternalState$3(view);
2635           if (intIndex + count > store.byteLength) throw RangeError$a(WRONG_INDEX);
2636           var bytes = getInternalState$3(store.buffer).bytes;
2637           var start = intIndex + store.byteOffset;
2638           var pack = conversion(+value);
2639           for (var i = 0; i < count; i++) bytes[start + i] = pack[isLittleEndian ? i : count - i - 1];
2640         };
2641
2642         if (!NATIVE_ARRAY_BUFFER$2) {
2643           $ArrayBuffer = function ArrayBuffer(length) {
2644             anInstance$6(this, ArrayBufferPrototype$1);
2645             var byteLength = toIndex$1(length);
2646             setInternalState$5(this, {
2647               bytes: fill$1(Array$4(byteLength), 0),
2648               byteLength: byteLength
2649             });
2650             if (!DESCRIPTORS$f) this.byteLength = byteLength;
2651           };
2652
2653           ArrayBufferPrototype$1 = $ArrayBuffer[PROTOTYPE];
2654
2655           $DataView = function DataView(buffer, byteOffset, byteLength) {
2656             anInstance$6(this, DataViewPrototype$1);
2657             anInstance$6(buffer, ArrayBufferPrototype$1);
2658             var bufferLength = getInternalState$3(buffer).byteLength;
2659             var offset = toIntegerOrInfinity$6(byteOffset);
2660             if (offset < 0 || offset > bufferLength) throw RangeError$a('Wrong offset');
2661             byteLength = byteLength === undefined ? bufferLength - offset : toLength$9(byteLength);
2662             if (offset + byteLength > bufferLength) throw RangeError$a(WRONG_LENGTH$1);
2663             setInternalState$5(this, {
2664               buffer: buffer,
2665               byteLength: byteLength,
2666               byteOffset: offset
2667             });
2668             if (!DESCRIPTORS$f) {
2669               this.buffer = buffer;
2670               this.byteLength = byteLength;
2671               this.byteOffset = offset;
2672             }
2673           };
2674
2675           DataViewPrototype$1 = $DataView[PROTOTYPE];
2676
2677           if (DESCRIPTORS$f) {
2678             addGetter$1($ArrayBuffer, 'byteLength');
2679             addGetter$1($DataView, 'buffer');
2680             addGetter$1($DataView, 'byteLength');
2681             addGetter$1($DataView, 'byteOffset');
2682           }
2683
2684           redefineAll$3(DataViewPrototype$1, {
2685             getInt8: function getInt8(byteOffset) {
2686               return get$4(this, 1, byteOffset)[0] << 24 >> 24;
2687             },
2688             getUint8: function getUint8(byteOffset) {
2689               return get$4(this, 1, byteOffset)[0];
2690             },
2691             getInt16: function getInt16(byteOffset /* , littleEndian */) {
2692               var bytes = get$4(this, 2, byteOffset, arguments.length > 1 ? arguments[1] : undefined);
2693               return (bytes[1] << 8 | bytes[0]) << 16 >> 16;
2694             },
2695             getUint16: function getUint16(byteOffset /* , littleEndian */) {
2696               var bytes = get$4(this, 2, byteOffset, arguments.length > 1 ? arguments[1] : undefined);
2697               return bytes[1] << 8 | bytes[0];
2698             },
2699             getInt32: function getInt32(byteOffset /* , littleEndian */) {
2700               return unpackInt32(get$4(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : undefined));
2701             },
2702             getUint32: function getUint32(byteOffset /* , littleEndian */) {
2703               return unpackInt32(get$4(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : undefined)) >>> 0;
2704             },
2705             getFloat32: function getFloat32(byteOffset /* , littleEndian */) {
2706               return unpackIEEE754(get$4(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : undefined), 23);
2707             },
2708             getFloat64: function getFloat64(byteOffset /* , littleEndian */) {
2709               return unpackIEEE754(get$4(this, 8, byteOffset, arguments.length > 1 ? arguments[1] : undefined), 52);
2710             },
2711             setInt8: function setInt8(byteOffset, value) {
2712               set$3(this, 1, byteOffset, packInt8, value);
2713             },
2714             setUint8: function setUint8(byteOffset, value) {
2715               set$3(this, 1, byteOffset, packInt8, value);
2716             },
2717             setInt16: function setInt16(byteOffset, value /* , littleEndian */) {
2718               set$3(this, 2, byteOffset, packInt16, value, arguments.length > 2 ? arguments[2] : undefined);
2719             },
2720             setUint16: function setUint16(byteOffset, value /* , littleEndian */) {
2721               set$3(this, 2, byteOffset, packInt16, value, arguments.length > 2 ? arguments[2] : undefined);
2722             },
2723             setInt32: function setInt32(byteOffset, value /* , littleEndian */) {
2724               set$3(this, 4, byteOffset, packInt32, value, arguments.length > 2 ? arguments[2] : undefined);
2725             },
2726             setUint32: function setUint32(byteOffset, value /* , littleEndian */) {
2727               set$3(this, 4, byteOffset, packInt32, value, arguments.length > 2 ? arguments[2] : undefined);
2728             },
2729             setFloat32: function setFloat32(byteOffset, value /* , littleEndian */) {
2730               set$3(this, 4, byteOffset, packFloat32, value, arguments.length > 2 ? arguments[2] : undefined);
2731             },
2732             setFloat64: function setFloat64(byteOffset, value /* , littleEndian */) {
2733               set$3(this, 8, byteOffset, packFloat64, value, arguments.length > 2 ? arguments[2] : undefined);
2734             }
2735           });
2736         } else {
2737           var INCORRECT_ARRAY_BUFFER_NAME = PROPER_FUNCTION_NAME$3 && NativeArrayBuffer$1.name !== ARRAY_BUFFER$1;
2738           /* eslint-disable no-new -- required for testing */
2739           if (!fails$I(function () {
2740             NativeArrayBuffer$1(1);
2741           }) || !fails$I(function () {
2742             new NativeArrayBuffer$1(-1);
2743           }) || fails$I(function () {
2744             new NativeArrayBuffer$1();
2745             new NativeArrayBuffer$1(1.5);
2746             new NativeArrayBuffer$1(NaN);
2747             return INCORRECT_ARRAY_BUFFER_NAME && !CONFIGURABLE_FUNCTION_NAME;
2748           })) {
2749           /* eslint-enable no-new -- required for testing */
2750             $ArrayBuffer = function ArrayBuffer(length) {
2751               anInstance$6(this, ArrayBufferPrototype$1);
2752               return new NativeArrayBuffer$1(toIndex$1(length));
2753             };
2754
2755             $ArrayBuffer[PROTOTYPE] = ArrayBufferPrototype$1;
2756
2757             for (var keys$2 = getOwnPropertyNames$4(NativeArrayBuffer$1), j$2 = 0, key$1; keys$2.length > j$2;) {
2758               if (!((key$1 = keys$2[j$2++]) in $ArrayBuffer)) {
2759                 createNonEnumerableProperty$5($ArrayBuffer, key$1, NativeArrayBuffer$1[key$1]);
2760               }
2761             }
2762
2763             ArrayBufferPrototype$1.constructor = $ArrayBuffer;
2764           } else if (INCORRECT_ARRAY_BUFFER_NAME && CONFIGURABLE_FUNCTION_NAME) {
2765             createNonEnumerableProperty$5(NativeArrayBuffer$1, 'name', ARRAY_BUFFER$1);
2766           }
2767
2768           // WebKit bug - the same parent prototype for typed arrays and data view
2769           if (setPrototypeOf$5 && getPrototypeOf$2(DataViewPrototype$1) !== ObjectPrototype$2) {
2770             setPrototypeOf$5(DataViewPrototype$1, ObjectPrototype$2);
2771           }
2772
2773           // iOS Safari 7.x bug
2774           var testView = new $DataView(new $ArrayBuffer(2));
2775           var $setInt8 = uncurryThis$E(DataViewPrototype$1.setInt8);
2776           testView.setInt8(0, 2147483648);
2777           testView.setInt8(1, 2147483649);
2778           if (testView.getInt8(0) || !testView.getInt8(1)) redefineAll$3(DataViewPrototype$1, {
2779             setInt8: function setInt8(byteOffset, value) {
2780               $setInt8(this, byteOffset, value << 24 >> 24);
2781             },
2782             setUint8: function setUint8(byteOffset, value) {
2783               $setInt8(this, byteOffset, value << 24 >> 24);
2784             }
2785           }, { unsafe: true });
2786         }
2787
2788         setToStringTag$6($ArrayBuffer, ARRAY_BUFFER$1);
2789         setToStringTag$6($DataView, DATA_VIEW);
2790
2791         var arrayBuffer = {
2792           ArrayBuffer: $ArrayBuffer,
2793           DataView: $DataView
2794         };
2795
2796         var global$O = global$1m;
2797         var isConstructor$2 = isConstructor$4;
2798         var tryToString$3 = tryToString$5;
2799
2800         var TypeError$e = global$O.TypeError;
2801
2802         // `Assert: IsConstructor(argument) is true`
2803         var aConstructor$3 = function (argument) {
2804           if (isConstructor$2(argument)) return argument;
2805           throw TypeError$e(tryToString$3(argument) + ' is not a constructor');
2806         };
2807
2808         var anObject$g = anObject$n;
2809         var aConstructor$2 = aConstructor$3;
2810         var wellKnownSymbol$h = wellKnownSymbol$t;
2811
2812         var SPECIES$5 = wellKnownSymbol$h('species');
2813
2814         // `SpeciesConstructor` abstract operation
2815         // https://tc39.es/ecma262/#sec-speciesconstructor
2816         var speciesConstructor$5 = function (O, defaultConstructor) {
2817           var C = anObject$g(O).constructor;
2818           var S;
2819           return C === undefined || (S = anObject$g(C)[SPECIES$5]) == undefined ? defaultConstructor : aConstructor$2(S);
2820         };
2821
2822         var $$19 = _export;
2823         var uncurryThis$D = functionUncurryThis;
2824         var fails$H = fails$S;
2825         var ArrayBufferModule$2 = arrayBuffer;
2826         var anObject$f = anObject$n;
2827         var toAbsoluteIndex$5 = toAbsoluteIndex$8;
2828         var toLength$8 = toLength$c;
2829         var speciesConstructor$4 = speciesConstructor$5;
2830
2831         var ArrayBuffer$4 = ArrayBufferModule$2.ArrayBuffer;
2832         var DataView$2 = ArrayBufferModule$2.DataView;
2833         var DataViewPrototype = DataView$2.prototype;
2834         var un$ArrayBufferSlice = uncurryThis$D(ArrayBuffer$4.prototype.slice);
2835         var getUint8 = uncurryThis$D(DataViewPrototype.getUint8);
2836         var setUint8 = uncurryThis$D(DataViewPrototype.setUint8);
2837
2838         var INCORRECT_SLICE = fails$H(function () {
2839           return !new ArrayBuffer$4(2).slice(1, undefined).byteLength;
2840         });
2841
2842         // `ArrayBuffer.prototype.slice` method
2843         // https://tc39.es/ecma262/#sec-arraybuffer.prototype.slice
2844         $$19({ target: 'ArrayBuffer', proto: true, unsafe: true, forced: INCORRECT_SLICE }, {
2845           slice: function slice(start, end) {
2846             if (un$ArrayBufferSlice && end === undefined) {
2847               return un$ArrayBufferSlice(anObject$f(this), start); // FF fix
2848             }
2849             var length = anObject$f(this).byteLength;
2850             var first = toAbsoluteIndex$5(start, length);
2851             var fin = toAbsoluteIndex$5(end === undefined ? length : end, length);
2852             var result = new (speciesConstructor$4(this, ArrayBuffer$4))(toLength$8(fin - first));
2853             var viewSource = new DataView$2(this);
2854             var viewTarget = new DataView$2(result);
2855             var index = 0;
2856             while (first < fin) {
2857               setUint8(viewTarget, index++, getUint8(viewSource, first++));
2858             } return result;
2859           }
2860         });
2861
2862         var $$18 = _export;
2863         var ArrayBufferModule$1 = arrayBuffer;
2864         var NATIVE_ARRAY_BUFFER$1 = arrayBufferNative;
2865
2866         // `DataView` constructor
2867         // https://tc39.es/ecma262/#sec-dataview-constructor
2868         $$18({ global: true, forced: !NATIVE_ARRAY_BUFFER$1 }, {
2869           DataView: ArrayBufferModule$1.DataView
2870         });
2871
2872         var NATIVE_ARRAY_BUFFER = arrayBufferNative;
2873         var DESCRIPTORS$e = descriptors;
2874         var global$N = global$1m;
2875         var isCallable$9 = isCallable$r;
2876         var isObject$k = isObject$s;
2877         var hasOwn$9 = hasOwnProperty_1;
2878         var classof$7 = classof$d;
2879         var tryToString$2 = tryToString$5;
2880         var createNonEnumerableProperty$4 = createNonEnumerableProperty$b;
2881         var redefine$9 = redefine$h.exports;
2882         var defineProperty$6 = objectDefineProperty.f;
2883         var isPrototypeOf$5 = objectIsPrototypeOf;
2884         var getPrototypeOf$1 = objectGetPrototypeOf;
2885         var setPrototypeOf$4 = objectSetPrototypeOf;
2886         var wellKnownSymbol$g = wellKnownSymbol$t;
2887         var uid$1 = uid$5;
2888
2889         var Int8Array$3 = global$N.Int8Array;
2890         var Int8ArrayPrototype = Int8Array$3 && Int8Array$3.prototype;
2891         var Uint8ClampedArray = global$N.Uint8ClampedArray;
2892         var Uint8ClampedArrayPrototype = Uint8ClampedArray && Uint8ClampedArray.prototype;
2893         var TypedArray$1 = Int8Array$3 && getPrototypeOf$1(Int8Array$3);
2894         var TypedArrayPrototype$1 = Int8ArrayPrototype && getPrototypeOf$1(Int8ArrayPrototype);
2895         var ObjectPrototype$1 = Object.prototype;
2896         var TypeError$d = global$N.TypeError;
2897
2898         var TO_STRING_TAG = wellKnownSymbol$g('toStringTag');
2899         var TYPED_ARRAY_TAG$1 = uid$1('TYPED_ARRAY_TAG');
2900         var TYPED_ARRAY_CONSTRUCTOR$2 = uid$1('TYPED_ARRAY_CONSTRUCTOR');
2901         // Fixing native typed arrays in Opera Presto crashes the browser, see #595
2902         var NATIVE_ARRAY_BUFFER_VIEWS$3 = NATIVE_ARRAY_BUFFER && !!setPrototypeOf$4 && classof$7(global$N.opera) !== 'Opera';
2903         var TYPED_ARRAY_TAG_REQIRED = false;
2904         var NAME$1, Constructor, Prototype;
2905
2906         var TypedArrayConstructorsList = {
2907           Int8Array: 1,
2908           Uint8Array: 1,
2909           Uint8ClampedArray: 1,
2910           Int16Array: 2,
2911           Uint16Array: 2,
2912           Int32Array: 4,
2913           Uint32Array: 4,
2914           Float32Array: 4,
2915           Float64Array: 8
2916         };
2917
2918         var BigIntArrayConstructorsList = {
2919           BigInt64Array: 8,
2920           BigUint64Array: 8
2921         };
2922
2923         var isView = function isView(it) {
2924           if (!isObject$k(it)) return false;
2925           var klass = classof$7(it);
2926           return klass === 'DataView'
2927             || hasOwn$9(TypedArrayConstructorsList, klass)
2928             || hasOwn$9(BigIntArrayConstructorsList, klass);
2929         };
2930
2931         var isTypedArray$1 = function (it) {
2932           if (!isObject$k(it)) return false;
2933           var klass = classof$7(it);
2934           return hasOwn$9(TypedArrayConstructorsList, klass)
2935             || hasOwn$9(BigIntArrayConstructorsList, klass);
2936         };
2937
2938         var aTypedArray$m = function (it) {
2939           if (isTypedArray$1(it)) return it;
2940           throw TypeError$d('Target is not a typed array');
2941         };
2942
2943         var aTypedArrayConstructor$3 = function (C) {
2944           if (isCallable$9(C) && (!setPrototypeOf$4 || isPrototypeOf$5(TypedArray$1, C))) return C;
2945           throw TypeError$d(tryToString$2(C) + ' is not a typed array constructor');
2946         };
2947
2948         var exportTypedArrayMethod$n = function (KEY, property, forced) {
2949           if (!DESCRIPTORS$e) return;
2950           if (forced) for (var ARRAY in TypedArrayConstructorsList) {
2951             var TypedArrayConstructor = global$N[ARRAY];
2952             if (TypedArrayConstructor && hasOwn$9(TypedArrayConstructor.prototype, KEY)) try {
2953               delete TypedArrayConstructor.prototype[KEY];
2954             } catch (error) { /* empty */ }
2955           }
2956           if (!TypedArrayPrototype$1[KEY] || forced) {
2957             redefine$9(TypedArrayPrototype$1, KEY, forced ? property
2958               : NATIVE_ARRAY_BUFFER_VIEWS$3 && Int8ArrayPrototype[KEY] || property);
2959           }
2960         };
2961
2962         var exportTypedArrayStaticMethod$1 = function (KEY, property, forced) {
2963           var ARRAY, TypedArrayConstructor;
2964           if (!DESCRIPTORS$e) return;
2965           if (setPrototypeOf$4) {
2966             if (forced) for (ARRAY in TypedArrayConstructorsList) {
2967               TypedArrayConstructor = global$N[ARRAY];
2968               if (TypedArrayConstructor && hasOwn$9(TypedArrayConstructor, KEY)) try {
2969                 delete TypedArrayConstructor[KEY];
2970               } catch (error) { /* empty */ }
2971             }
2972             if (!TypedArray$1[KEY] || forced) {
2973               // V8 ~ Chrome 49-50 `%TypedArray%` methods are non-writable non-configurable
2974               try {
2975                 return redefine$9(TypedArray$1, KEY, forced ? property : NATIVE_ARRAY_BUFFER_VIEWS$3 && TypedArray$1[KEY] || property);
2976               } catch (error) { /* empty */ }
2977             } else return;
2978           }
2979           for (ARRAY in TypedArrayConstructorsList) {
2980             TypedArrayConstructor = global$N[ARRAY];
2981             if (TypedArrayConstructor && (!TypedArrayConstructor[KEY] || forced)) {
2982               redefine$9(TypedArrayConstructor, KEY, property);
2983             }
2984           }
2985         };
2986
2987         for (NAME$1 in TypedArrayConstructorsList) {
2988           Constructor = global$N[NAME$1];
2989           Prototype = Constructor && Constructor.prototype;
2990           if (Prototype) createNonEnumerableProperty$4(Prototype, TYPED_ARRAY_CONSTRUCTOR$2, Constructor);
2991           else NATIVE_ARRAY_BUFFER_VIEWS$3 = false;
2992         }
2993
2994         for (NAME$1 in BigIntArrayConstructorsList) {
2995           Constructor = global$N[NAME$1];
2996           Prototype = Constructor && Constructor.prototype;
2997           if (Prototype) createNonEnumerableProperty$4(Prototype, TYPED_ARRAY_CONSTRUCTOR$2, Constructor);
2998         }
2999
3000         // WebKit bug - typed arrays constructors prototype is Object.prototype
3001         if (!NATIVE_ARRAY_BUFFER_VIEWS$3 || !isCallable$9(TypedArray$1) || TypedArray$1 === Function.prototype) {
3002           // eslint-disable-next-line no-shadow -- safe
3003           TypedArray$1 = function TypedArray() {
3004             throw TypeError$d('Incorrect invocation');
3005           };
3006           if (NATIVE_ARRAY_BUFFER_VIEWS$3) for (NAME$1 in TypedArrayConstructorsList) {
3007             if (global$N[NAME$1]) setPrototypeOf$4(global$N[NAME$1], TypedArray$1);
3008           }
3009         }
3010
3011         if (!NATIVE_ARRAY_BUFFER_VIEWS$3 || !TypedArrayPrototype$1 || TypedArrayPrototype$1 === ObjectPrototype$1) {
3012           TypedArrayPrototype$1 = TypedArray$1.prototype;
3013           if (NATIVE_ARRAY_BUFFER_VIEWS$3) for (NAME$1 in TypedArrayConstructorsList) {
3014             if (global$N[NAME$1]) setPrototypeOf$4(global$N[NAME$1].prototype, TypedArrayPrototype$1);
3015           }
3016         }
3017
3018         // WebKit bug - one more object in Uint8ClampedArray prototype chain
3019         if (NATIVE_ARRAY_BUFFER_VIEWS$3 && getPrototypeOf$1(Uint8ClampedArrayPrototype) !== TypedArrayPrototype$1) {
3020           setPrototypeOf$4(Uint8ClampedArrayPrototype, TypedArrayPrototype$1);
3021         }
3022
3023         if (DESCRIPTORS$e && !hasOwn$9(TypedArrayPrototype$1, TO_STRING_TAG)) {
3024           TYPED_ARRAY_TAG_REQIRED = true;
3025           defineProperty$6(TypedArrayPrototype$1, TO_STRING_TAG, { get: function () {
3026             return isObject$k(this) ? this[TYPED_ARRAY_TAG$1] : undefined;
3027           } });
3028           for (NAME$1 in TypedArrayConstructorsList) if (global$N[NAME$1]) {
3029             createNonEnumerableProperty$4(global$N[NAME$1], TYPED_ARRAY_TAG$1, NAME$1);
3030           }
3031         }
3032
3033         var arrayBufferViewCore = {
3034           NATIVE_ARRAY_BUFFER_VIEWS: NATIVE_ARRAY_BUFFER_VIEWS$3,
3035           TYPED_ARRAY_CONSTRUCTOR: TYPED_ARRAY_CONSTRUCTOR$2,
3036           TYPED_ARRAY_TAG: TYPED_ARRAY_TAG_REQIRED && TYPED_ARRAY_TAG$1,
3037           aTypedArray: aTypedArray$m,
3038           aTypedArrayConstructor: aTypedArrayConstructor$3,
3039           exportTypedArrayMethod: exportTypedArrayMethod$n,
3040           exportTypedArrayStaticMethod: exportTypedArrayStaticMethod$1,
3041           isView: isView,
3042           isTypedArray: isTypedArray$1,
3043           TypedArray: TypedArray$1,
3044           TypedArrayPrototype: TypedArrayPrototype$1
3045         };
3046
3047         var $$17 = _export;
3048         var ArrayBufferViewCore$o = arrayBufferViewCore;
3049
3050         var NATIVE_ARRAY_BUFFER_VIEWS$2 = ArrayBufferViewCore$o.NATIVE_ARRAY_BUFFER_VIEWS;
3051
3052         // `ArrayBuffer.isView` method
3053         // https://tc39.es/ecma262/#sec-arraybuffer.isview
3054         $$17({ target: 'ArrayBuffer', stat: true, forced: !NATIVE_ARRAY_BUFFER_VIEWS$2 }, {
3055           isView: ArrayBufferViewCore$o.isView
3056         });
3057
3058         var getBuiltIn$4 = getBuiltIn$b;
3059         var definePropertyModule$2 = objectDefineProperty;
3060         var wellKnownSymbol$f = wellKnownSymbol$t;
3061         var DESCRIPTORS$d = descriptors;
3062
3063         var SPECIES$4 = wellKnownSymbol$f('species');
3064
3065         var setSpecies$5 = function (CONSTRUCTOR_NAME) {
3066           var Constructor = getBuiltIn$4(CONSTRUCTOR_NAME);
3067           var defineProperty = definePropertyModule$2.f;
3068
3069           if (DESCRIPTORS$d && Constructor && !Constructor[SPECIES$4]) {
3070             defineProperty(Constructor, SPECIES$4, {
3071               configurable: true,
3072               get: function () { return this; }
3073             });
3074           }
3075         };
3076
3077         var $$16 = _export;
3078         var global$M = global$1m;
3079         var arrayBufferModule = arrayBuffer;
3080         var setSpecies$4 = setSpecies$5;
3081
3082         var ARRAY_BUFFER = 'ArrayBuffer';
3083         var ArrayBuffer$3 = arrayBufferModule[ARRAY_BUFFER];
3084         var NativeArrayBuffer = global$M[ARRAY_BUFFER];
3085
3086         // `ArrayBuffer` constructor
3087         // https://tc39.es/ecma262/#sec-arraybuffer-constructor
3088         $$16({ global: true, forced: NativeArrayBuffer !== ArrayBuffer$3 }, {
3089           ArrayBuffer: ArrayBuffer$3
3090         });
3091
3092         setSpecies$4(ARRAY_BUFFER);
3093
3094         var fails$G = fails$S;
3095
3096         var arrayMethodIsStrict$9 = function (METHOD_NAME, argument) {
3097           var method = [][METHOD_NAME];
3098           return !!method && fails$G(function () {
3099             // eslint-disable-next-line no-useless-call,no-throw-literal -- required for testing
3100             method.call(null, argument || function () { throw 1; }, 1);
3101           });
3102         };
3103
3104         /* eslint-disable es/no-array-prototype-indexof -- required for testing */
3105         var $$15 = _export;
3106         var uncurryThis$C = functionUncurryThis;
3107         var $IndexOf = arrayIncludes.indexOf;
3108         var arrayMethodIsStrict$8 = arrayMethodIsStrict$9;
3109
3110         var un$IndexOf = uncurryThis$C([].indexOf);
3111
3112         var NEGATIVE_ZERO$1 = !!un$IndexOf && 1 / un$IndexOf([1], 1, -0) < 0;
3113         var STRICT_METHOD$8 = arrayMethodIsStrict$8('indexOf');
3114
3115         // `Array.prototype.indexOf` method
3116         // https://tc39.es/ecma262/#sec-array.prototype.indexof
3117         $$15({ target: 'Array', proto: true, forced: NEGATIVE_ZERO$1 || !STRICT_METHOD$8 }, {
3118           indexOf: function indexOf(searchElement /* , fromIndex = 0 */) {
3119             var fromIndex = arguments.length > 1 ? arguments[1] : undefined;
3120             return NEGATIVE_ZERO$1
3121               // convert -0 to +0
3122               ? un$IndexOf(this, searchElement, fromIndex) || 0
3123               : $IndexOf(this, searchElement, fromIndex);
3124           }
3125         });
3126
3127         var anObject$e = anObject$n;
3128
3129         // `RegExp.prototype.flags` getter implementation
3130         // https://tc39.es/ecma262/#sec-get-regexp.prototype.flags
3131         var regexpFlags$1 = function () {
3132           var that = anObject$e(this);
3133           var result = '';
3134           if (that.global) result += 'g';
3135           if (that.ignoreCase) result += 'i';
3136           if (that.multiline) result += 'm';
3137           if (that.dotAll) result += 's';
3138           if (that.unicode) result += 'u';
3139           if (that.sticky) result += 'y';
3140           return result;
3141         };
3142
3143         var regexpStickyHelpers = {};
3144
3145         var fails$F = fails$S;
3146         var global$L = global$1m;
3147
3148         // babel-minify and Closure Compiler transpiles RegExp('a', 'y') -> /a/y and it causes SyntaxError
3149         var $RegExp$2 = global$L.RegExp;
3150
3151         regexpStickyHelpers.UNSUPPORTED_Y = fails$F(function () {
3152           var re = $RegExp$2('a', 'y');
3153           re.lastIndex = 2;
3154           return re.exec('abcd') != null;
3155         });
3156
3157         regexpStickyHelpers.BROKEN_CARET = fails$F(function () {
3158           // https://bugzilla.mozilla.org/show_bug.cgi?id=773687
3159           var re = $RegExp$2('^r', 'gy');
3160           re.lastIndex = 2;
3161           return re.exec('str') != null;
3162         });
3163
3164         var fails$E = fails$S;
3165         var global$K = global$1m;
3166
3167         // babel-minify and Closure Compiler transpiles RegExp('.', 's') -> /./s and it causes SyntaxError
3168         var $RegExp$1 = global$K.RegExp;
3169
3170         var regexpUnsupportedDotAll = fails$E(function () {
3171           var re = $RegExp$1('.', 's');
3172           return !(re.dotAll && re.exec('\n') && re.flags === 's');
3173         });
3174
3175         var fails$D = fails$S;
3176         var global$J = global$1m;
3177
3178         // babel-minify and Closure Compiler transpiles RegExp('(?<a>b)', 'g') -> /(?<a>b)/g and it causes SyntaxError
3179         var $RegExp = global$J.RegExp;
3180
3181         var regexpUnsupportedNcg = fails$D(function () {
3182           var re = $RegExp('(?<a>b)', 'g');
3183           return re.exec('b').groups.a !== 'b' ||
3184             'b'.replace(re, '$<a>c') !== 'bc';
3185         });
3186
3187         /* eslint-disable regexp/no-empty-capturing-group, regexp/no-empty-group, regexp/no-lazy-ends -- testing */
3188         /* eslint-disable regexp/no-useless-quantifier -- testing */
3189         var call$i = functionCall;
3190         var uncurryThis$B = functionUncurryThis;
3191         var toString$g = toString$k;
3192         var regexpFlags = regexpFlags$1;
3193         var stickyHelpers$2 = regexpStickyHelpers;
3194         var shared = shared$5.exports;
3195         var create$8 = objectCreate;
3196         var getInternalState$2 = internalState.get;
3197         var UNSUPPORTED_DOT_ALL$1 = regexpUnsupportedDotAll;
3198         var UNSUPPORTED_NCG$1 = regexpUnsupportedNcg;
3199
3200         var nativeReplace = shared('native-string-replace', String.prototype.replace);
3201         var nativeExec = RegExp.prototype.exec;
3202         var patchedExec = nativeExec;
3203         var charAt$6 = uncurryThis$B(''.charAt);
3204         var indexOf = uncurryThis$B(''.indexOf);
3205         var replace$7 = uncurryThis$B(''.replace);
3206         var stringSlice$9 = uncurryThis$B(''.slice);
3207
3208         var UPDATES_LAST_INDEX_WRONG = (function () {
3209           var re1 = /a/;
3210           var re2 = /b*/g;
3211           call$i(nativeExec, re1, 'a');
3212           call$i(nativeExec, re2, 'a');
3213           return re1.lastIndex !== 0 || re2.lastIndex !== 0;
3214         })();
3215
3216         var UNSUPPORTED_Y$2 = stickyHelpers$2.UNSUPPORTED_Y || stickyHelpers$2.BROKEN_CARET;
3217
3218         // nonparticipating capturing group, copied from es5-shim's String#split patch.
3219         var NPCG_INCLUDED = /()??/.exec('')[1] !== undefined;
3220
3221         var PATCH = UPDATES_LAST_INDEX_WRONG || NPCG_INCLUDED || UNSUPPORTED_Y$2 || UNSUPPORTED_DOT_ALL$1 || UNSUPPORTED_NCG$1;
3222
3223         if (PATCH) {
3224           // eslint-disable-next-line max-statements -- TODO
3225           patchedExec = function exec(string) {
3226             var re = this;
3227             var state = getInternalState$2(re);
3228             var str = toString$g(string);
3229             var raw = state.raw;
3230             var result, reCopy, lastIndex, match, i, object, group;
3231
3232             if (raw) {
3233               raw.lastIndex = re.lastIndex;
3234               result = call$i(patchedExec, raw, str);
3235               re.lastIndex = raw.lastIndex;
3236               return result;
3237             }
3238
3239             var groups = state.groups;
3240             var sticky = UNSUPPORTED_Y$2 && re.sticky;
3241             var flags = call$i(regexpFlags, re);
3242             var source = re.source;
3243             var charsAdded = 0;
3244             var strCopy = str;
3245
3246             if (sticky) {
3247               flags = replace$7(flags, 'y', '');
3248               if (indexOf(flags, 'g') === -1) {
3249                 flags += 'g';
3250               }
3251
3252               strCopy = stringSlice$9(str, re.lastIndex);
3253               // Support anchored sticky behavior.
3254               if (re.lastIndex > 0 && (!re.multiline || re.multiline && charAt$6(str, re.lastIndex - 1) !== '\n')) {
3255                 source = '(?: ' + source + ')';
3256                 strCopy = ' ' + strCopy;
3257                 charsAdded++;
3258               }
3259               // ^(? + rx + ) is needed, in combination with some str slicing, to
3260               // simulate the 'y' flag.
3261               reCopy = new RegExp('^(?:' + source + ')', flags);
3262             }
3263
3264             if (NPCG_INCLUDED) {
3265               reCopy = new RegExp('^' + source + '$(?!\\s)', flags);
3266             }
3267             if (UPDATES_LAST_INDEX_WRONG) lastIndex = re.lastIndex;
3268
3269             match = call$i(nativeExec, sticky ? reCopy : re, strCopy);
3270
3271             if (sticky) {
3272               if (match) {
3273                 match.input = stringSlice$9(match.input, charsAdded);
3274                 match[0] = stringSlice$9(match[0], charsAdded);
3275                 match.index = re.lastIndex;
3276                 re.lastIndex += match[0].length;
3277               } else re.lastIndex = 0;
3278             } else if (UPDATES_LAST_INDEX_WRONG && match) {
3279               re.lastIndex = re.global ? match.index + match[0].length : lastIndex;
3280             }
3281             if (NPCG_INCLUDED && match && match.length > 1) {
3282               // Fix browsers whose `exec` methods don't consistently return `undefined`
3283               // for NPCG, like IE8. NOTE: This doesn' work for /(.?)?/
3284               call$i(nativeReplace, match[0], reCopy, function () {
3285                 for (i = 1; i < arguments.length - 2; i++) {
3286                   if (arguments[i] === undefined) match[i] = undefined;
3287                 }
3288               });
3289             }
3290
3291             if (match && groups) {
3292               match.groups = object = create$8(null);
3293               for (i = 0; i < groups.length; i++) {
3294                 group = groups[i];
3295                 object[group[0]] = match[group[1]];
3296               }
3297             }
3298
3299             return match;
3300           };
3301         }
3302
3303         var regexpExec$3 = patchedExec;
3304
3305         var $$14 = _export;
3306         var exec$5 = regexpExec$3;
3307
3308         // `RegExp.prototype.exec` method
3309         // https://tc39.es/ecma262/#sec-regexp.prototype.exec
3310         $$14({ target: 'RegExp', proto: true, forced: /./.exec !== exec$5 }, {
3311           exec: exec$5
3312         });
3313
3314         var fails$C = fails$S;
3315         var wellKnownSymbol$e = wellKnownSymbol$t;
3316         var V8_VERSION$2 = engineV8Version;
3317
3318         var SPECIES$3 = wellKnownSymbol$e('species');
3319
3320         var arrayMethodHasSpeciesSupport$5 = function (METHOD_NAME) {
3321           // We can't use this feature detection in V8 since it causes
3322           // deoptimization and serious performance degradation
3323           // https://github.com/zloirock/core-js/issues/677
3324           return V8_VERSION$2 >= 51 || !fails$C(function () {
3325             var array = [];
3326             var constructor = array.constructor = {};
3327             constructor[SPECIES$3] = function () {
3328               return { foo: 1 };
3329             };
3330             return array[METHOD_NAME](Boolean).foo !== 1;
3331           });
3332         };
3333
3334         var $$13 = _export;
3335         var $map$1 = arrayIteration.map;
3336         var arrayMethodHasSpeciesSupport$4 = arrayMethodHasSpeciesSupport$5;
3337
3338         var HAS_SPECIES_SUPPORT$3 = arrayMethodHasSpeciesSupport$4('map');
3339
3340         // `Array.prototype.map` method
3341         // https://tc39.es/ecma262/#sec-array.prototype.map
3342         // with adding support of @@species
3343         $$13({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$3 }, {
3344           map: function map(callbackfn /* , thisArg */) {
3345             return $map$1(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
3346           }
3347         });
3348
3349         var $forEach$1 = arrayIteration.forEach;
3350         var arrayMethodIsStrict$7 = arrayMethodIsStrict$9;
3351
3352         var STRICT_METHOD$7 = arrayMethodIsStrict$7('forEach');
3353
3354         // `Array.prototype.forEach` method implementation
3355         // https://tc39.es/ecma262/#sec-array.prototype.foreach
3356         var arrayForEach = !STRICT_METHOD$7 ? function forEach(callbackfn /* , thisArg */) {
3357           return $forEach$1(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
3358         // eslint-disable-next-line es/no-array-prototype-foreach -- safe
3359         } : [].forEach;
3360
3361         var $$12 = _export;
3362         var forEach$3 = arrayForEach;
3363
3364         // `Array.prototype.forEach` method
3365         // https://tc39.es/ecma262/#sec-array.prototype.foreach
3366         // eslint-disable-next-line es/no-array-prototype-foreach -- safe
3367         $$12({ target: 'Array', proto: true, forced: [].forEach != forEach$3 }, {
3368           forEach: forEach$3
3369         });
3370
3371         var global$I = global$1m;
3372         var DOMIterables = domIterables;
3373         var DOMTokenListPrototype = domTokenListPrototype;
3374         var forEach$2 = arrayForEach;
3375         var createNonEnumerableProperty$3 = createNonEnumerableProperty$b;
3376
3377         var handlePrototype = function (CollectionPrototype) {
3378           // some Chrome versions have non-configurable methods on DOMTokenList
3379           if (CollectionPrototype && CollectionPrototype.forEach !== forEach$2) try {
3380             createNonEnumerableProperty$3(CollectionPrototype, 'forEach', forEach$2);
3381           } catch (error) {
3382             CollectionPrototype.forEach = forEach$2;
3383           }
3384         };
3385
3386         for (var COLLECTION_NAME in DOMIterables) {
3387           if (DOMIterables[COLLECTION_NAME]) {
3388             handlePrototype(global$I[COLLECTION_NAME] && global$I[COLLECTION_NAME].prototype);
3389           }
3390         }
3391
3392         handlePrototype(DOMTokenListPrototype);
3393
3394         var $$11 = _export;
3395         var isArray$5 = isArray$8;
3396
3397         // `Array.isArray` method
3398         // https://tc39.es/ecma262/#sec-array.isarray
3399         $$11({ target: 'Array', stat: true }, {
3400           isArray: isArray$5
3401         });
3402
3403         var $$10 = _export;
3404         var fails$B = fails$S;
3405         var getOwnPropertyNames$3 = objectGetOwnPropertyNamesExternal.f;
3406
3407         // eslint-disable-next-line es/no-object-getownpropertynames -- required for testing
3408         var FAILS_ON_PRIMITIVES$5 = fails$B(function () { return !Object.getOwnPropertyNames(1); });
3409
3410         // `Object.getOwnPropertyNames` method
3411         // https://tc39.es/ecma262/#sec-object.getownpropertynames
3412         $$10({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES$5 }, {
3413           getOwnPropertyNames: getOwnPropertyNames$3
3414         });
3415
3416         var global$H = global$1m;
3417
3418         var nativePromiseConstructor = global$H.Promise;
3419
3420         var wellKnownSymbol$d = wellKnownSymbol$t;
3421         var Iterators$1 = iterators;
3422
3423         var ITERATOR$7 = wellKnownSymbol$d('iterator');
3424         var ArrayPrototype = Array.prototype;
3425
3426         // check on default Array iterator
3427         var isArrayIteratorMethod$3 = function (it) {
3428           return it !== undefined && (Iterators$1.Array === it || ArrayPrototype[ITERATOR$7] === it);
3429         };
3430
3431         var classof$6 = classof$d;
3432         var getMethod$5 = getMethod$7;
3433         var Iterators = iterators;
3434         var wellKnownSymbol$c = wellKnownSymbol$t;
3435
3436         var ITERATOR$6 = wellKnownSymbol$c('iterator');
3437
3438         var getIteratorMethod$5 = function (it) {
3439           if (it != undefined) return getMethod$5(it, ITERATOR$6)
3440             || getMethod$5(it, '@@iterator')
3441             || Iterators[classof$6(it)];
3442         };
3443
3444         var global$G = global$1m;
3445         var call$h = functionCall;
3446         var aCallable$7 = aCallable$a;
3447         var anObject$d = anObject$n;
3448         var tryToString$1 = tryToString$5;
3449         var getIteratorMethod$4 = getIteratorMethod$5;
3450
3451         var TypeError$c = global$G.TypeError;
3452
3453         var getIterator$4 = function (argument, usingIterator) {
3454           var iteratorMethod = arguments.length < 2 ? getIteratorMethod$4(argument) : usingIterator;
3455           if (aCallable$7(iteratorMethod)) return anObject$d(call$h(iteratorMethod, argument));
3456           throw TypeError$c(tryToString$1(argument) + ' is not iterable');
3457         };
3458
3459         var call$g = functionCall;
3460         var anObject$c = anObject$n;
3461         var getMethod$4 = getMethod$7;
3462
3463         var iteratorClose$2 = function (iterator, kind, value) {
3464           var innerResult, innerError;
3465           anObject$c(iterator);
3466           try {
3467             innerResult = getMethod$4(iterator, 'return');
3468             if (!innerResult) {
3469               if (kind === 'throw') throw value;
3470               return value;
3471             }
3472             innerResult = call$g(innerResult, iterator);
3473           } catch (error) {
3474             innerError = true;
3475             innerResult = error;
3476           }
3477           if (kind === 'throw') throw value;
3478           if (innerError) throw innerResult;
3479           anObject$c(innerResult);
3480           return value;
3481         };
3482
3483         var global$F = global$1m;
3484         var bind$d = functionBindContext;
3485         var call$f = functionCall;
3486         var anObject$b = anObject$n;
3487         var tryToString = tryToString$5;
3488         var isArrayIteratorMethod$2 = isArrayIteratorMethod$3;
3489         var lengthOfArrayLike$c = lengthOfArrayLike$g;
3490         var isPrototypeOf$4 = objectIsPrototypeOf;
3491         var getIterator$3 = getIterator$4;
3492         var getIteratorMethod$3 = getIteratorMethod$5;
3493         var iteratorClose$1 = iteratorClose$2;
3494
3495         var TypeError$b = global$F.TypeError;
3496
3497         var Result = function (stopped, result) {
3498           this.stopped = stopped;
3499           this.result = result;
3500         };
3501
3502         var ResultPrototype = Result.prototype;
3503
3504         var iterate$3 = function (iterable, unboundFunction, options) {
3505           var that = options && options.that;
3506           var AS_ENTRIES = !!(options && options.AS_ENTRIES);
3507           var IS_ITERATOR = !!(options && options.IS_ITERATOR);
3508           var INTERRUPTED = !!(options && options.INTERRUPTED);
3509           var fn = bind$d(unboundFunction, that);
3510           var iterator, iterFn, index, length, result, next, step;
3511
3512           var stop = function (condition) {
3513             if (iterator) iteratorClose$1(iterator, 'normal', condition);
3514             return new Result(true, condition);
3515           };
3516
3517           var callFn = function (value) {
3518             if (AS_ENTRIES) {
3519               anObject$b(value);
3520               return INTERRUPTED ? fn(value[0], value[1], stop) : fn(value[0], value[1]);
3521             } return INTERRUPTED ? fn(value, stop) : fn(value);
3522           };
3523
3524           if (IS_ITERATOR) {
3525             iterator = iterable;
3526           } else {
3527             iterFn = getIteratorMethod$3(iterable);
3528             if (!iterFn) throw TypeError$b(tryToString(iterable) + ' is not iterable');
3529             // optimisation for array iterators
3530             if (isArrayIteratorMethod$2(iterFn)) {
3531               for (index = 0, length = lengthOfArrayLike$c(iterable); length > index; index++) {
3532                 result = callFn(iterable[index]);
3533                 if (result && isPrototypeOf$4(ResultPrototype, result)) return result;
3534               } return new Result(false);
3535             }
3536             iterator = getIterator$3(iterable, iterFn);
3537           }
3538
3539           next = iterator.next;
3540           while (!(step = call$f(next, iterator)).done) {
3541             try {
3542               result = callFn(step.value);
3543             } catch (error) {
3544               iteratorClose$1(iterator, 'throw', error);
3545             }
3546             if (typeof result == 'object' && result && isPrototypeOf$4(ResultPrototype, result)) return result;
3547           } return new Result(false);
3548         };
3549
3550         var wellKnownSymbol$b = wellKnownSymbol$t;
3551
3552         var ITERATOR$5 = wellKnownSymbol$b('iterator');
3553         var SAFE_CLOSING = false;
3554
3555         try {
3556           var called = 0;
3557           var iteratorWithReturn = {
3558             next: function () {
3559               return { done: !!called++ };
3560             },
3561             'return': function () {
3562               SAFE_CLOSING = true;
3563             }
3564           };
3565           iteratorWithReturn[ITERATOR$5] = function () {
3566             return this;
3567           };
3568           // eslint-disable-next-line es/no-array-from, no-throw-literal -- required for testing
3569           Array.from(iteratorWithReturn, function () { throw 2; });
3570         } catch (error) { /* empty */ }
3571
3572         var checkCorrectnessOfIteration$4 = function (exec, SKIP_CLOSING) {
3573           if (!SKIP_CLOSING && !SAFE_CLOSING) return false;
3574           var ITERATION_SUPPORT = false;
3575           try {
3576             var object = {};
3577             object[ITERATOR$5] = function () {
3578               return {
3579                 next: function () {
3580                   return { done: ITERATION_SUPPORT = true };
3581                 }
3582               };
3583             };
3584             exec(object);
3585           } catch (error) { /* empty */ }
3586           return ITERATION_SUPPORT;
3587         };
3588
3589         var userAgent$6 = engineUserAgent;
3590
3591         var engineIsIos = /(?:ipad|iphone|ipod).*applewebkit/i.test(userAgent$6);
3592
3593         var classof$5 = classofRaw$1;
3594         var global$E = global$1m;
3595
3596         var engineIsNode = classof$5(global$E.process) == 'process';
3597
3598         var global$D = global$1m;
3599         var apply$7 = functionApply;
3600         var bind$c = functionBindContext;
3601         var isCallable$8 = isCallable$r;
3602         var hasOwn$8 = hasOwnProperty_1;
3603         var fails$A = fails$S;
3604         var html = html$2;
3605         var arraySlice$8 = arraySlice$c;
3606         var createElement = documentCreateElement$2;
3607         var IS_IOS$1 = engineIsIos;
3608         var IS_NODE$4 = engineIsNode;
3609
3610         var set$2 = global$D.setImmediate;
3611         var clear = global$D.clearImmediate;
3612         var process$3 = global$D.process;
3613         var Dispatch$1 = global$D.Dispatch;
3614         var Function$3 = global$D.Function;
3615         var MessageChannel = global$D.MessageChannel;
3616         var String$2 = global$D.String;
3617         var counter = 0;
3618         var queue = {};
3619         var ONREADYSTATECHANGE = 'onreadystatechange';
3620         var location$1, defer, channel, port;
3621
3622         try {
3623           // Deno throws a ReferenceError on `location` access without `--location` flag
3624           location$1 = global$D.location;
3625         } catch (error) { /* empty */ }
3626
3627         var run = function (id) {
3628           if (hasOwn$8(queue, id)) {
3629             var fn = queue[id];
3630             delete queue[id];
3631             fn();
3632           }
3633         };
3634
3635         var runner = function (id) {
3636           return function () {
3637             run(id);
3638           };
3639         };
3640
3641         var listener = function (event) {
3642           run(event.data);
3643         };
3644
3645         var post = function (id) {
3646           // old engines have not location.origin
3647           global$D.postMessage(String$2(id), location$1.protocol + '//' + location$1.host);
3648         };
3649
3650         // Node.js 0.9+ & IE10+ has setImmediate, otherwise:
3651         if (!set$2 || !clear) {
3652           set$2 = function setImmediate(fn) {
3653             var args = arraySlice$8(arguments, 1);
3654             queue[++counter] = function () {
3655               apply$7(isCallable$8(fn) ? fn : Function$3(fn), undefined, args);
3656             };
3657             defer(counter);
3658             return counter;
3659           };
3660           clear = function clearImmediate(id) {
3661             delete queue[id];
3662           };
3663           // Node.js 0.8-
3664           if (IS_NODE$4) {
3665             defer = function (id) {
3666               process$3.nextTick(runner(id));
3667             };
3668           // Sphere (JS game engine) Dispatch API
3669           } else if (Dispatch$1 && Dispatch$1.now) {
3670             defer = function (id) {
3671               Dispatch$1.now(runner(id));
3672             };
3673           // Browsers with MessageChannel, includes WebWorkers
3674           // except iOS - https://github.com/zloirock/core-js/issues/624
3675           } else if (MessageChannel && !IS_IOS$1) {
3676             channel = new MessageChannel();
3677             port = channel.port2;
3678             channel.port1.onmessage = listener;
3679             defer = bind$c(port.postMessage, port);
3680           // Browsers with postMessage, skip WebWorkers
3681           // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'
3682           } else if (
3683             global$D.addEventListener &&
3684             isCallable$8(global$D.postMessage) &&
3685             !global$D.importScripts &&
3686             location$1 && location$1.protocol !== 'file:' &&
3687             !fails$A(post)
3688           ) {
3689             defer = post;
3690             global$D.addEventListener('message', listener, false);
3691           // IE8-
3692           } else if (ONREADYSTATECHANGE in createElement('script')) {
3693             defer = function (id) {
3694               html.appendChild(createElement('script'))[ONREADYSTATECHANGE] = function () {
3695                 html.removeChild(this);
3696                 run(id);
3697               };
3698             };
3699           // Rest old browsers
3700           } else {
3701             defer = function (id) {
3702               setTimeout(runner(id), 0);
3703             };
3704           }
3705         }
3706
3707         var task$1 = {
3708           set: set$2,
3709           clear: clear
3710         };
3711
3712         var userAgent$5 = engineUserAgent;
3713         var global$C = global$1m;
3714
3715         var engineIsIosPebble = /ipad|iphone|ipod/i.test(userAgent$5) && global$C.Pebble !== undefined;
3716
3717         var userAgent$4 = engineUserAgent;
3718
3719         var engineIsWebosWebkit = /web0s(?!.*chrome)/i.test(userAgent$4);
3720
3721         var global$B = global$1m;
3722         var bind$b = functionBindContext;
3723         var getOwnPropertyDescriptor$3 = objectGetOwnPropertyDescriptor.f;
3724         var macrotask = task$1.set;
3725         var IS_IOS = engineIsIos;
3726         var IS_IOS_PEBBLE = engineIsIosPebble;
3727         var IS_WEBOS_WEBKIT = engineIsWebosWebkit;
3728         var IS_NODE$3 = engineIsNode;
3729
3730         var MutationObserver = global$B.MutationObserver || global$B.WebKitMutationObserver;
3731         var document$2 = global$B.document;
3732         var process$2 = global$B.process;
3733         var Promise$1 = global$B.Promise;
3734         // Node.js 11 shows ExperimentalWarning on getting `queueMicrotask`
3735         var queueMicrotaskDescriptor = getOwnPropertyDescriptor$3(global$B, 'queueMicrotask');
3736         var queueMicrotask = queueMicrotaskDescriptor && queueMicrotaskDescriptor.value;
3737
3738         var flush, head, last, notify$1, toggle, node, promise, then;
3739
3740         // modern engines have queueMicrotask method
3741         if (!queueMicrotask) {
3742           flush = function () {
3743             var parent, fn;
3744             if (IS_NODE$3 && (parent = process$2.domain)) parent.exit();
3745             while (head) {
3746               fn = head.fn;
3747               head = head.next;
3748               try {
3749                 fn();
3750               } catch (error) {
3751                 if (head) notify$1();
3752                 else last = undefined;
3753                 throw error;
3754               }
3755             } last = undefined;
3756             if (parent) parent.enter();
3757           };
3758
3759           // browsers with MutationObserver, except iOS - https://github.com/zloirock/core-js/issues/339
3760           // also except WebOS Webkit https://github.com/zloirock/core-js/issues/898
3761           if (!IS_IOS && !IS_NODE$3 && !IS_WEBOS_WEBKIT && MutationObserver && document$2) {
3762             toggle = true;
3763             node = document$2.createTextNode('');
3764             new MutationObserver(flush).observe(node, { characterData: true });
3765             notify$1 = function () {
3766               node.data = toggle = !toggle;
3767             };
3768           // environments with maybe non-completely correct, but existent Promise
3769           } else if (!IS_IOS_PEBBLE && Promise$1 && Promise$1.resolve) {
3770             // Promise.resolve without an argument throws an error in LG WebOS 2
3771             promise = Promise$1.resolve(undefined);
3772             // workaround of WebKit ~ iOS Safari 10.1 bug
3773             promise.constructor = Promise$1;
3774             then = bind$b(promise.then, promise);
3775             notify$1 = function () {
3776               then(flush);
3777             };
3778           // Node.js without promises
3779           } else if (IS_NODE$3) {
3780             notify$1 = function () {
3781               process$2.nextTick(flush);
3782             };
3783           // for other environments - macrotask based on:
3784           // - setImmediate
3785           // - MessageChannel
3786           // - window.postMessag
3787           // - onreadystatechange
3788           // - setTimeout
3789           } else {
3790             // strange IE + webpack dev server bug - use .bind(global)
3791             macrotask = bind$b(macrotask, global$B);
3792             notify$1 = function () {
3793               macrotask(flush);
3794             };
3795           }
3796         }
3797
3798         var microtask$1 = queueMicrotask || function (fn) {
3799           var task = { fn: fn, next: undefined };
3800           if (last) last.next = task;
3801           if (!head) {
3802             head = task;
3803             notify$1();
3804           } last = task;
3805         };
3806
3807         var newPromiseCapability$2 = {};
3808
3809         var aCallable$6 = aCallable$a;
3810
3811         var PromiseCapability = function (C) {
3812           var resolve, reject;
3813           this.promise = new C(function ($$resolve, $$reject) {
3814             if (resolve !== undefined || reject !== undefined) throw TypeError('Bad Promise constructor');
3815             resolve = $$resolve;
3816             reject = $$reject;
3817           });
3818           this.resolve = aCallable$6(resolve);
3819           this.reject = aCallable$6(reject);
3820         };
3821
3822         // `NewPromiseCapability` abstract operation
3823         // https://tc39.es/ecma262/#sec-newpromisecapability
3824         newPromiseCapability$2.f = function (C) {
3825           return new PromiseCapability(C);
3826         };
3827
3828         var anObject$a = anObject$n;
3829         var isObject$j = isObject$s;
3830         var newPromiseCapability$1 = newPromiseCapability$2;
3831
3832         var promiseResolve$2 = function (C, x) {
3833           anObject$a(C);
3834           if (isObject$j(x) && x.constructor === C) return x;
3835           var promiseCapability = newPromiseCapability$1.f(C);
3836           var resolve = promiseCapability.resolve;
3837           resolve(x);
3838           return promiseCapability.promise;
3839         };
3840
3841         var global$A = global$1m;
3842
3843         var hostReportErrors$1 = function (a, b) {
3844           var console = global$A.console;
3845           if (console && console.error) {
3846             arguments.length == 1 ? console.error(a) : console.error(a, b);
3847           }
3848         };
3849
3850         var perform$1 = function (exec) {
3851           try {
3852             return { error: false, value: exec() };
3853           } catch (error) {
3854             return { error: true, value: error };
3855           }
3856         };
3857
3858         var engineIsBrowser = typeof window == 'object';
3859
3860         var $$$ = _export;
3861         var global$z = global$1m;
3862         var getBuiltIn$3 = getBuiltIn$b;
3863         var call$e = functionCall;
3864         var NativePromise$1 = nativePromiseConstructor;
3865         var redefine$8 = redefine$h.exports;
3866         var redefineAll$2 = redefineAll$4;
3867         var setPrototypeOf$3 = objectSetPrototypeOf;
3868         var setToStringTag$5 = setToStringTag$a;
3869         var setSpecies$3 = setSpecies$5;
3870         var aCallable$5 = aCallable$a;
3871         var isCallable$7 = isCallable$r;
3872         var isObject$i = isObject$s;
3873         var anInstance$5 = anInstance$7;
3874         var inspectSource = inspectSource$4;
3875         var iterate$2 = iterate$3;
3876         var checkCorrectnessOfIteration$3 = checkCorrectnessOfIteration$4;
3877         var speciesConstructor$3 = speciesConstructor$5;
3878         var task = task$1.set;
3879         var microtask = microtask$1;
3880         var promiseResolve$1 = promiseResolve$2;
3881         var hostReportErrors = hostReportErrors$1;
3882         var newPromiseCapabilityModule = newPromiseCapability$2;
3883         var perform = perform$1;
3884         var InternalStateModule$4 = internalState;
3885         var isForced$3 = isForced_1;
3886         var wellKnownSymbol$a = wellKnownSymbol$t;
3887         var IS_BROWSER = engineIsBrowser;
3888         var IS_NODE$2 = engineIsNode;
3889         var V8_VERSION$1 = engineV8Version;
3890
3891         var SPECIES$2 = wellKnownSymbol$a('species');
3892         var PROMISE = 'Promise';
3893
3894         var getInternalState$1 = InternalStateModule$4.get;
3895         var setInternalState$4 = InternalStateModule$4.set;
3896         var getInternalPromiseState = InternalStateModule$4.getterFor(PROMISE);
3897         var NativePromisePrototype = NativePromise$1 && NativePromise$1.prototype;
3898         var PromiseConstructor = NativePromise$1;
3899         var PromisePrototype = NativePromisePrototype;
3900         var TypeError$a = global$z.TypeError;
3901         var document$1 = global$z.document;
3902         var process$1 = global$z.process;
3903         var newPromiseCapability = newPromiseCapabilityModule.f;
3904         var newGenericPromiseCapability = newPromiseCapability;
3905
3906         var DISPATCH_EVENT = !!(document$1 && document$1.createEvent && global$z.dispatchEvent);
3907         var NATIVE_REJECTION_EVENT = isCallable$7(global$z.PromiseRejectionEvent);
3908         var UNHANDLED_REJECTION = 'unhandledrejection';
3909         var REJECTION_HANDLED = 'rejectionhandled';
3910         var PENDING = 0;
3911         var FULFILLED = 1;
3912         var REJECTED = 2;
3913         var HANDLED = 1;
3914         var UNHANDLED = 2;
3915         var SUBCLASSING = false;
3916
3917         var Internal, OwnPromiseCapability, PromiseWrapper, nativeThen;
3918
3919         var FORCED$h = isForced$3(PROMISE, function () {
3920           var PROMISE_CONSTRUCTOR_SOURCE = inspectSource(PromiseConstructor);
3921           var GLOBAL_CORE_JS_PROMISE = PROMISE_CONSTRUCTOR_SOURCE !== String(PromiseConstructor);
3922           // V8 6.6 (Node 10 and Chrome 66) have a bug with resolving custom thenables
3923           // https://bugs.chromium.org/p/chromium/issues/detail?id=830565
3924           // We can't detect it synchronously, so just check versions
3925           if (!GLOBAL_CORE_JS_PROMISE && V8_VERSION$1 === 66) return true;
3926           // We can't use @@species feature detection in V8 since it causes
3927           // deoptimization and performance degradation
3928           // https://github.com/zloirock/core-js/issues/679
3929           if (V8_VERSION$1 >= 51 && /native code/.test(PROMISE_CONSTRUCTOR_SOURCE)) return false;
3930           // Detect correctness of subclassing with @@species support
3931           var promise = new PromiseConstructor(function (resolve) { resolve(1); });
3932           var FakePromise = function (exec) {
3933             exec(function () { /* empty */ }, function () { /* empty */ });
3934           };
3935           var constructor = promise.constructor = {};
3936           constructor[SPECIES$2] = FakePromise;
3937           SUBCLASSING = promise.then(function () { /* empty */ }) instanceof FakePromise;
3938           if (!SUBCLASSING) return true;
3939           // Unhandled rejections tracking support, NodeJS Promise without it fails @@species test
3940           return !GLOBAL_CORE_JS_PROMISE && IS_BROWSER && !NATIVE_REJECTION_EVENT;
3941         });
3942
3943         var INCORRECT_ITERATION$1 = FORCED$h || !checkCorrectnessOfIteration$3(function (iterable) {
3944           PromiseConstructor.all(iterable)['catch'](function () { /* empty */ });
3945         });
3946
3947         // helpers
3948         var isThenable = function (it) {
3949           var then;
3950           return isObject$i(it) && isCallable$7(then = it.then) ? then : false;
3951         };
3952
3953         var notify = function (state, isReject) {
3954           if (state.notified) return;
3955           state.notified = true;
3956           var chain = state.reactions;
3957           microtask(function () {
3958             var value = state.value;
3959             var ok = state.state == FULFILLED;
3960             var index = 0;
3961             // variable length - can't use forEach
3962             while (chain.length > index) {
3963               var reaction = chain[index++];
3964               var handler = ok ? reaction.ok : reaction.fail;
3965               var resolve = reaction.resolve;
3966               var reject = reaction.reject;
3967               var domain = reaction.domain;
3968               var result, then, exited;
3969               try {
3970                 if (handler) {
3971                   if (!ok) {
3972                     if (state.rejection === UNHANDLED) onHandleUnhandled(state);
3973                     state.rejection = HANDLED;
3974                   }
3975                   if (handler === true) result = value;
3976                   else {
3977                     if (domain) domain.enter();
3978                     result = handler(value); // can throw
3979                     if (domain) {
3980                       domain.exit();
3981                       exited = true;
3982                     }
3983                   }
3984                   if (result === reaction.promise) {
3985                     reject(TypeError$a('Promise-chain cycle'));
3986                   } else if (then = isThenable(result)) {
3987                     call$e(then, result, resolve, reject);
3988                   } else resolve(result);
3989                 } else reject(value);
3990               } catch (error) {
3991                 if (domain && !exited) domain.exit();
3992                 reject(error);
3993               }
3994             }
3995             state.reactions = [];
3996             state.notified = false;
3997             if (isReject && !state.rejection) onUnhandled(state);
3998           });
3999         };
4000
4001         var dispatchEvent$1 = function (name, promise, reason) {
4002           var event, handler;
4003           if (DISPATCH_EVENT) {
4004             event = document$1.createEvent('Event');
4005             event.promise = promise;
4006             event.reason = reason;
4007             event.initEvent(name, false, true);
4008             global$z.dispatchEvent(event);
4009           } else event = { promise: promise, reason: reason };
4010           if (!NATIVE_REJECTION_EVENT && (handler = global$z['on' + name])) handler(event);
4011           else if (name === UNHANDLED_REJECTION) hostReportErrors('Unhandled promise rejection', reason);
4012         };
4013
4014         var onUnhandled = function (state) {
4015           call$e(task, global$z, function () {
4016             var promise = state.facade;
4017             var value = state.value;
4018             var IS_UNHANDLED = isUnhandled(state);
4019             var result;
4020             if (IS_UNHANDLED) {
4021               result = perform(function () {
4022                 if (IS_NODE$2) {
4023                   process$1.emit('unhandledRejection', value, promise);
4024                 } else dispatchEvent$1(UNHANDLED_REJECTION, promise, value);
4025               });
4026               // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should
4027               state.rejection = IS_NODE$2 || isUnhandled(state) ? UNHANDLED : HANDLED;
4028               if (result.error) throw result.value;
4029             }
4030           });
4031         };
4032
4033         var isUnhandled = function (state) {
4034           return state.rejection !== HANDLED && !state.parent;
4035         };
4036
4037         var onHandleUnhandled = function (state) {
4038           call$e(task, global$z, function () {
4039             var promise = state.facade;
4040             if (IS_NODE$2) {
4041               process$1.emit('rejectionHandled', promise);
4042             } else dispatchEvent$1(REJECTION_HANDLED, promise, state.value);
4043           });
4044         };
4045
4046         var bind$a = function (fn, state, unwrap) {
4047           return function (value) {
4048             fn(state, value, unwrap);
4049           };
4050         };
4051
4052         var internalReject = function (state, value, unwrap) {
4053           if (state.done) return;
4054           state.done = true;
4055           if (unwrap) state = unwrap;
4056           state.value = value;
4057           state.state = REJECTED;
4058           notify(state, true);
4059         };
4060
4061         var internalResolve = function (state, value, unwrap) {
4062           if (state.done) return;
4063           state.done = true;
4064           if (unwrap) state = unwrap;
4065           try {
4066             if (state.facade === value) throw TypeError$a("Promise can't be resolved itself");
4067             var then = isThenable(value);
4068             if (then) {
4069               microtask(function () {
4070                 var wrapper = { done: false };
4071                 try {
4072                   call$e(then, value,
4073                     bind$a(internalResolve, wrapper, state),
4074                     bind$a(internalReject, wrapper, state)
4075                   );
4076                 } catch (error) {
4077                   internalReject(wrapper, error, state);
4078                 }
4079               });
4080             } else {
4081               state.value = value;
4082               state.state = FULFILLED;
4083               notify(state, false);
4084             }
4085           } catch (error) {
4086             internalReject({ done: false }, error, state);
4087           }
4088         };
4089
4090         // constructor polyfill
4091         if (FORCED$h) {
4092           // 25.4.3.1 Promise(executor)
4093           PromiseConstructor = function Promise(executor) {
4094             anInstance$5(this, PromisePrototype);
4095             aCallable$5(executor);
4096             call$e(Internal, this);
4097             var state = getInternalState$1(this);
4098             try {
4099               executor(bind$a(internalResolve, state), bind$a(internalReject, state));
4100             } catch (error) {
4101               internalReject(state, error);
4102             }
4103           };
4104           PromisePrototype = PromiseConstructor.prototype;
4105           // eslint-disable-next-line no-unused-vars -- required for `.length`
4106           Internal = function Promise(executor) {
4107             setInternalState$4(this, {
4108               type: PROMISE,
4109               done: false,
4110               notified: false,
4111               parent: false,
4112               reactions: [],
4113               rejection: false,
4114               state: PENDING,
4115               value: undefined
4116             });
4117           };
4118           Internal.prototype = redefineAll$2(PromisePrototype, {
4119             // `Promise.prototype.then` method
4120             // https://tc39.es/ecma262/#sec-promise.prototype.then
4121             then: function then(onFulfilled, onRejected) {
4122               var state = getInternalPromiseState(this);
4123               var reactions = state.reactions;
4124               var reaction = newPromiseCapability(speciesConstructor$3(this, PromiseConstructor));
4125               reaction.ok = isCallable$7(onFulfilled) ? onFulfilled : true;
4126               reaction.fail = isCallable$7(onRejected) && onRejected;
4127               reaction.domain = IS_NODE$2 ? process$1.domain : undefined;
4128               state.parent = true;
4129               reactions[reactions.length] = reaction;
4130               if (state.state != PENDING) notify(state, false);
4131               return reaction.promise;
4132             },
4133             // `Promise.prototype.catch` method
4134             // https://tc39.es/ecma262/#sec-promise.prototype.catch
4135             'catch': function (onRejected) {
4136               return this.then(undefined, onRejected);
4137             }
4138           });
4139           OwnPromiseCapability = function () {
4140             var promise = new Internal();
4141             var state = getInternalState$1(promise);
4142             this.promise = promise;
4143             this.resolve = bind$a(internalResolve, state);
4144             this.reject = bind$a(internalReject, state);
4145           };
4146           newPromiseCapabilityModule.f = newPromiseCapability = function (C) {
4147             return C === PromiseConstructor || C === PromiseWrapper
4148               ? new OwnPromiseCapability(C)
4149               : newGenericPromiseCapability(C);
4150           };
4151
4152           if (isCallable$7(NativePromise$1) && NativePromisePrototype !== Object.prototype) {
4153             nativeThen = NativePromisePrototype.then;
4154
4155             if (!SUBCLASSING) {
4156               // make `Promise#then` return a polyfilled `Promise` for native promise-based APIs
4157               redefine$8(NativePromisePrototype, 'then', function then(onFulfilled, onRejected) {
4158                 var that = this;
4159                 return new PromiseConstructor(function (resolve, reject) {
4160                   call$e(nativeThen, that, resolve, reject);
4161                 }).then(onFulfilled, onRejected);
4162               // https://github.com/zloirock/core-js/issues/640
4163               }, { unsafe: true });
4164
4165               // makes sure that native promise-based APIs `Promise#catch` properly works with patched `Promise#then`
4166               redefine$8(NativePromisePrototype, 'catch', PromisePrototype['catch'], { unsafe: true });
4167             }
4168
4169             // make `.constructor === Promise` work for native promise-based APIs
4170             try {
4171               delete NativePromisePrototype.constructor;
4172             } catch (error) { /* empty */ }
4173
4174             // make `instanceof Promise` work for native promise-based APIs
4175             if (setPrototypeOf$3) {
4176               setPrototypeOf$3(NativePromisePrototype, PromisePrototype);
4177             }
4178           }
4179         }
4180
4181         $$$({ global: true, wrap: true, forced: FORCED$h }, {
4182           Promise: PromiseConstructor
4183         });
4184
4185         setToStringTag$5(PromiseConstructor, PROMISE, false);
4186         setSpecies$3(PROMISE);
4187
4188         PromiseWrapper = getBuiltIn$3(PROMISE);
4189
4190         // statics
4191         $$$({ target: PROMISE, stat: true, forced: FORCED$h }, {
4192           // `Promise.reject` method
4193           // https://tc39.es/ecma262/#sec-promise.reject
4194           reject: function reject(r) {
4195             var capability = newPromiseCapability(this);
4196             call$e(capability.reject, undefined, r);
4197             return capability.promise;
4198           }
4199         });
4200
4201         $$$({ target: PROMISE, stat: true, forced: FORCED$h }, {
4202           // `Promise.resolve` method
4203           // https://tc39.es/ecma262/#sec-promise.resolve
4204           resolve: function resolve(x) {
4205             return promiseResolve$1(this, x);
4206           }
4207         });
4208
4209         $$$({ target: PROMISE, stat: true, forced: INCORRECT_ITERATION$1 }, {
4210           // `Promise.all` method
4211           // https://tc39.es/ecma262/#sec-promise.all
4212           all: function all(iterable) {
4213             var C = this;
4214             var capability = newPromiseCapability(C);
4215             var resolve = capability.resolve;
4216             var reject = capability.reject;
4217             var result = perform(function () {
4218               var $promiseResolve = aCallable$5(C.resolve);
4219               var values = [];
4220               var counter = 0;
4221               var remaining = 1;
4222               iterate$2(iterable, function (promise) {
4223                 var index = counter++;
4224                 var alreadyCalled = false;
4225                 remaining++;
4226                 call$e($promiseResolve, C, promise).then(function (value) {
4227                   if (alreadyCalled) return;
4228                   alreadyCalled = true;
4229                   values[index] = value;
4230                   --remaining || resolve(values);
4231                 }, reject);
4232               });
4233               --remaining || resolve(values);
4234             });
4235             if (result.error) reject(result.value);
4236             return capability.promise;
4237           },
4238           // `Promise.race` method
4239           // https://tc39.es/ecma262/#sec-promise.race
4240           race: function race(iterable) {
4241             var C = this;
4242             var capability = newPromiseCapability(C);
4243             var reject = capability.reject;
4244             var result = perform(function () {
4245               var $promiseResolve = aCallable$5(C.resolve);
4246               iterate$2(iterable, function (promise) {
4247                 call$e($promiseResolve, C, promise).then(capability.resolve, reject);
4248               });
4249             });
4250             if (result.error) reject(result.value);
4251             return capability.promise;
4252           }
4253         });
4254
4255         var typedArrayConstructor = {exports: {}};
4256
4257         /* eslint-disable no-new -- required for testing */
4258
4259         var global$y = global$1m;
4260         var fails$z = fails$S;
4261         var checkCorrectnessOfIteration$2 = checkCorrectnessOfIteration$4;
4262         var NATIVE_ARRAY_BUFFER_VIEWS$1 = arrayBufferViewCore.NATIVE_ARRAY_BUFFER_VIEWS;
4263
4264         var ArrayBuffer$2 = global$y.ArrayBuffer;
4265         var Int8Array$2 = global$y.Int8Array;
4266
4267         var typedArrayConstructorsRequireWrappers = !NATIVE_ARRAY_BUFFER_VIEWS$1 || !fails$z(function () {
4268           Int8Array$2(1);
4269         }) || !fails$z(function () {
4270           new Int8Array$2(-1);
4271         }) || !checkCorrectnessOfIteration$2(function (iterable) {
4272           new Int8Array$2();
4273           new Int8Array$2(null);
4274           new Int8Array$2(1.5);
4275           new Int8Array$2(iterable);
4276         }, true) || fails$z(function () {
4277           // Safari (11+) bug - a reason why even Safari 13 should load a typed array polyfill
4278           return new Int8Array$2(new ArrayBuffer$2(2), 1, undefined).length !== 1;
4279         });
4280
4281         var isObject$h = isObject$s;
4282
4283         var floor$6 = Math.floor;
4284
4285         // `IsIntegralNumber` abstract operation
4286         // https://tc39.es/ecma262/#sec-isintegralnumber
4287         // eslint-disable-next-line es/no-number-isinteger -- safe
4288         var isIntegralNumber$1 = Number.isInteger || function isInteger(it) {
4289           return !isObject$h(it) && isFinite(it) && floor$6(it) === it;
4290         };
4291
4292         var global$x = global$1m;
4293         var toIntegerOrInfinity$5 = toIntegerOrInfinity$b;
4294
4295         var RangeError$9 = global$x.RangeError;
4296
4297         var toPositiveInteger$1 = function (it) {
4298           var result = toIntegerOrInfinity$5(it);
4299           if (result < 0) throw RangeError$9("The argument can't be less than 0");
4300           return result;
4301         };
4302
4303         var global$w = global$1m;
4304         var toPositiveInteger = toPositiveInteger$1;
4305
4306         var RangeError$8 = global$w.RangeError;
4307
4308         var toOffset$2 = function (it, BYTES) {
4309           var offset = toPositiveInteger(it);
4310           if (offset % BYTES) throw RangeError$8('Wrong offset');
4311           return offset;
4312         };
4313
4314         var bind$9 = functionBindContext;
4315         var call$d = functionCall;
4316         var aConstructor$1 = aConstructor$3;
4317         var toObject$d = toObject$j;
4318         var lengthOfArrayLike$b = lengthOfArrayLike$g;
4319         var getIterator$2 = getIterator$4;
4320         var getIteratorMethod$2 = getIteratorMethod$5;
4321         var isArrayIteratorMethod$1 = isArrayIteratorMethod$3;
4322         var aTypedArrayConstructor$2 = arrayBufferViewCore.aTypedArrayConstructor;
4323
4324         var typedArrayFrom$2 = function from(source /* , mapfn, thisArg */) {
4325           var C = aConstructor$1(this);
4326           var O = toObject$d(source);
4327           var argumentsLength = arguments.length;
4328           var mapfn = argumentsLength > 1 ? arguments[1] : undefined;
4329           var mapping = mapfn !== undefined;
4330           var iteratorMethod = getIteratorMethod$2(O);
4331           var i, length, result, step, iterator, next;
4332           if (iteratorMethod && !isArrayIteratorMethod$1(iteratorMethod)) {
4333             iterator = getIterator$2(O, iteratorMethod);
4334             next = iterator.next;
4335             O = [];
4336             while (!(step = call$d(next, iterator)).done) {
4337               O.push(step.value);
4338             }
4339           }
4340           if (mapping && argumentsLength > 2) {
4341             mapfn = bind$9(mapfn, arguments[2]);
4342           }
4343           length = lengthOfArrayLike$b(O);
4344           result = new (aTypedArrayConstructor$2(C))(length);
4345           for (i = 0; length > i; i++) {
4346             result[i] = mapping ? mapfn(O[i], i) : O[i];
4347           }
4348           return result;
4349         };
4350
4351         var isCallable$6 = isCallable$r;
4352         var isObject$g = isObject$s;
4353         var setPrototypeOf$2 = objectSetPrototypeOf;
4354
4355         // makes subclassing work correct for wrapped built-ins
4356         var inheritIfRequired$4 = function ($this, dummy, Wrapper) {
4357           var NewTarget, NewTargetPrototype;
4358           if (
4359             // it can work only with native `setPrototypeOf`
4360             setPrototypeOf$2 &&
4361             // we haven't completely correct pre-ES6 way for getting `new.target`, so use this
4362             isCallable$6(NewTarget = dummy.constructor) &&
4363             NewTarget !== Wrapper &&
4364             isObject$g(NewTargetPrototype = NewTarget.prototype) &&
4365             NewTargetPrototype !== Wrapper.prototype
4366           ) setPrototypeOf$2($this, NewTargetPrototype);
4367           return $this;
4368         };
4369
4370         var $$_ = _export;
4371         var global$v = global$1m;
4372         var call$c = functionCall;
4373         var DESCRIPTORS$c = descriptors;
4374         var TYPED_ARRAYS_CONSTRUCTORS_REQUIRES_WRAPPERS$1 = typedArrayConstructorsRequireWrappers;
4375         var ArrayBufferViewCore$n = arrayBufferViewCore;
4376         var ArrayBufferModule = arrayBuffer;
4377         var anInstance$4 = anInstance$7;
4378         var createPropertyDescriptor$2 = createPropertyDescriptor$7;
4379         var createNonEnumerableProperty$2 = createNonEnumerableProperty$b;
4380         var isIntegralNumber = isIntegralNumber$1;
4381         var toLength$7 = toLength$c;
4382         var toIndex = toIndex$2;
4383         var toOffset$1 = toOffset$2;
4384         var toPropertyKey$1 = toPropertyKey$5;
4385         var hasOwn$7 = hasOwnProperty_1;
4386         var classof$4 = classof$d;
4387         var isObject$f = isObject$s;
4388         var isSymbol$2 = isSymbol$6;
4389         var create$7 = objectCreate;
4390         var isPrototypeOf$3 = objectIsPrototypeOf;
4391         var setPrototypeOf$1 = objectSetPrototypeOf;
4392         var getOwnPropertyNames$2 = objectGetOwnPropertyNames.f;
4393         var typedArrayFrom$1 = typedArrayFrom$2;
4394         var forEach$1 = arrayIteration.forEach;
4395         var setSpecies$2 = setSpecies$5;
4396         var definePropertyModule$1 = objectDefineProperty;
4397         var getOwnPropertyDescriptorModule$1 = objectGetOwnPropertyDescriptor;
4398         var InternalStateModule$3 = internalState;
4399         var inheritIfRequired$3 = inheritIfRequired$4;
4400
4401         var getInternalState = InternalStateModule$3.get;
4402         var setInternalState$3 = InternalStateModule$3.set;
4403         var nativeDefineProperty = definePropertyModule$1.f;
4404         var nativeGetOwnPropertyDescriptor$1 = getOwnPropertyDescriptorModule$1.f;
4405         var round = Math.round;
4406         var RangeError$7 = global$v.RangeError;
4407         var ArrayBuffer$1 = ArrayBufferModule.ArrayBuffer;
4408         var ArrayBufferPrototype = ArrayBuffer$1.prototype;
4409         var DataView$1 = ArrayBufferModule.DataView;
4410         var NATIVE_ARRAY_BUFFER_VIEWS = ArrayBufferViewCore$n.NATIVE_ARRAY_BUFFER_VIEWS;
4411         var TYPED_ARRAY_CONSTRUCTOR$1 = ArrayBufferViewCore$n.TYPED_ARRAY_CONSTRUCTOR;
4412         var TYPED_ARRAY_TAG = ArrayBufferViewCore$n.TYPED_ARRAY_TAG;
4413         var TypedArray = ArrayBufferViewCore$n.TypedArray;
4414         var TypedArrayPrototype = ArrayBufferViewCore$n.TypedArrayPrototype;
4415         var aTypedArrayConstructor$1 = ArrayBufferViewCore$n.aTypedArrayConstructor;
4416         var isTypedArray = ArrayBufferViewCore$n.isTypedArray;
4417         var BYTES_PER_ELEMENT = 'BYTES_PER_ELEMENT';
4418         var WRONG_LENGTH = 'Wrong length';
4419
4420         var fromList = function (C, list) {
4421           aTypedArrayConstructor$1(C);
4422           var index = 0;
4423           var length = list.length;
4424           var result = new C(length);
4425           while (length > index) result[index] = list[index++];
4426           return result;
4427         };
4428
4429         var addGetter = function (it, key) {
4430           nativeDefineProperty(it, key, { get: function () {
4431             return getInternalState(this)[key];
4432           } });
4433         };
4434
4435         var isArrayBuffer = function (it) {
4436           var klass;
4437           return isPrototypeOf$3(ArrayBufferPrototype, it) || (klass = classof$4(it)) == 'ArrayBuffer' || klass == 'SharedArrayBuffer';
4438         };
4439
4440         var isTypedArrayIndex = function (target, key) {
4441           return isTypedArray(target)
4442             && !isSymbol$2(key)
4443             && key in target
4444             && isIntegralNumber(+key)
4445             && key >= 0;
4446         };
4447
4448         var wrappedGetOwnPropertyDescriptor = function getOwnPropertyDescriptor(target, key) {
4449           key = toPropertyKey$1(key);
4450           return isTypedArrayIndex(target, key)
4451             ? createPropertyDescriptor$2(2, target[key])
4452             : nativeGetOwnPropertyDescriptor$1(target, key);
4453         };
4454
4455         var wrappedDefineProperty = function defineProperty(target, key, descriptor) {
4456           key = toPropertyKey$1(key);
4457           if (isTypedArrayIndex(target, key)
4458             && isObject$f(descriptor)
4459             && hasOwn$7(descriptor, 'value')
4460             && !hasOwn$7(descriptor, 'get')
4461             && !hasOwn$7(descriptor, 'set')
4462             // TODO: add validation descriptor w/o calling accessors
4463             && !descriptor.configurable
4464             && (!hasOwn$7(descriptor, 'writable') || descriptor.writable)
4465             && (!hasOwn$7(descriptor, 'enumerable') || descriptor.enumerable)
4466           ) {
4467             target[key] = descriptor.value;
4468             return target;
4469           } return nativeDefineProperty(target, key, descriptor);
4470         };
4471
4472         if (DESCRIPTORS$c) {
4473           if (!NATIVE_ARRAY_BUFFER_VIEWS) {
4474             getOwnPropertyDescriptorModule$1.f = wrappedGetOwnPropertyDescriptor;
4475             definePropertyModule$1.f = wrappedDefineProperty;
4476             addGetter(TypedArrayPrototype, 'buffer');
4477             addGetter(TypedArrayPrototype, 'byteOffset');
4478             addGetter(TypedArrayPrototype, 'byteLength');
4479             addGetter(TypedArrayPrototype, 'length');
4480           }
4481
4482           $$_({ target: 'Object', stat: true, forced: !NATIVE_ARRAY_BUFFER_VIEWS }, {
4483             getOwnPropertyDescriptor: wrappedGetOwnPropertyDescriptor,
4484             defineProperty: wrappedDefineProperty
4485           });
4486
4487           typedArrayConstructor.exports = function (TYPE, wrapper, CLAMPED) {
4488             var BYTES = TYPE.match(/\d+$/)[0] / 8;
4489             var CONSTRUCTOR_NAME = TYPE + (CLAMPED ? 'Clamped' : '') + 'Array';
4490             var GETTER = 'get' + TYPE;
4491             var SETTER = 'set' + TYPE;
4492             var NativeTypedArrayConstructor = global$v[CONSTRUCTOR_NAME];
4493             var TypedArrayConstructor = NativeTypedArrayConstructor;
4494             var TypedArrayConstructorPrototype = TypedArrayConstructor && TypedArrayConstructor.prototype;
4495             var exported = {};
4496
4497             var getter = function (that, index) {
4498               var data = getInternalState(that);
4499               return data.view[GETTER](index * BYTES + data.byteOffset, true);
4500             };
4501
4502             var setter = function (that, index, value) {
4503               var data = getInternalState(that);
4504               if (CLAMPED) value = (value = round(value)) < 0 ? 0 : value > 0xFF ? 0xFF : value & 0xFF;
4505               data.view[SETTER](index * BYTES + data.byteOffset, value, true);
4506             };
4507
4508             var addElement = function (that, index) {
4509               nativeDefineProperty(that, index, {
4510                 get: function () {
4511                   return getter(this, index);
4512                 },
4513                 set: function (value) {
4514                   return setter(this, index, value);
4515                 },
4516                 enumerable: true
4517               });
4518             };
4519
4520             if (!NATIVE_ARRAY_BUFFER_VIEWS) {
4521               TypedArrayConstructor = wrapper(function (that, data, offset, $length) {
4522                 anInstance$4(that, TypedArrayConstructorPrototype);
4523                 var index = 0;
4524                 var byteOffset = 0;
4525                 var buffer, byteLength, length;
4526                 if (!isObject$f(data)) {
4527                   length = toIndex(data);
4528                   byteLength = length * BYTES;
4529                   buffer = new ArrayBuffer$1(byteLength);
4530                 } else if (isArrayBuffer(data)) {
4531                   buffer = data;
4532                   byteOffset = toOffset$1(offset, BYTES);
4533                   var $len = data.byteLength;
4534                   if ($length === undefined) {
4535                     if ($len % BYTES) throw RangeError$7(WRONG_LENGTH);
4536                     byteLength = $len - byteOffset;
4537                     if (byteLength < 0) throw RangeError$7(WRONG_LENGTH);
4538                   } else {
4539                     byteLength = toLength$7($length) * BYTES;
4540                     if (byteLength + byteOffset > $len) throw RangeError$7(WRONG_LENGTH);
4541                   }
4542                   length = byteLength / BYTES;
4543                 } else if (isTypedArray(data)) {
4544                   return fromList(TypedArrayConstructor, data);
4545                 } else {
4546                   return call$c(typedArrayFrom$1, TypedArrayConstructor, data);
4547                 }
4548                 setInternalState$3(that, {
4549                   buffer: buffer,
4550                   byteOffset: byteOffset,
4551                   byteLength: byteLength,
4552                   length: length,
4553                   view: new DataView$1(buffer)
4554                 });
4555                 while (index < length) addElement(that, index++);
4556               });
4557
4558               if (setPrototypeOf$1) setPrototypeOf$1(TypedArrayConstructor, TypedArray);
4559               TypedArrayConstructorPrototype = TypedArrayConstructor.prototype = create$7(TypedArrayPrototype);
4560             } else if (TYPED_ARRAYS_CONSTRUCTORS_REQUIRES_WRAPPERS$1) {
4561               TypedArrayConstructor = wrapper(function (dummy, data, typedArrayOffset, $length) {
4562                 anInstance$4(dummy, TypedArrayConstructorPrototype);
4563                 return inheritIfRequired$3(function () {
4564                   if (!isObject$f(data)) return new NativeTypedArrayConstructor(toIndex(data));
4565                   if (isArrayBuffer(data)) return $length !== undefined
4566                     ? new NativeTypedArrayConstructor(data, toOffset$1(typedArrayOffset, BYTES), $length)
4567                     : typedArrayOffset !== undefined
4568                       ? new NativeTypedArrayConstructor(data, toOffset$1(typedArrayOffset, BYTES))
4569                       : new NativeTypedArrayConstructor(data);
4570                   if (isTypedArray(data)) return fromList(TypedArrayConstructor, data);
4571                   return call$c(typedArrayFrom$1, TypedArrayConstructor, data);
4572                 }(), dummy, TypedArrayConstructor);
4573               });
4574
4575               if (setPrototypeOf$1) setPrototypeOf$1(TypedArrayConstructor, TypedArray);
4576               forEach$1(getOwnPropertyNames$2(NativeTypedArrayConstructor), function (key) {
4577                 if (!(key in TypedArrayConstructor)) {
4578                   createNonEnumerableProperty$2(TypedArrayConstructor, key, NativeTypedArrayConstructor[key]);
4579                 }
4580               });
4581               TypedArrayConstructor.prototype = TypedArrayConstructorPrototype;
4582             }
4583
4584             if (TypedArrayConstructorPrototype.constructor !== TypedArrayConstructor) {
4585               createNonEnumerableProperty$2(TypedArrayConstructorPrototype, 'constructor', TypedArrayConstructor);
4586             }
4587
4588             createNonEnumerableProperty$2(TypedArrayConstructorPrototype, TYPED_ARRAY_CONSTRUCTOR$1, TypedArrayConstructor);
4589
4590             if (TYPED_ARRAY_TAG) {
4591               createNonEnumerableProperty$2(TypedArrayConstructorPrototype, TYPED_ARRAY_TAG, CONSTRUCTOR_NAME);
4592             }
4593
4594             exported[CONSTRUCTOR_NAME] = TypedArrayConstructor;
4595
4596             $$_({
4597               global: true, forced: TypedArrayConstructor != NativeTypedArrayConstructor, sham: !NATIVE_ARRAY_BUFFER_VIEWS
4598             }, exported);
4599
4600             if (!(BYTES_PER_ELEMENT in TypedArrayConstructor)) {
4601               createNonEnumerableProperty$2(TypedArrayConstructor, BYTES_PER_ELEMENT, BYTES);
4602             }
4603
4604             if (!(BYTES_PER_ELEMENT in TypedArrayConstructorPrototype)) {
4605               createNonEnumerableProperty$2(TypedArrayConstructorPrototype, BYTES_PER_ELEMENT, BYTES);
4606             }
4607
4608             setSpecies$2(CONSTRUCTOR_NAME);
4609           };
4610         } else typedArrayConstructor.exports = function () { /* empty */ };
4611
4612         var createTypedArrayConstructor$1 = typedArrayConstructor.exports;
4613
4614         // `Uint8Array` constructor
4615         // https://tc39.es/ecma262/#sec-typedarray-objects
4616         createTypedArrayConstructor$1('Uint8', function (init) {
4617           return function Uint8Array(data, byteOffset, length) {
4618             return init(this, data, byteOffset, length);
4619           };
4620         });
4621
4622         var toObject$c = toObject$j;
4623         var toAbsoluteIndex$4 = toAbsoluteIndex$8;
4624         var lengthOfArrayLike$a = lengthOfArrayLike$g;
4625
4626         var min$7 = Math.min;
4627
4628         // `Array.prototype.copyWithin` method implementation
4629         // https://tc39.es/ecma262/#sec-array.prototype.copywithin
4630         // eslint-disable-next-line es/no-array-prototype-copywithin -- safe
4631         var arrayCopyWithin = [].copyWithin || function copyWithin(target /* = 0 */, start /* = 0, end = @length */) {
4632           var O = toObject$c(this);
4633           var len = lengthOfArrayLike$a(O);
4634           var to = toAbsoluteIndex$4(target, len);
4635           var from = toAbsoluteIndex$4(start, len);
4636           var end = arguments.length > 2 ? arguments[2] : undefined;
4637           var count = min$7((end === undefined ? len : toAbsoluteIndex$4(end, len)) - from, len - to);
4638           var inc = 1;
4639           if (from < to && to < from + count) {
4640             inc = -1;
4641             from += count - 1;
4642             to += count - 1;
4643           }
4644           while (count-- > 0) {
4645             if (from in O) O[to] = O[from];
4646             else delete O[to];
4647             to += inc;
4648             from += inc;
4649           } return O;
4650         };
4651
4652         var uncurryThis$A = functionUncurryThis;
4653         var ArrayBufferViewCore$m = arrayBufferViewCore;
4654         var $ArrayCopyWithin = arrayCopyWithin;
4655
4656         var u$ArrayCopyWithin = uncurryThis$A($ArrayCopyWithin);
4657         var aTypedArray$l = ArrayBufferViewCore$m.aTypedArray;
4658         var exportTypedArrayMethod$m = ArrayBufferViewCore$m.exportTypedArrayMethod;
4659
4660         // `%TypedArray%.prototype.copyWithin` method
4661         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.copywithin
4662         exportTypedArrayMethod$m('copyWithin', function copyWithin(target, start /* , end */) {
4663           return u$ArrayCopyWithin(aTypedArray$l(this), target, start, arguments.length > 2 ? arguments[2] : undefined);
4664         });
4665
4666         var ArrayBufferViewCore$l = arrayBufferViewCore;
4667         var $every$1 = arrayIteration.every;
4668
4669         var aTypedArray$k = ArrayBufferViewCore$l.aTypedArray;
4670         var exportTypedArrayMethod$l = ArrayBufferViewCore$l.exportTypedArrayMethod;
4671
4672         // `%TypedArray%.prototype.every` method
4673         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.every
4674         exportTypedArrayMethod$l('every', function every(callbackfn /* , thisArg */) {
4675           return $every$1(aTypedArray$k(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined);
4676         });
4677
4678         var ArrayBufferViewCore$k = arrayBufferViewCore;
4679         var call$b = functionCall;
4680         var $fill = arrayFill$1;
4681
4682         var aTypedArray$j = ArrayBufferViewCore$k.aTypedArray;
4683         var exportTypedArrayMethod$k = ArrayBufferViewCore$k.exportTypedArrayMethod;
4684
4685         // `%TypedArray%.prototype.fill` method
4686         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.fill
4687         exportTypedArrayMethod$k('fill', function fill(value /* , start, end */) {
4688           var length = arguments.length;
4689           return call$b(
4690             $fill,
4691             aTypedArray$j(this),
4692             value,
4693             length > 1 ? arguments[1] : undefined,
4694             length > 2 ? arguments[2] : undefined
4695           );
4696         });
4697
4698         var arrayFromConstructorAndList$1 = function (Constructor, list) {
4699           var index = 0;
4700           var length = list.length;
4701           var result = new Constructor(length);
4702           while (length > index) result[index] = list[index++];
4703           return result;
4704         };
4705
4706         var ArrayBufferViewCore$j = arrayBufferViewCore;
4707         var speciesConstructor$2 = speciesConstructor$5;
4708
4709         var TYPED_ARRAY_CONSTRUCTOR = ArrayBufferViewCore$j.TYPED_ARRAY_CONSTRUCTOR;
4710         var aTypedArrayConstructor = ArrayBufferViewCore$j.aTypedArrayConstructor;
4711
4712         // a part of `TypedArraySpeciesCreate` abstract operation
4713         // https://tc39.es/ecma262/#typedarray-species-create
4714         var typedArraySpeciesConstructor$4 = function (originalArray) {
4715           return aTypedArrayConstructor(speciesConstructor$2(originalArray, originalArray[TYPED_ARRAY_CONSTRUCTOR]));
4716         };
4717
4718         var arrayFromConstructorAndList = arrayFromConstructorAndList$1;
4719         var typedArraySpeciesConstructor$3 = typedArraySpeciesConstructor$4;
4720
4721         var typedArrayFromSpeciesAndList = function (instance, list) {
4722           return arrayFromConstructorAndList(typedArraySpeciesConstructor$3(instance), list);
4723         };
4724
4725         var ArrayBufferViewCore$i = arrayBufferViewCore;
4726         var $filter$1 = arrayIteration.filter;
4727         var fromSpeciesAndList = typedArrayFromSpeciesAndList;
4728
4729         var aTypedArray$i = ArrayBufferViewCore$i.aTypedArray;
4730         var exportTypedArrayMethod$j = ArrayBufferViewCore$i.exportTypedArrayMethod;
4731
4732         // `%TypedArray%.prototype.filter` method
4733         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.filter
4734         exportTypedArrayMethod$j('filter', function filter(callbackfn /* , thisArg */) {
4735           var list = $filter$1(aTypedArray$i(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined);
4736           return fromSpeciesAndList(this, list);
4737         });
4738
4739         var ArrayBufferViewCore$h = arrayBufferViewCore;
4740         var $find$1 = arrayIteration.find;
4741
4742         var aTypedArray$h = ArrayBufferViewCore$h.aTypedArray;
4743         var exportTypedArrayMethod$i = ArrayBufferViewCore$h.exportTypedArrayMethod;
4744
4745         // `%TypedArray%.prototype.find` method
4746         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.find
4747         exportTypedArrayMethod$i('find', function find(predicate /* , thisArg */) {
4748           return $find$1(aTypedArray$h(this), predicate, arguments.length > 1 ? arguments[1] : undefined);
4749         });
4750
4751         var ArrayBufferViewCore$g = arrayBufferViewCore;
4752         var $findIndex$1 = arrayIteration.findIndex;
4753
4754         var aTypedArray$g = ArrayBufferViewCore$g.aTypedArray;
4755         var exportTypedArrayMethod$h = ArrayBufferViewCore$g.exportTypedArrayMethod;
4756
4757         // `%TypedArray%.prototype.findIndex` method
4758         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.findindex
4759         exportTypedArrayMethod$h('findIndex', function findIndex(predicate /* , thisArg */) {
4760           return $findIndex$1(aTypedArray$g(this), predicate, arguments.length > 1 ? arguments[1] : undefined);
4761         });
4762
4763         var ArrayBufferViewCore$f = arrayBufferViewCore;
4764         var $forEach = arrayIteration.forEach;
4765
4766         var aTypedArray$f = ArrayBufferViewCore$f.aTypedArray;
4767         var exportTypedArrayMethod$g = ArrayBufferViewCore$f.exportTypedArrayMethod;
4768
4769         // `%TypedArray%.prototype.forEach` method
4770         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.foreach
4771         exportTypedArrayMethod$g('forEach', function forEach(callbackfn /* , thisArg */) {
4772           $forEach(aTypedArray$f(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined);
4773         });
4774
4775         var ArrayBufferViewCore$e = arrayBufferViewCore;
4776         var $includes$1 = arrayIncludes.includes;
4777
4778         var aTypedArray$e = ArrayBufferViewCore$e.aTypedArray;
4779         var exportTypedArrayMethod$f = ArrayBufferViewCore$e.exportTypedArrayMethod;
4780
4781         // `%TypedArray%.prototype.includes` method
4782         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.includes
4783         exportTypedArrayMethod$f('includes', function includes(searchElement /* , fromIndex */) {
4784           return $includes$1(aTypedArray$e(this), searchElement, arguments.length > 1 ? arguments[1] : undefined);
4785         });
4786
4787         var ArrayBufferViewCore$d = arrayBufferViewCore;
4788         var $indexOf = arrayIncludes.indexOf;
4789
4790         var aTypedArray$d = ArrayBufferViewCore$d.aTypedArray;
4791         var exportTypedArrayMethod$e = ArrayBufferViewCore$d.exportTypedArrayMethod;
4792
4793         // `%TypedArray%.prototype.indexOf` method
4794         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.indexof
4795         exportTypedArrayMethod$e('indexOf', function indexOf(searchElement /* , fromIndex */) {
4796           return $indexOf(aTypedArray$d(this), searchElement, arguments.length > 1 ? arguments[1] : undefined);
4797         });
4798
4799         var global$u = global$1m;
4800         var uncurryThis$z = functionUncurryThis;
4801         var PROPER_FUNCTION_NAME$2 = functionName.PROPER;
4802         var ArrayBufferViewCore$c = arrayBufferViewCore;
4803         var ArrayIterators = es_array_iterator;
4804         var wellKnownSymbol$9 = wellKnownSymbol$t;
4805
4806         var ITERATOR$4 = wellKnownSymbol$9('iterator');
4807         var Uint8Array$2 = global$u.Uint8Array;
4808         var arrayValues = uncurryThis$z(ArrayIterators.values);
4809         var arrayKeys = uncurryThis$z(ArrayIterators.keys);
4810         var arrayEntries = uncurryThis$z(ArrayIterators.entries);
4811         var aTypedArray$c = ArrayBufferViewCore$c.aTypedArray;
4812         var exportTypedArrayMethod$d = ArrayBufferViewCore$c.exportTypedArrayMethod;
4813         var nativeTypedArrayIterator = Uint8Array$2 && Uint8Array$2.prototype[ITERATOR$4];
4814
4815         var PROPER_ARRAY_VALUES_NAME = !!nativeTypedArrayIterator && nativeTypedArrayIterator.name === 'values';
4816
4817         var typedArrayValues = function values() {
4818           return arrayValues(aTypedArray$c(this));
4819         };
4820
4821         // `%TypedArray%.prototype.entries` method
4822         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.entries
4823         exportTypedArrayMethod$d('entries', function entries() {
4824           return arrayEntries(aTypedArray$c(this));
4825         });
4826         // `%TypedArray%.prototype.keys` method
4827         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.keys
4828         exportTypedArrayMethod$d('keys', function keys() {
4829           return arrayKeys(aTypedArray$c(this));
4830         });
4831         // `%TypedArray%.prototype.values` method
4832         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.values
4833         exportTypedArrayMethod$d('values', typedArrayValues, PROPER_FUNCTION_NAME$2 && !PROPER_ARRAY_VALUES_NAME);
4834         // `%TypedArray%.prototype[@@iterator]` method
4835         // https://tc39.es/ecma262/#sec-%typedarray%.prototype-@@iterator
4836         exportTypedArrayMethod$d(ITERATOR$4, typedArrayValues, PROPER_FUNCTION_NAME$2 && !PROPER_ARRAY_VALUES_NAME);
4837
4838         var ArrayBufferViewCore$b = arrayBufferViewCore;
4839         var uncurryThis$y = functionUncurryThis;
4840
4841         var aTypedArray$b = ArrayBufferViewCore$b.aTypedArray;
4842         var exportTypedArrayMethod$c = ArrayBufferViewCore$b.exportTypedArrayMethod;
4843         var $join = uncurryThis$y([].join);
4844
4845         // `%TypedArray%.prototype.join` method
4846         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.join
4847         exportTypedArrayMethod$c('join', function join(separator) {
4848           return $join(aTypedArray$b(this), separator);
4849         });
4850
4851         /* eslint-disable es/no-array-prototype-lastindexof -- safe */
4852         var apply$6 = functionApply;
4853         var toIndexedObject$4 = toIndexedObject$c;
4854         var toIntegerOrInfinity$4 = toIntegerOrInfinity$b;
4855         var lengthOfArrayLike$9 = lengthOfArrayLike$g;
4856         var arrayMethodIsStrict$6 = arrayMethodIsStrict$9;
4857
4858         var min$6 = Math.min;
4859         var $lastIndexOf$1 = [].lastIndexOf;
4860         var NEGATIVE_ZERO = !!$lastIndexOf$1 && 1 / [1].lastIndexOf(1, -0) < 0;
4861         var STRICT_METHOD$6 = arrayMethodIsStrict$6('lastIndexOf');
4862         var FORCED$g = NEGATIVE_ZERO || !STRICT_METHOD$6;
4863
4864         // `Array.prototype.lastIndexOf` method implementation
4865         // https://tc39.es/ecma262/#sec-array.prototype.lastindexof
4866         var arrayLastIndexOf = FORCED$g ? function lastIndexOf(searchElement /* , fromIndex = @[*-1] */) {
4867           // convert -0 to +0
4868           if (NEGATIVE_ZERO) return apply$6($lastIndexOf$1, this, arguments) || 0;
4869           var O = toIndexedObject$4(this);
4870           var length = lengthOfArrayLike$9(O);
4871           var index = length - 1;
4872           if (arguments.length > 1) index = min$6(index, toIntegerOrInfinity$4(arguments[1]));
4873           if (index < 0) index = length + index;
4874           for (;index >= 0; index--) if (index in O && O[index] === searchElement) return index || 0;
4875           return -1;
4876         } : $lastIndexOf$1;
4877
4878         var ArrayBufferViewCore$a = arrayBufferViewCore;
4879         var apply$5 = functionApply;
4880         var $lastIndexOf = arrayLastIndexOf;
4881
4882         var aTypedArray$a = ArrayBufferViewCore$a.aTypedArray;
4883         var exportTypedArrayMethod$b = ArrayBufferViewCore$a.exportTypedArrayMethod;
4884
4885         // `%TypedArray%.prototype.lastIndexOf` method
4886         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.lastindexof
4887         exportTypedArrayMethod$b('lastIndexOf', function lastIndexOf(searchElement /* , fromIndex */) {
4888           var length = arguments.length;
4889           return apply$5($lastIndexOf, aTypedArray$a(this), length > 1 ? [searchElement, arguments[1]] : [searchElement]);
4890         });
4891
4892         var ArrayBufferViewCore$9 = arrayBufferViewCore;
4893         var $map = arrayIteration.map;
4894         var typedArraySpeciesConstructor$2 = typedArraySpeciesConstructor$4;
4895
4896         var aTypedArray$9 = ArrayBufferViewCore$9.aTypedArray;
4897         var exportTypedArrayMethod$a = ArrayBufferViewCore$9.exportTypedArrayMethod;
4898
4899         // `%TypedArray%.prototype.map` method
4900         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.map
4901         exportTypedArrayMethod$a('map', function map(mapfn /* , thisArg */) {
4902           return $map(aTypedArray$9(this), mapfn, arguments.length > 1 ? arguments[1] : undefined, function (O, length) {
4903             return new (typedArraySpeciesConstructor$2(O))(length);
4904           });
4905         });
4906
4907         var global$t = global$1m;
4908         var aCallable$4 = aCallable$a;
4909         var toObject$b = toObject$j;
4910         var IndexedObject$2 = indexedObject;
4911         var lengthOfArrayLike$8 = lengthOfArrayLike$g;
4912
4913         var TypeError$9 = global$t.TypeError;
4914
4915         // `Array.prototype.{ reduce, reduceRight }` methods implementation
4916         var createMethod$3 = function (IS_RIGHT) {
4917           return function (that, callbackfn, argumentsLength, memo) {
4918             aCallable$4(callbackfn);
4919             var O = toObject$b(that);
4920             var self = IndexedObject$2(O);
4921             var length = lengthOfArrayLike$8(O);
4922             var index = IS_RIGHT ? length - 1 : 0;
4923             var i = IS_RIGHT ? -1 : 1;
4924             if (argumentsLength < 2) while (true) {
4925               if (index in self) {
4926                 memo = self[index];
4927                 index += i;
4928                 break;
4929               }
4930               index += i;
4931               if (IS_RIGHT ? index < 0 : length <= index) {
4932                 throw TypeError$9('Reduce of empty array with no initial value');
4933               }
4934             }
4935             for (;IS_RIGHT ? index >= 0 : length > index; index += i) if (index in self) {
4936               memo = callbackfn(memo, self[index], index, O);
4937             }
4938             return memo;
4939           };
4940         };
4941
4942         var arrayReduce = {
4943           // `Array.prototype.reduce` method
4944           // https://tc39.es/ecma262/#sec-array.prototype.reduce
4945           left: createMethod$3(false),
4946           // `Array.prototype.reduceRight` method
4947           // https://tc39.es/ecma262/#sec-array.prototype.reduceright
4948           right: createMethod$3(true)
4949         };
4950
4951         var ArrayBufferViewCore$8 = arrayBufferViewCore;
4952         var $reduce$1 = arrayReduce.left;
4953
4954         var aTypedArray$8 = ArrayBufferViewCore$8.aTypedArray;
4955         var exportTypedArrayMethod$9 = ArrayBufferViewCore$8.exportTypedArrayMethod;
4956
4957         // `%TypedArray%.prototype.reduce` method
4958         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.reduce
4959         exportTypedArrayMethod$9('reduce', function reduce(callbackfn /* , initialValue */) {
4960           var length = arguments.length;
4961           return $reduce$1(aTypedArray$8(this), callbackfn, length, length > 1 ? arguments[1] : undefined);
4962         });
4963
4964         var ArrayBufferViewCore$7 = arrayBufferViewCore;
4965         var $reduceRight$1 = arrayReduce.right;
4966
4967         var aTypedArray$7 = ArrayBufferViewCore$7.aTypedArray;
4968         var exportTypedArrayMethod$8 = ArrayBufferViewCore$7.exportTypedArrayMethod;
4969
4970         // `%TypedArray%.prototype.reduceRicht` method
4971         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.reduceright
4972         exportTypedArrayMethod$8('reduceRight', function reduceRight(callbackfn /* , initialValue */) {
4973           var length = arguments.length;
4974           return $reduceRight$1(aTypedArray$7(this), callbackfn, length, length > 1 ? arguments[1] : undefined);
4975         });
4976
4977         var ArrayBufferViewCore$6 = arrayBufferViewCore;
4978
4979         var aTypedArray$6 = ArrayBufferViewCore$6.aTypedArray;
4980         var exportTypedArrayMethod$7 = ArrayBufferViewCore$6.exportTypedArrayMethod;
4981         var floor$5 = Math.floor;
4982
4983         // `%TypedArray%.prototype.reverse` method
4984         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.reverse
4985         exportTypedArrayMethod$7('reverse', function reverse() {
4986           var that = this;
4987           var length = aTypedArray$6(that).length;
4988           var middle = floor$5(length / 2);
4989           var index = 0;
4990           var value;
4991           while (index < middle) {
4992             value = that[index];
4993             that[index++] = that[--length];
4994             that[length] = value;
4995           } return that;
4996         });
4997
4998         var global$s = global$1m;
4999         var ArrayBufferViewCore$5 = arrayBufferViewCore;
5000         var lengthOfArrayLike$7 = lengthOfArrayLike$g;
5001         var toOffset = toOffset$2;
5002         var toObject$a = toObject$j;
5003         var fails$y = fails$S;
5004
5005         var RangeError$6 = global$s.RangeError;
5006         var aTypedArray$5 = ArrayBufferViewCore$5.aTypedArray;
5007         var exportTypedArrayMethod$6 = ArrayBufferViewCore$5.exportTypedArrayMethod;
5008
5009         var FORCED$f = fails$y(function () {
5010           // eslint-disable-next-line es/no-typed-arrays -- required for testing
5011           new Int8Array(1).set({});
5012         });
5013
5014         // `%TypedArray%.prototype.set` method
5015         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.set
5016         exportTypedArrayMethod$6('set', function set(arrayLike /* , offset */) {
5017           aTypedArray$5(this);
5018           var offset = toOffset(arguments.length > 1 ? arguments[1] : undefined, 1);
5019           var length = this.length;
5020           var src = toObject$a(arrayLike);
5021           var len = lengthOfArrayLike$7(src);
5022           var index = 0;
5023           if (len + offset > length) throw RangeError$6('Wrong length');
5024           while (index < len) this[offset + index] = src[index++];
5025         }, FORCED$f);
5026
5027         var ArrayBufferViewCore$4 = arrayBufferViewCore;
5028         var typedArraySpeciesConstructor$1 = typedArraySpeciesConstructor$4;
5029         var fails$x = fails$S;
5030         var arraySlice$7 = arraySlice$c;
5031
5032         var aTypedArray$4 = ArrayBufferViewCore$4.aTypedArray;
5033         var exportTypedArrayMethod$5 = ArrayBufferViewCore$4.exportTypedArrayMethod;
5034
5035         var FORCED$e = fails$x(function () {
5036           // eslint-disable-next-line es/no-typed-arrays -- required for testing
5037           new Int8Array(1).slice();
5038         });
5039
5040         // `%TypedArray%.prototype.slice` method
5041         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.slice
5042         exportTypedArrayMethod$5('slice', function slice(start, end) {
5043           var list = arraySlice$7(aTypedArray$4(this), start, end);
5044           var C = typedArraySpeciesConstructor$1(this);
5045           var index = 0;
5046           var length = list.length;
5047           var result = new C(length);
5048           while (length > index) result[index] = list[index++];
5049           return result;
5050         }, FORCED$e);
5051
5052         var ArrayBufferViewCore$3 = arrayBufferViewCore;
5053         var $some$1 = arrayIteration.some;
5054
5055         var aTypedArray$3 = ArrayBufferViewCore$3.aTypedArray;
5056         var exportTypedArrayMethod$4 = ArrayBufferViewCore$3.exportTypedArrayMethod;
5057
5058         // `%TypedArray%.prototype.some` method
5059         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.some
5060         exportTypedArrayMethod$4('some', function some(callbackfn /* , thisArg */) {
5061           return $some$1(aTypedArray$3(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined);
5062         });
5063
5064         var arraySlice$6 = arraySlice$c;
5065
5066         var floor$4 = Math.floor;
5067
5068         var mergeSort = function (array, comparefn) {
5069           var length = array.length;
5070           var middle = floor$4(length / 2);
5071           return length < 8 ? insertionSort(array, comparefn) : merge$5(
5072             array,
5073             mergeSort(arraySlice$6(array, 0, middle), comparefn),
5074             mergeSort(arraySlice$6(array, middle), comparefn),
5075             comparefn
5076           );
5077         };
5078
5079         var insertionSort = function (array, comparefn) {
5080           var length = array.length;
5081           var i = 1;
5082           var element, j;
5083
5084           while (i < length) {
5085             j = i;
5086             element = array[i];
5087             while (j && comparefn(array[j - 1], element) > 0) {
5088               array[j] = array[--j];
5089             }
5090             if (j !== i++) array[j] = element;
5091           } return array;
5092         };
5093
5094         var merge$5 = function (array, left, right, comparefn) {
5095           var llength = left.length;
5096           var rlength = right.length;
5097           var lindex = 0;
5098           var rindex = 0;
5099
5100           while (lindex < llength || rindex < rlength) {
5101             array[lindex + rindex] = (lindex < llength && rindex < rlength)
5102               ? comparefn(left[lindex], right[rindex]) <= 0 ? left[lindex++] : right[rindex++]
5103               : lindex < llength ? left[lindex++] : right[rindex++];
5104           } return array;
5105         };
5106
5107         var arraySort$1 = mergeSort;
5108
5109         var userAgent$3 = engineUserAgent;
5110
5111         var firefox = userAgent$3.match(/firefox\/(\d+)/i);
5112
5113         var engineFfVersion = !!firefox && +firefox[1];
5114
5115         var UA = engineUserAgent;
5116
5117         var engineIsIeOrEdge = /MSIE|Trident/.test(UA);
5118
5119         var userAgent$2 = engineUserAgent;
5120
5121         var webkit = userAgent$2.match(/AppleWebKit\/(\d+)\./);
5122
5123         var engineWebkitVersion = !!webkit && +webkit[1];
5124
5125         var global$r = global$1m;
5126         var uncurryThis$x = functionUncurryThis;
5127         var fails$w = fails$S;
5128         var aCallable$3 = aCallable$a;
5129         var internalSort$1 = arraySort$1;
5130         var ArrayBufferViewCore$2 = arrayBufferViewCore;
5131         var FF$1 = engineFfVersion;
5132         var IE_OR_EDGE$1 = engineIsIeOrEdge;
5133         var V8$1 = engineV8Version;
5134         var WEBKIT$1 = engineWebkitVersion;
5135
5136         var Array$3 = global$r.Array;
5137         var aTypedArray$2 = ArrayBufferViewCore$2.aTypedArray;
5138         var exportTypedArrayMethod$3 = ArrayBufferViewCore$2.exportTypedArrayMethod;
5139         var Uint16Array = global$r.Uint16Array;
5140         var un$Sort$1 = Uint16Array && uncurryThis$x(Uint16Array.prototype.sort);
5141
5142         // WebKit
5143         var ACCEPT_INCORRECT_ARGUMENTS = !!un$Sort$1 && !(fails$w(function () {
5144           un$Sort$1(new Uint16Array(2), null);
5145         }) && fails$w(function () {
5146           un$Sort$1(new Uint16Array(2), {});
5147         }));
5148
5149         var STABLE_SORT$1 = !!un$Sort$1 && !fails$w(function () {
5150           // feature detection can be too slow, so check engines versions
5151           if (V8$1) return V8$1 < 74;
5152           if (FF$1) return FF$1 < 67;
5153           if (IE_OR_EDGE$1) return true;
5154           if (WEBKIT$1) return WEBKIT$1 < 602;
5155
5156           var array = new Uint16Array(516);
5157           var expected = Array$3(516);
5158           var index, mod;
5159
5160           for (index = 0; index < 516; index++) {
5161             mod = index % 4;
5162             array[index] = 515 - index;
5163             expected[index] = index - 2 * mod + 3;
5164           }
5165
5166           un$Sort$1(array, function (a, b) {
5167             return (a / 4 | 0) - (b / 4 | 0);
5168           });
5169
5170           for (index = 0; index < 516; index++) {
5171             if (array[index] !== expected[index]) return true;
5172           }
5173         });
5174
5175         var getSortCompare$1 = function (comparefn) {
5176           return function (x, y) {
5177             if (comparefn !== undefined) return +comparefn(x, y) || 0;
5178             // eslint-disable-next-line no-self-compare -- NaN check
5179             if (y !== y) return -1;
5180             // eslint-disable-next-line no-self-compare -- NaN check
5181             if (x !== x) return 1;
5182             if (x === 0 && y === 0) return 1 / x > 0 && 1 / y < 0 ? 1 : -1;
5183             return x > y;
5184           };
5185         };
5186
5187         // `%TypedArray%.prototype.sort` method
5188         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.sort
5189         exportTypedArrayMethod$3('sort', function sort(comparefn) {
5190           if (comparefn !== undefined) aCallable$3(comparefn);
5191           if (STABLE_SORT$1) return un$Sort$1(this, comparefn);
5192
5193           return internalSort$1(aTypedArray$2(this), getSortCompare$1(comparefn));
5194         }, !STABLE_SORT$1 || ACCEPT_INCORRECT_ARGUMENTS);
5195
5196         var ArrayBufferViewCore$1 = arrayBufferViewCore;
5197         var toLength$6 = toLength$c;
5198         var toAbsoluteIndex$3 = toAbsoluteIndex$8;
5199         var typedArraySpeciesConstructor = typedArraySpeciesConstructor$4;
5200
5201         var aTypedArray$1 = ArrayBufferViewCore$1.aTypedArray;
5202         var exportTypedArrayMethod$2 = ArrayBufferViewCore$1.exportTypedArrayMethod;
5203
5204         // `%TypedArray%.prototype.subarray` method
5205         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.subarray
5206         exportTypedArrayMethod$2('subarray', function subarray(begin, end) {
5207           var O = aTypedArray$1(this);
5208           var length = O.length;
5209           var beginIndex = toAbsoluteIndex$3(begin, length);
5210           var C = typedArraySpeciesConstructor(O);
5211           return new C(
5212             O.buffer,
5213             O.byteOffset + beginIndex * O.BYTES_PER_ELEMENT,
5214             toLength$6((end === undefined ? length : toAbsoluteIndex$3(end, length)) - beginIndex)
5215           );
5216         });
5217
5218         var global$q = global$1m;
5219         var apply$4 = functionApply;
5220         var ArrayBufferViewCore = arrayBufferViewCore;
5221         var fails$v = fails$S;
5222         var arraySlice$5 = arraySlice$c;
5223
5224         var Int8Array$1 = global$q.Int8Array;
5225         var aTypedArray = ArrayBufferViewCore.aTypedArray;
5226         var exportTypedArrayMethod$1 = ArrayBufferViewCore.exportTypedArrayMethod;
5227         var $toLocaleString = [].toLocaleString;
5228
5229         // iOS Safari 6.x fails here
5230         var TO_LOCALE_STRING_BUG = !!Int8Array$1 && fails$v(function () {
5231           $toLocaleString.call(new Int8Array$1(1));
5232         });
5233
5234         var FORCED$d = fails$v(function () {
5235           return [1, 2].toLocaleString() != new Int8Array$1([1, 2]).toLocaleString();
5236         }) || !fails$v(function () {
5237           Int8Array$1.prototype.toLocaleString.call([1, 2]);
5238         });
5239
5240         // `%TypedArray%.prototype.toLocaleString` method
5241         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.tolocalestring
5242         exportTypedArrayMethod$1('toLocaleString', function toLocaleString() {
5243           return apply$4(
5244             $toLocaleString,
5245             TO_LOCALE_STRING_BUG ? arraySlice$5(aTypedArray(this)) : aTypedArray(this),
5246             arraySlice$5(arguments)
5247           );
5248         }, FORCED$d);
5249
5250         var exportTypedArrayMethod = arrayBufferViewCore.exportTypedArrayMethod;
5251         var fails$u = fails$S;
5252         var global$p = global$1m;
5253         var uncurryThis$w = functionUncurryThis;
5254
5255         var Uint8Array$1 = global$p.Uint8Array;
5256         var Uint8ArrayPrototype = Uint8Array$1 && Uint8Array$1.prototype || {};
5257         var arrayToString = [].toString;
5258         var join$5 = uncurryThis$w([].join);
5259
5260         if (fails$u(function () { arrayToString.call({}); })) {
5261           arrayToString = function toString() {
5262             return join$5(this);
5263           };
5264         }
5265
5266         var IS_NOT_ARRAY_METHOD = Uint8ArrayPrototype.toString != arrayToString;
5267
5268         // `%TypedArray%.prototype.toString` method
5269         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.tostring
5270         exportTypedArrayMethod('toString', arrayToString, IS_NOT_ARRAY_METHOD);
5271
5272         var $$Z = _export;
5273         var uncurryThis$v = functionUncurryThis;
5274         var IndexedObject$1 = indexedObject;
5275         var toIndexedObject$3 = toIndexedObject$c;
5276         var arrayMethodIsStrict$5 = arrayMethodIsStrict$9;
5277
5278         var un$Join = uncurryThis$v([].join);
5279
5280         var ES3_STRINGS = IndexedObject$1 != Object;
5281         var STRICT_METHOD$5 = arrayMethodIsStrict$5('join', ',');
5282
5283         // `Array.prototype.join` method
5284         // https://tc39.es/ecma262/#sec-array.prototype.join
5285         $$Z({ target: 'Array', proto: true, forced: ES3_STRINGS || !STRICT_METHOD$5 }, {
5286           join: function join(separator) {
5287             return un$Join(toIndexedObject$3(this), separator === undefined ? ',' : separator);
5288           }
5289         });
5290
5291         var toPropertyKey = toPropertyKey$5;
5292         var definePropertyModule = objectDefineProperty;
5293         var createPropertyDescriptor$1 = createPropertyDescriptor$7;
5294
5295         var createProperty$4 = function (object, key, value) {
5296           var propertyKey = toPropertyKey(key);
5297           if (propertyKey in object) definePropertyModule.f(object, propertyKey, createPropertyDescriptor$1(0, value));
5298           else object[propertyKey] = value;
5299         };
5300
5301         var $$Y = _export;
5302         var global$o = global$1m;
5303         var isArray$4 = isArray$8;
5304         var isConstructor$1 = isConstructor$4;
5305         var isObject$e = isObject$s;
5306         var toAbsoluteIndex$2 = toAbsoluteIndex$8;
5307         var lengthOfArrayLike$6 = lengthOfArrayLike$g;
5308         var toIndexedObject$2 = toIndexedObject$c;
5309         var createProperty$3 = createProperty$4;
5310         var wellKnownSymbol$8 = wellKnownSymbol$t;
5311         var arrayMethodHasSpeciesSupport$3 = arrayMethodHasSpeciesSupport$5;
5312         var un$Slice = arraySlice$c;
5313
5314         var HAS_SPECIES_SUPPORT$2 = arrayMethodHasSpeciesSupport$3('slice');
5315
5316         var SPECIES$1 = wellKnownSymbol$8('species');
5317         var Array$2 = global$o.Array;
5318         var max$3 = Math.max;
5319
5320         // `Array.prototype.slice` method
5321         // https://tc39.es/ecma262/#sec-array.prototype.slice
5322         // fallback for not array-like ES3 strings and DOM objects
5323         $$Y({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$2 }, {
5324           slice: function slice(start, end) {
5325             var O = toIndexedObject$2(this);
5326             var length = lengthOfArrayLike$6(O);
5327             var k = toAbsoluteIndex$2(start, length);
5328             var fin = toAbsoluteIndex$2(end === undefined ? length : end, length);
5329             // inline `ArraySpeciesCreate` for usage native `Array#slice` where it's possible
5330             var Constructor, result, n;
5331             if (isArray$4(O)) {
5332               Constructor = O.constructor;
5333               // cross-realm fallback
5334               if (isConstructor$1(Constructor) && (Constructor === Array$2 || isArray$4(Constructor.prototype))) {
5335                 Constructor = undefined;
5336               } else if (isObject$e(Constructor)) {
5337                 Constructor = Constructor[SPECIES$1];
5338                 if (Constructor === null) Constructor = undefined;
5339               }
5340               if (Constructor === Array$2 || Constructor === undefined) {
5341                 return un$Slice(O, k, fin);
5342               }
5343             }
5344             result = new (Constructor === undefined ? Array$2 : Constructor)(max$3(fin - k, 0));
5345             for (n = 0; k < fin; k++, n++) if (k in O) createProperty$3(result, n, O[k]);
5346             result.length = n;
5347             return result;
5348           }
5349         });
5350
5351         var fails$t = fails$S;
5352         var wellKnownSymbol$7 = wellKnownSymbol$t;
5353         var IS_PURE = isPure;
5354
5355         var ITERATOR$3 = wellKnownSymbol$7('iterator');
5356
5357         var nativeUrl = !fails$t(function () {
5358           var url = new URL('b?a=1&b=2&c=3', 'http://a');
5359           var searchParams = url.searchParams;
5360           var result = '';
5361           url.pathname = 'c%20d';
5362           searchParams.forEach(function (value, key) {
5363             searchParams['delete']('b');
5364             result += key + value;
5365           });
5366           return (IS_PURE && !url.toJSON)
5367             || !searchParams.sort
5368             || url.href !== 'http://a/c%20d?a=1&c=3'
5369             || searchParams.get('c') !== '3'
5370             || String(new URLSearchParams('?a=1')) !== 'a=1'
5371             || !searchParams[ITERATOR$3]
5372             // throws in Edge
5373             || new URL('https://a@b').username !== 'a'
5374             || new URLSearchParams(new URLSearchParams('a=b')).get('a') !== 'b'
5375             // not punycoded in Edge
5376             || new URL('http://тест').host !== 'xn--e1aybc'
5377             // not escaped in Chrome 62-
5378             || new URL('http://a#б').hash !== '#%D0%B1'
5379             // fails in Chrome 66-
5380             || result !== 'a1c3'
5381             // throws in Safari
5382             || new URL('http://x', undefined).host !== 'x';
5383         });
5384
5385         // TODO: in core-js@4, move /modules/ dependencies to public entries for better optimization by tools like `preset-env`
5386
5387         var $$X = _export;
5388         var global$n = global$1m;
5389         var getBuiltIn$2 = getBuiltIn$b;
5390         var call$a = functionCall;
5391         var uncurryThis$u = functionUncurryThis;
5392         var USE_NATIVE_URL$1 = nativeUrl;
5393         var redefine$7 = redefine$h.exports;
5394         var redefineAll$1 = redefineAll$4;
5395         var setToStringTag$4 = setToStringTag$a;
5396         var createIteratorConstructor = createIteratorConstructor$2;
5397         var InternalStateModule$2 = internalState;
5398         var anInstance$3 = anInstance$7;
5399         var isCallable$5 = isCallable$r;
5400         var hasOwn$6 = hasOwnProperty_1;
5401         var bind$8 = functionBindContext;
5402         var classof$3 = classof$d;
5403         var anObject$9 = anObject$n;
5404         var isObject$d = isObject$s;
5405         var $toString$2 = toString$k;
5406         var create$6 = objectCreate;
5407         var createPropertyDescriptor = createPropertyDescriptor$7;
5408         var getIterator$1 = getIterator$4;
5409         var getIteratorMethod$1 = getIteratorMethod$5;
5410         var wellKnownSymbol$6 = wellKnownSymbol$t;
5411         var arraySort = arraySort$1;
5412
5413         var ITERATOR$2 = wellKnownSymbol$6('iterator');
5414         var URL_SEARCH_PARAMS = 'URLSearchParams';
5415         var URL_SEARCH_PARAMS_ITERATOR = URL_SEARCH_PARAMS + 'Iterator';
5416         var setInternalState$2 = InternalStateModule$2.set;
5417         var getInternalParamsState = InternalStateModule$2.getterFor(URL_SEARCH_PARAMS);
5418         var getInternalIteratorState = InternalStateModule$2.getterFor(URL_SEARCH_PARAMS_ITERATOR);
5419
5420         var n$Fetch = getBuiltIn$2('fetch');
5421         var N$Request = getBuiltIn$2('Request');
5422         var Headers$1 = getBuiltIn$2('Headers');
5423         var RequestPrototype = N$Request && N$Request.prototype;
5424         var HeadersPrototype = Headers$1 && Headers$1.prototype;
5425         var RegExp$1 = global$n.RegExp;
5426         var TypeError$8 = global$n.TypeError;
5427         var decodeURIComponent$1 = global$n.decodeURIComponent;
5428         var encodeURIComponent$1 = global$n.encodeURIComponent;
5429         var charAt$5 = uncurryThis$u(''.charAt);
5430         var join$4 = uncurryThis$u([].join);
5431         var push$7 = uncurryThis$u([].push);
5432         var replace$6 = uncurryThis$u(''.replace);
5433         var shift$1 = uncurryThis$u([].shift);
5434         var splice = uncurryThis$u([].splice);
5435         var split$3 = uncurryThis$u(''.split);
5436         var stringSlice$8 = uncurryThis$u(''.slice);
5437
5438         var plus = /\+/g;
5439         var sequences = Array(4);
5440
5441         var percentSequence = function (bytes) {
5442           return sequences[bytes - 1] || (sequences[bytes - 1] = RegExp$1('((?:%[\\da-f]{2}){' + bytes + '})', 'gi'));
5443         };
5444
5445         var percentDecode = function (sequence) {
5446           try {
5447             return decodeURIComponent$1(sequence);
5448           } catch (error) {
5449             return sequence;
5450           }
5451         };
5452
5453         var deserialize = function (it) {
5454           var result = replace$6(it, plus, ' ');
5455           var bytes = 4;
5456           try {
5457             return decodeURIComponent$1(result);
5458           } catch (error) {
5459             while (bytes) {
5460               result = replace$6(result, percentSequence(bytes--), percentDecode);
5461             }
5462             return result;
5463           }
5464         };
5465
5466         var find$1 = /[!'()~]|%20/g;
5467
5468         var replacements = {
5469           '!': '%21',
5470           "'": '%27',
5471           '(': '%28',
5472           ')': '%29',
5473           '~': '%7E',
5474           '%20': '+'
5475         };
5476
5477         var replacer = function (match) {
5478           return replacements[match];
5479         };
5480
5481         var serialize = function (it) {
5482           return replace$6(encodeURIComponent$1(it), find$1, replacer);
5483         };
5484
5485         var parseSearchParams = function (result, query) {
5486           if (query) {
5487             var attributes = split$3(query, '&');
5488             var index = 0;
5489             var attribute, entry;
5490             while (index < attributes.length) {
5491               attribute = attributes[index++];
5492               if (attribute.length) {
5493                 entry = split$3(attribute, '=');
5494                 push$7(result, {
5495                   key: deserialize(shift$1(entry)),
5496                   value: deserialize(join$4(entry, '='))
5497                 });
5498               }
5499             }
5500           }
5501         };
5502
5503         var updateSearchParams = function (query) {
5504           this.entries.length = 0;
5505           parseSearchParams(this.entries, query);
5506         };
5507
5508         var validateArgumentsLength = function (passed, required) {
5509           if (passed < required) throw TypeError$8('Not enough arguments');
5510         };
5511
5512         var URLSearchParamsIterator = createIteratorConstructor(function Iterator(params, kind) {
5513           setInternalState$2(this, {
5514             type: URL_SEARCH_PARAMS_ITERATOR,
5515             iterator: getIterator$1(getInternalParamsState(params).entries),
5516             kind: kind
5517           });
5518         }, 'Iterator', function next() {
5519           var state = getInternalIteratorState(this);
5520           var kind = state.kind;
5521           var step = state.iterator.next();
5522           var entry = step.value;
5523           if (!step.done) {
5524             step.value = kind === 'keys' ? entry.key : kind === 'values' ? entry.value : [entry.key, entry.value];
5525           } return step;
5526         });
5527
5528         // `URLSearchParams` constructor
5529         // https://url.spec.whatwg.org/#interface-urlsearchparams
5530         var URLSearchParamsConstructor = function URLSearchParams(/* init */) {
5531           anInstance$3(this, URLSearchParamsPrototype);
5532           var init = arguments.length > 0 ? arguments[0] : undefined;
5533           var that = this;
5534           var entries = [];
5535           var iteratorMethod, iterator, next, step, entryIterator, entryNext, first, second, key;
5536
5537           setInternalState$2(that, {
5538             type: URL_SEARCH_PARAMS,
5539             entries: entries,
5540             updateURL: function () { /* empty */ },
5541             updateSearchParams: updateSearchParams
5542           });
5543
5544           if (init !== undefined) {
5545             if (isObject$d(init)) {
5546               iteratorMethod = getIteratorMethod$1(init);
5547               if (iteratorMethod) {
5548                 iterator = getIterator$1(init, iteratorMethod);
5549                 next = iterator.next;
5550                 while (!(step = call$a(next, iterator)).done) {
5551                   entryIterator = getIterator$1(anObject$9(step.value));
5552                   entryNext = entryIterator.next;
5553                   if (
5554                     (first = call$a(entryNext, entryIterator)).done ||
5555                     (second = call$a(entryNext, entryIterator)).done ||
5556                     !call$a(entryNext, entryIterator).done
5557                   ) throw TypeError$8('Expected sequence with length 2');
5558                   push$7(entries, { key: $toString$2(first.value), value: $toString$2(second.value) });
5559                 }
5560               } else for (key in init) if (hasOwn$6(init, key)) push$7(entries, { key: key, value: $toString$2(init[key]) });
5561             } else {
5562               parseSearchParams(
5563                 entries,
5564                 typeof init == 'string' ? charAt$5(init, 0) === '?' ? stringSlice$8(init, 1) : init : $toString$2(init)
5565               );
5566             }
5567           }
5568         };
5569
5570         var URLSearchParamsPrototype = URLSearchParamsConstructor.prototype;
5571
5572         redefineAll$1(URLSearchParamsPrototype, {
5573           // `URLSearchParams.prototype.append` method
5574           // https://url.spec.whatwg.org/#dom-urlsearchparams-append
5575           append: function append(name, value) {
5576             validateArgumentsLength(arguments.length, 2);
5577             var state = getInternalParamsState(this);
5578             push$7(state.entries, { key: $toString$2(name), value: $toString$2(value) });
5579             state.updateURL();
5580           },
5581           // `URLSearchParams.prototype.delete` method
5582           // https://url.spec.whatwg.org/#dom-urlsearchparams-delete
5583           'delete': function (name) {
5584             validateArgumentsLength(arguments.length, 1);
5585             var state = getInternalParamsState(this);
5586             var entries = state.entries;
5587             var key = $toString$2(name);
5588             var index = 0;
5589             while (index < entries.length) {
5590               if (entries[index].key === key) splice(entries, index, 1);
5591               else index++;
5592             }
5593             state.updateURL();
5594           },
5595           // `URLSearchParams.prototype.get` method
5596           // https://url.spec.whatwg.org/#dom-urlsearchparams-get
5597           get: function get(name) {
5598             validateArgumentsLength(arguments.length, 1);
5599             var entries = getInternalParamsState(this).entries;
5600             var key = $toString$2(name);
5601             var index = 0;
5602             for (; index < entries.length; index++) {
5603               if (entries[index].key === key) return entries[index].value;
5604             }
5605             return null;
5606           },
5607           // `URLSearchParams.prototype.getAll` method
5608           // https://url.spec.whatwg.org/#dom-urlsearchparams-getall
5609           getAll: function getAll(name) {
5610             validateArgumentsLength(arguments.length, 1);
5611             var entries = getInternalParamsState(this).entries;
5612             var key = $toString$2(name);
5613             var result = [];
5614             var index = 0;
5615             for (; index < entries.length; index++) {
5616               if (entries[index].key === key) push$7(result, entries[index].value);
5617             }
5618             return result;
5619           },
5620           // `URLSearchParams.prototype.has` method
5621           // https://url.spec.whatwg.org/#dom-urlsearchparams-has
5622           has: function has(name) {
5623             validateArgumentsLength(arguments.length, 1);
5624             var entries = getInternalParamsState(this).entries;
5625             var key = $toString$2(name);
5626             var index = 0;
5627             while (index < entries.length) {
5628               if (entries[index++].key === key) return true;
5629             }
5630             return false;
5631           },
5632           // `URLSearchParams.prototype.set` method
5633           // https://url.spec.whatwg.org/#dom-urlsearchparams-set
5634           set: function set(name, value) {
5635             validateArgumentsLength(arguments.length, 1);
5636             var state = getInternalParamsState(this);
5637             var entries = state.entries;
5638             var found = false;
5639             var key = $toString$2(name);
5640             var val = $toString$2(value);
5641             var index = 0;
5642             var entry;
5643             for (; index < entries.length; index++) {
5644               entry = entries[index];
5645               if (entry.key === key) {
5646                 if (found) splice(entries, index--, 1);
5647                 else {
5648                   found = true;
5649                   entry.value = val;
5650                 }
5651               }
5652             }
5653             if (!found) push$7(entries, { key: key, value: val });
5654             state.updateURL();
5655           },
5656           // `URLSearchParams.prototype.sort` method
5657           // https://url.spec.whatwg.org/#dom-urlsearchparams-sort
5658           sort: function sort() {
5659             var state = getInternalParamsState(this);
5660             arraySort(state.entries, function (a, b) {
5661               return a.key > b.key ? 1 : -1;
5662             });
5663             state.updateURL();
5664           },
5665           // `URLSearchParams.prototype.forEach` method
5666           forEach: function forEach(callback /* , thisArg */) {
5667             var entries = getInternalParamsState(this).entries;
5668             var boundFunction = bind$8(callback, arguments.length > 1 ? arguments[1] : undefined);
5669             var index = 0;
5670             var entry;
5671             while (index < entries.length) {
5672               entry = entries[index++];
5673               boundFunction(entry.value, entry.key, this);
5674             }
5675           },
5676           // `URLSearchParams.prototype.keys` method
5677           keys: function keys() {
5678             return new URLSearchParamsIterator(this, 'keys');
5679           },
5680           // `URLSearchParams.prototype.values` method
5681           values: function values() {
5682             return new URLSearchParamsIterator(this, 'values');
5683           },
5684           // `URLSearchParams.prototype.entries` method
5685           entries: function entries() {
5686             return new URLSearchParamsIterator(this, 'entries');
5687           }
5688         }, { enumerable: true });
5689
5690         // `URLSearchParams.prototype[@@iterator]` method
5691         redefine$7(URLSearchParamsPrototype, ITERATOR$2, URLSearchParamsPrototype.entries, { name: 'entries' });
5692
5693         // `URLSearchParams.prototype.toString` method
5694         // https://url.spec.whatwg.org/#urlsearchparams-stringification-behavior
5695         redefine$7(URLSearchParamsPrototype, 'toString', function toString() {
5696           var entries = getInternalParamsState(this).entries;
5697           var result = [];
5698           var index = 0;
5699           var entry;
5700           while (index < entries.length) {
5701             entry = entries[index++];
5702             push$7(result, serialize(entry.key) + '=' + serialize(entry.value));
5703           } return join$4(result, '&');
5704         }, { enumerable: true });
5705
5706         setToStringTag$4(URLSearchParamsConstructor, URL_SEARCH_PARAMS);
5707
5708         $$X({ global: true, forced: !USE_NATIVE_URL$1 }, {
5709           URLSearchParams: URLSearchParamsConstructor
5710         });
5711
5712         // Wrap `fetch` and `Request` for correct work with polyfilled `URLSearchParams`
5713         if (!USE_NATIVE_URL$1 && isCallable$5(Headers$1)) {
5714           var headersHas = uncurryThis$u(HeadersPrototype.has);
5715           var headersSet = uncurryThis$u(HeadersPrototype.set);
5716
5717           var wrapRequestOptions = function (init) {
5718             if (isObject$d(init)) {
5719               var body = init.body;
5720               var headers;
5721               if (classof$3(body) === URL_SEARCH_PARAMS) {
5722                 headers = init.headers ? new Headers$1(init.headers) : new Headers$1();
5723                 if (!headersHas(headers, 'content-type')) {
5724                   headersSet(headers, 'content-type', 'application/x-www-form-urlencoded;charset=UTF-8');
5725                 }
5726                 return create$6(init, {
5727                   body: createPropertyDescriptor(0, $toString$2(body)),
5728                   headers: createPropertyDescriptor(0, headers)
5729                 });
5730               }
5731             } return init;
5732           };
5733
5734           if (isCallable$5(n$Fetch)) {
5735             $$X({ global: true, enumerable: true, forced: true }, {
5736               fetch: function fetch(input /* , init */) {
5737                 return n$Fetch(input, arguments.length > 1 ? wrapRequestOptions(arguments[1]) : {});
5738               }
5739             });
5740           }
5741
5742           if (isCallable$5(N$Request)) {
5743             var RequestConstructor = function Request(input /* , init */) {
5744               anInstance$3(this, RequestPrototype);
5745               return new N$Request(input, arguments.length > 1 ? wrapRequestOptions(arguments[1]) : {});
5746             };
5747
5748             RequestPrototype.constructor = RequestConstructor;
5749             RequestConstructor.prototype = RequestPrototype;
5750
5751             $$X({ global: true, forced: true }, {
5752               Request: RequestConstructor
5753             });
5754           }
5755         }
5756
5757         var web_urlSearchParams = {
5758           URLSearchParams: URLSearchParamsConstructor,
5759           getState: getInternalParamsState
5760         };
5761
5762         var uncurryThis$t = functionUncurryThis;
5763         var PROPER_FUNCTION_NAME$1 = functionName.PROPER;
5764         var redefine$6 = redefine$h.exports;
5765         var anObject$8 = anObject$n;
5766         var isPrototypeOf$2 = objectIsPrototypeOf;
5767         var $toString$1 = toString$k;
5768         var fails$s = fails$S;
5769         var regExpFlags$2 = regexpFlags$1;
5770
5771         var TO_STRING = 'toString';
5772         var RegExpPrototype$3 = RegExp.prototype;
5773         var n$ToString = RegExpPrototype$3[TO_STRING];
5774         var getFlags$1 = uncurryThis$t(regExpFlags$2);
5775
5776         var NOT_GENERIC = fails$s(function () { return n$ToString.call({ source: 'a', flags: 'b' }) != '/a/b'; });
5777         // FF44- RegExp#toString has a wrong name
5778         var INCORRECT_NAME = PROPER_FUNCTION_NAME$1 && n$ToString.name != TO_STRING;
5779
5780         // `RegExp.prototype.toString` method
5781         // https://tc39.es/ecma262/#sec-regexp.prototype.tostring
5782         if (NOT_GENERIC || INCORRECT_NAME) {
5783           redefine$6(RegExp.prototype, TO_STRING, function toString() {
5784             var R = anObject$8(this);
5785             var p = $toString$1(R.source);
5786             var rf = R.flags;
5787             var f = $toString$1(rf === undefined && isPrototypeOf$2(RegExpPrototype$3, R) && !('flags' in RegExpPrototype$3) ? getFlags$1(R) : rf);
5788             return '/' + p + '/' + f;
5789           }, { unsafe: true });
5790         }
5791
5792         // TODO: Remove from `core-js@4` since it's moved to entry points
5793
5794         var uncurryThis$s = functionUncurryThis;
5795         var redefine$5 = redefine$h.exports;
5796         var regexpExec$2 = regexpExec$3;
5797         var fails$r = fails$S;
5798         var wellKnownSymbol$5 = wellKnownSymbol$t;
5799         var createNonEnumerableProperty$1 = createNonEnumerableProperty$b;
5800
5801         var SPECIES = wellKnownSymbol$5('species');
5802         var RegExpPrototype$2 = RegExp.prototype;
5803
5804         var fixRegexpWellKnownSymbolLogic = function (KEY, exec, FORCED, SHAM) {
5805           var SYMBOL = wellKnownSymbol$5(KEY);
5806
5807           var DELEGATES_TO_SYMBOL = !fails$r(function () {
5808             // String methods call symbol-named RegEp methods
5809             var O = {};
5810             O[SYMBOL] = function () { return 7; };
5811             return ''[KEY](O) != 7;
5812           });
5813
5814           var DELEGATES_TO_EXEC = DELEGATES_TO_SYMBOL && !fails$r(function () {
5815             // Symbol-named RegExp methods call .exec
5816             var execCalled = false;
5817             var re = /a/;
5818
5819             if (KEY === 'split') {
5820               // We can't use real regex here since it causes deoptimization
5821               // and serious performance degradation in V8
5822               // https://github.com/zloirock/core-js/issues/306
5823               re = {};
5824               // RegExp[@@split] doesn't call the regex's exec method, but first creates
5825               // a new one. We need to return the patched regex when creating the new one.
5826               re.constructor = {};
5827               re.constructor[SPECIES] = function () { return re; };
5828               re.flags = '';
5829               re[SYMBOL] = /./[SYMBOL];
5830             }
5831
5832             re.exec = function () { execCalled = true; return null; };
5833
5834             re[SYMBOL]('');
5835             return !execCalled;
5836           });
5837
5838           if (
5839             !DELEGATES_TO_SYMBOL ||
5840             !DELEGATES_TO_EXEC ||
5841             FORCED
5842           ) {
5843             var uncurriedNativeRegExpMethod = uncurryThis$s(/./[SYMBOL]);
5844             var methods = exec(SYMBOL, ''[KEY], function (nativeMethod, regexp, str, arg2, forceStringMethod) {
5845               var uncurriedNativeMethod = uncurryThis$s(nativeMethod);
5846               var $exec = regexp.exec;
5847               if ($exec === regexpExec$2 || $exec === RegExpPrototype$2.exec) {
5848                 if (DELEGATES_TO_SYMBOL && !forceStringMethod) {
5849                   // The native String method already delegates to @@method (this
5850                   // polyfilled function), leasing to infinite recursion.
5851                   // We avoid it by directly calling the native @@method method.
5852                   return { done: true, value: uncurriedNativeRegExpMethod(regexp, str, arg2) };
5853                 }
5854                 return { done: true, value: uncurriedNativeMethod(str, regexp, arg2) };
5855               }
5856               return { done: false };
5857             });
5858
5859             redefine$5(String.prototype, KEY, methods[0]);
5860             redefine$5(RegExpPrototype$2, SYMBOL, methods[1]);
5861           }
5862
5863           if (SHAM) createNonEnumerableProperty$1(RegExpPrototype$2[SYMBOL], 'sham', true);
5864         };
5865
5866         var charAt$4 = stringMultibyte.charAt;
5867
5868         // `AdvanceStringIndex` abstract operation
5869         // https://tc39.es/ecma262/#sec-advancestringindex
5870         var advanceStringIndex$3 = function (S, index, unicode) {
5871           return index + (unicode ? charAt$4(S, index).length : 1);
5872         };
5873
5874         var uncurryThis$r = functionUncurryThis;
5875         var toObject$9 = toObject$j;
5876
5877         var floor$3 = Math.floor;
5878         var charAt$3 = uncurryThis$r(''.charAt);
5879         var replace$5 = uncurryThis$r(''.replace);
5880         var stringSlice$7 = uncurryThis$r(''.slice);
5881         var SUBSTITUTION_SYMBOLS = /\$([$&'`]|\d{1,2}|<[^>]*>)/g;
5882         var SUBSTITUTION_SYMBOLS_NO_NAMED = /\$([$&'`]|\d{1,2})/g;
5883
5884         // `GetSubstitution` abstract operation
5885         // https://tc39.es/ecma262/#sec-getsubstitution
5886         var getSubstitution$1 = function (matched, str, position, captures, namedCaptures, replacement) {
5887           var tailPos = position + matched.length;
5888           var m = captures.length;
5889           var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED;
5890           if (namedCaptures !== undefined) {
5891             namedCaptures = toObject$9(namedCaptures);
5892             symbols = SUBSTITUTION_SYMBOLS;
5893           }
5894           return replace$5(replacement, symbols, function (match, ch) {
5895             var capture;
5896             switch (charAt$3(ch, 0)) {
5897               case '$': return '$';
5898               case '&': return matched;
5899               case '`': return stringSlice$7(str, 0, position);
5900               case "'": return stringSlice$7(str, tailPos);
5901               case '<':
5902                 capture = namedCaptures[stringSlice$7(ch, 1, -1)];
5903                 break;
5904               default: // \d\d?
5905                 var n = +ch;
5906                 if (n === 0) return match;
5907                 if (n > m) {
5908                   var f = floor$3(n / 10);
5909                   if (f === 0) return match;
5910                   if (f <= m) return captures[f - 1] === undefined ? charAt$3(ch, 1) : captures[f - 1] + charAt$3(ch, 1);
5911                   return match;
5912                 }
5913                 capture = captures[n - 1];
5914             }
5915             return capture === undefined ? '' : capture;
5916           });
5917         };
5918
5919         var global$m = global$1m;
5920         var call$9 = functionCall;
5921         var anObject$7 = anObject$n;
5922         var isCallable$4 = isCallable$r;
5923         var classof$2 = classofRaw$1;
5924         var regexpExec$1 = regexpExec$3;
5925
5926         var TypeError$7 = global$m.TypeError;
5927
5928         // `RegExpExec` abstract operation
5929         // https://tc39.es/ecma262/#sec-regexpexec
5930         var regexpExecAbstract = function (R, S) {
5931           var exec = R.exec;
5932           if (isCallable$4(exec)) {
5933             var result = call$9(exec, R, S);
5934             if (result !== null) anObject$7(result);
5935             return result;
5936           }
5937           if (classof$2(R) === 'RegExp') return call$9(regexpExec$1, R, S);
5938           throw TypeError$7('RegExp#exec called on incompatible receiver');
5939         };
5940
5941         var apply$3 = functionApply;
5942         var call$8 = functionCall;
5943         var uncurryThis$q = functionUncurryThis;
5944         var fixRegExpWellKnownSymbolLogic$3 = fixRegexpWellKnownSymbolLogic;
5945         var fails$q = fails$S;
5946         var anObject$6 = anObject$n;
5947         var isCallable$3 = isCallable$r;
5948         var toIntegerOrInfinity$3 = toIntegerOrInfinity$b;
5949         var toLength$5 = toLength$c;
5950         var toString$f = toString$k;
5951         var requireObjectCoercible$a = requireObjectCoercible$e;
5952         var advanceStringIndex$2 = advanceStringIndex$3;
5953         var getMethod$3 = getMethod$7;
5954         var getSubstitution = getSubstitution$1;
5955         var regExpExec$3 = regexpExecAbstract;
5956         var wellKnownSymbol$4 = wellKnownSymbol$t;
5957
5958         var REPLACE = wellKnownSymbol$4('replace');
5959         var max$2 = Math.max;
5960         var min$5 = Math.min;
5961         var concat$2 = uncurryThis$q([].concat);
5962         var push$6 = uncurryThis$q([].push);
5963         var stringIndexOf$2 = uncurryThis$q(''.indexOf);
5964         var stringSlice$6 = uncurryThis$q(''.slice);
5965
5966         var maybeToString = function (it) {
5967           return it === undefined ? it : String(it);
5968         };
5969
5970         // IE <= 11 replaces $0 with the whole match, as if it was $&
5971         // https://stackoverflow.com/questions/6024666/getting-ie-to-replace-a-regex-with-the-literal-string-0
5972         var REPLACE_KEEPS_$0 = (function () {
5973           // eslint-disable-next-line regexp/prefer-escape-replacement-dollar-char -- required for testing
5974           return 'a'.replace(/./, '$0') === '$0';
5975         })();
5976
5977         // Safari <= 13.0.3(?) substitutes nth capture where n>m with an empty string
5978         var REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE = (function () {
5979           if (/./[REPLACE]) {
5980             return /./[REPLACE]('a', '$0') === '';
5981           }
5982           return false;
5983         })();
5984
5985         var REPLACE_SUPPORTS_NAMED_GROUPS = !fails$q(function () {
5986           var re = /./;
5987           re.exec = function () {
5988             var result = [];
5989             result.groups = { a: '7' };
5990             return result;
5991           };
5992           // eslint-disable-next-line regexp/no-useless-dollar-replacements -- false positive
5993           return ''.replace(re, '$<a>') !== '7';
5994         });
5995
5996         // @@replace logic
5997         fixRegExpWellKnownSymbolLogic$3('replace', function (_, nativeReplace, maybeCallNative) {
5998           var UNSAFE_SUBSTITUTE = REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE ? '$' : '$0';
5999
6000           return [
6001             // `String.prototype.replace` method
6002             // https://tc39.es/ecma262/#sec-string.prototype.replace
6003             function replace(searchValue, replaceValue) {
6004               var O = requireObjectCoercible$a(this);
6005               var replacer = searchValue == undefined ? undefined : getMethod$3(searchValue, REPLACE);
6006               return replacer
6007                 ? call$8(replacer, searchValue, O, replaceValue)
6008                 : call$8(nativeReplace, toString$f(O), searchValue, replaceValue);
6009             },
6010             // `RegExp.prototype[@@replace]` method
6011             // https://tc39.es/ecma262/#sec-regexp.prototype-@@replace
6012             function (string, replaceValue) {
6013               var rx = anObject$6(this);
6014               var S = toString$f(string);
6015
6016               if (
6017                 typeof replaceValue == 'string' &&
6018                 stringIndexOf$2(replaceValue, UNSAFE_SUBSTITUTE) === -1 &&
6019                 stringIndexOf$2(replaceValue, '$<') === -1
6020               ) {
6021                 var res = maybeCallNative(nativeReplace, rx, S, replaceValue);
6022                 if (res.done) return res.value;
6023               }
6024
6025               var functionalReplace = isCallable$3(replaceValue);
6026               if (!functionalReplace) replaceValue = toString$f(replaceValue);
6027
6028               var global = rx.global;
6029               if (global) {
6030                 var fullUnicode = rx.unicode;
6031                 rx.lastIndex = 0;
6032               }
6033               var results = [];
6034               while (true) {
6035                 var result = regExpExec$3(rx, S);
6036                 if (result === null) break;
6037
6038                 push$6(results, result);
6039                 if (!global) break;
6040
6041                 var matchStr = toString$f(result[0]);
6042                 if (matchStr === '') rx.lastIndex = advanceStringIndex$2(S, toLength$5(rx.lastIndex), fullUnicode);
6043               }
6044
6045               var accumulatedResult = '';
6046               var nextSourcePosition = 0;
6047               for (var i = 0; i < results.length; i++) {
6048                 result = results[i];
6049
6050                 var matched = toString$f(result[0]);
6051                 var position = max$2(min$5(toIntegerOrInfinity$3(result.index), S.length), 0);
6052                 var captures = [];
6053                 // NOTE: This is equivalent to
6054                 //   captures = result.slice(1).map(maybeToString)
6055                 // but for some reason `nativeSlice.call(result, 1, result.length)` (called in
6056                 // the slice polyfill when slicing native arrays) "doesn't work" in safari 9 and
6057                 // causes a crash (https://pastebin.com/N21QzeQA) when trying to debug it.
6058                 for (var j = 1; j < result.length; j++) push$6(captures, maybeToString(result[j]));
6059                 var namedCaptures = result.groups;
6060                 if (functionalReplace) {
6061                   var replacerArgs = concat$2([matched], captures, position, S);
6062                   if (namedCaptures !== undefined) push$6(replacerArgs, namedCaptures);
6063                   var replacement = toString$f(apply$3(replaceValue, undefined, replacerArgs));
6064                 } else {
6065                   replacement = getSubstitution(matched, S, position, captures, namedCaptures, replaceValue);
6066                 }
6067                 if (position >= nextSourcePosition) {
6068                   accumulatedResult += stringSlice$6(S, nextSourcePosition, position) + replacement;
6069                   nextSourcePosition = position + matched.length;
6070                 }
6071               }
6072               return accumulatedResult + stringSlice$6(S, nextSourcePosition);
6073             }
6074           ];
6075         }, !REPLACE_SUPPORTS_NAMED_GROUPS || !REPLACE_KEEPS_$0 || REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE);
6076
6077         var isObject$c = isObject$s;
6078         var classof$1 = classofRaw$1;
6079         var wellKnownSymbol$3 = wellKnownSymbol$t;
6080
6081         var MATCH$2 = wellKnownSymbol$3('match');
6082
6083         // `IsRegExp` abstract operation
6084         // https://tc39.es/ecma262/#sec-isregexp
6085         var isRegexp = function (it) {
6086           var isRegExp;
6087           return isObject$c(it) && ((isRegExp = it[MATCH$2]) !== undefined ? !!isRegExp : classof$1(it) == 'RegExp');
6088         };
6089
6090         var apply$2 = functionApply;
6091         var call$7 = functionCall;
6092         var uncurryThis$p = functionUncurryThis;
6093         var fixRegExpWellKnownSymbolLogic$2 = fixRegexpWellKnownSymbolLogic;
6094         var isRegExp$2 = isRegexp;
6095         var anObject$5 = anObject$n;
6096         var requireObjectCoercible$9 = requireObjectCoercible$e;
6097         var speciesConstructor$1 = speciesConstructor$5;
6098         var advanceStringIndex$1 = advanceStringIndex$3;
6099         var toLength$4 = toLength$c;
6100         var toString$e = toString$k;
6101         var getMethod$2 = getMethod$7;
6102         var arraySlice$4 = arraySlice$c;
6103         var callRegExpExec = regexpExecAbstract;
6104         var regexpExec = regexpExec$3;
6105         var stickyHelpers$1 = regexpStickyHelpers;
6106         var fails$p = fails$S;
6107
6108         var UNSUPPORTED_Y$1 = stickyHelpers$1.UNSUPPORTED_Y;
6109         var MAX_UINT32 = 0xFFFFFFFF;
6110         var min$4 = Math.min;
6111         var $push = [].push;
6112         var exec$4 = uncurryThis$p(/./.exec);
6113         var push$5 = uncurryThis$p($push);
6114         var stringSlice$5 = uncurryThis$p(''.slice);
6115
6116         // Chrome 51 has a buggy "split" implementation when RegExp#exec !== nativeExec
6117         // Weex JS has frozen built-in prototypes, so use try / catch wrapper
6118         var SPLIT_WORKS_WITH_OVERWRITTEN_EXEC = !fails$p(function () {
6119           // eslint-disable-next-line regexp/no-empty-group -- required for testing
6120           var re = /(?:)/;
6121           var originalExec = re.exec;
6122           re.exec = function () { return originalExec.apply(this, arguments); };
6123           var result = 'ab'.split(re);
6124           return result.length !== 2 || result[0] !== 'a' || result[1] !== 'b';
6125         });
6126
6127         // @@split logic
6128         fixRegExpWellKnownSymbolLogic$2('split', function (SPLIT, nativeSplit, maybeCallNative) {
6129           var internalSplit;
6130           if (
6131             'abbc'.split(/(b)*/)[1] == 'c' ||
6132             // eslint-disable-next-line regexp/no-empty-group -- required for testing
6133             'test'.split(/(?:)/, -1).length != 4 ||
6134             'ab'.split(/(?:ab)*/).length != 2 ||
6135             '.'.split(/(.?)(.?)/).length != 4 ||
6136             // eslint-disable-next-line regexp/no-empty-capturing-group, regexp/no-empty-group -- required for testing
6137             '.'.split(/()()/).length > 1 ||
6138             ''.split(/.?/).length
6139           ) {
6140             // based on es5-shim implementation, need to rework it
6141             internalSplit = function (separator, limit) {
6142               var string = toString$e(requireObjectCoercible$9(this));
6143               var lim = limit === undefined ? MAX_UINT32 : limit >>> 0;
6144               if (lim === 0) return [];
6145               if (separator === undefined) return [string];
6146               // If `separator` is not a regex, use native split
6147               if (!isRegExp$2(separator)) {
6148                 return call$7(nativeSplit, string, separator, lim);
6149               }
6150               var output = [];
6151               var flags = (separator.ignoreCase ? 'i' : '') +
6152                           (separator.multiline ? 'm' : '') +
6153                           (separator.unicode ? 'u' : '') +
6154                           (separator.sticky ? 'y' : '');
6155               var lastLastIndex = 0;
6156               // Make `global` and avoid `lastIndex` issues by working with a copy
6157               var separatorCopy = new RegExp(separator.source, flags + 'g');
6158               var match, lastIndex, lastLength;
6159               while (match = call$7(regexpExec, separatorCopy, string)) {
6160                 lastIndex = separatorCopy.lastIndex;
6161                 if (lastIndex > lastLastIndex) {
6162                   push$5(output, stringSlice$5(string, lastLastIndex, match.index));
6163                   if (match.length > 1 && match.index < string.length) apply$2($push, output, arraySlice$4(match, 1));
6164                   lastLength = match[0].length;
6165                   lastLastIndex = lastIndex;
6166                   if (output.length >= lim) break;
6167                 }
6168                 if (separatorCopy.lastIndex === match.index) separatorCopy.lastIndex++; // Avoid an infinite loop
6169               }
6170               if (lastLastIndex === string.length) {
6171                 if (lastLength || !exec$4(separatorCopy, '')) push$5(output, '');
6172               } else push$5(output, stringSlice$5(string, lastLastIndex));
6173               return output.length > lim ? arraySlice$4(output, 0, lim) : output;
6174             };
6175           // Chakra, V8
6176           } else if ('0'.split(undefined, 0).length) {
6177             internalSplit = function (separator, limit) {
6178               return separator === undefined && limit === 0 ? [] : call$7(nativeSplit, this, separator, limit);
6179             };
6180           } else internalSplit = nativeSplit;
6181
6182           return [
6183             // `String.prototype.split` method
6184             // https://tc39.es/ecma262/#sec-string.prototype.split
6185             function split(separator, limit) {
6186               var O = requireObjectCoercible$9(this);
6187               var splitter = separator == undefined ? undefined : getMethod$2(separator, SPLIT);
6188               return splitter
6189                 ? call$7(splitter, separator, O, limit)
6190                 : call$7(internalSplit, toString$e(O), separator, limit);
6191             },
6192             // `RegExp.prototype[@@split]` method
6193             // https://tc39.es/ecma262/#sec-regexp.prototype-@@split
6194             //
6195             // NOTE: This cannot be properly polyfilled in engines that don't support
6196             // the 'y' flag.
6197             function (string, limit) {
6198               var rx = anObject$5(this);
6199               var S = toString$e(string);
6200               var res = maybeCallNative(internalSplit, rx, S, limit, internalSplit !== nativeSplit);
6201
6202               if (res.done) return res.value;
6203
6204               var C = speciesConstructor$1(rx, RegExp);
6205
6206               var unicodeMatching = rx.unicode;
6207               var flags = (rx.ignoreCase ? 'i' : '') +
6208                           (rx.multiline ? 'm' : '') +
6209                           (rx.unicode ? 'u' : '') +
6210                           (UNSUPPORTED_Y$1 ? 'g' : 'y');
6211
6212               // ^(? + rx + ) is needed, in combination with some S slicing, to
6213               // simulate the 'y' flag.
6214               var splitter = new C(UNSUPPORTED_Y$1 ? '^(?:' + rx.source + ')' : rx, flags);
6215               var lim = limit === undefined ? MAX_UINT32 : limit >>> 0;
6216               if (lim === 0) return [];
6217               if (S.length === 0) return callRegExpExec(splitter, S) === null ? [S] : [];
6218               var p = 0;
6219               var q = 0;
6220               var A = [];
6221               while (q < S.length) {
6222                 splitter.lastIndex = UNSUPPORTED_Y$1 ? 0 : q;
6223                 var z = callRegExpExec(splitter, UNSUPPORTED_Y$1 ? stringSlice$5(S, q) : S);
6224                 var e;
6225                 if (
6226                   z === null ||
6227                   (e = min$4(toLength$4(splitter.lastIndex + (UNSUPPORTED_Y$1 ? q : 0)), S.length)) === p
6228                 ) {
6229                   q = advanceStringIndex$1(S, q, unicodeMatching);
6230                 } else {
6231                   push$5(A, stringSlice$5(S, p, q));
6232                   if (A.length === lim) return A;
6233                   for (var i = 1; i <= z.length - 1; i++) {
6234                     push$5(A, z[i]);
6235                     if (A.length === lim) return A;
6236                   }
6237                   q = p = e;
6238                 }
6239               }
6240               push$5(A, stringSlice$5(S, p));
6241               return A;
6242             }
6243           ];
6244         }, !SPLIT_WORKS_WITH_OVERWRITTEN_EXEC, UNSUPPORTED_Y$1);
6245
6246         // a string of all valid unicode whitespaces
6247         var whitespaces$4 = '\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u2000\u2001\u2002' +
6248           '\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF';
6249
6250         var uncurryThis$o = functionUncurryThis;
6251         var requireObjectCoercible$8 = requireObjectCoercible$e;
6252         var toString$d = toString$k;
6253         var whitespaces$3 = whitespaces$4;
6254
6255         var replace$4 = uncurryThis$o(''.replace);
6256         var whitespace = '[' + whitespaces$3 + ']';
6257         var ltrim = RegExp('^' + whitespace + whitespace + '*');
6258         var rtrim$2 = RegExp(whitespace + whitespace + '*$');
6259
6260         // `String.prototype.{ trim, trimStart, trimEnd, trimLeft, trimRight }` methods implementation
6261         var createMethod$2 = function (TYPE) {
6262           return function ($this) {
6263             var string = toString$d(requireObjectCoercible$8($this));
6264             if (TYPE & 1) string = replace$4(string, ltrim, '');
6265             if (TYPE & 2) string = replace$4(string, rtrim$2, '');
6266             return string;
6267           };
6268         };
6269
6270         var stringTrim = {
6271           // `String.prototype.{ trimLeft, trimStart }` methods
6272           // https://tc39.es/ecma262/#sec-string.prototype.trimstart
6273           start: createMethod$2(1),
6274           // `String.prototype.{ trimRight, trimEnd }` methods
6275           // https://tc39.es/ecma262/#sec-string.prototype.trimend
6276           end: createMethod$2(2),
6277           // `String.prototype.trim` method
6278           // https://tc39.es/ecma262/#sec-string.prototype.trim
6279           trim: createMethod$2(3)
6280         };
6281
6282         var PROPER_FUNCTION_NAME = functionName.PROPER;
6283         var fails$o = fails$S;
6284         var whitespaces$2 = whitespaces$4;
6285
6286         var non = '\u200B\u0085\u180E';
6287
6288         // check that a method works with the correct list
6289         // of whitespaces and has a correct name
6290         var stringTrimForced = function (METHOD_NAME) {
6291           return fails$o(function () {
6292             return !!whitespaces$2[METHOD_NAME]()
6293               || non[METHOD_NAME]() !== non
6294               || (PROPER_FUNCTION_NAME && whitespaces$2[METHOD_NAME].name !== METHOD_NAME);
6295           });
6296         };
6297
6298         var $$W = _export;
6299         var $trim = stringTrim.trim;
6300         var forcedStringTrimMethod$2 = stringTrimForced;
6301
6302         // `String.prototype.trim` method
6303         // https://tc39.es/ecma262/#sec-string.prototype.trim
6304         $$W({ target: 'String', proto: true, forced: forcedStringTrimMethod$2('trim') }, {
6305           trim: function trim() {
6306             return $trim(this);
6307           }
6308         });
6309
6310         var DESCRIPTORS$b = descriptors;
6311         var FUNCTION_NAME_EXISTS = functionName.EXISTS;
6312         var uncurryThis$n = functionUncurryThis;
6313         var defineProperty$5 = objectDefineProperty.f;
6314
6315         var FunctionPrototype = Function.prototype;
6316         var functionToString = uncurryThis$n(FunctionPrototype.toString);
6317         var nameRE = /^\s*function ([^ (]*)/;
6318         var regExpExec$2 = uncurryThis$n(nameRE.exec);
6319         var NAME = 'name';
6320
6321         // Function instances `.name` property
6322         // https://tc39.es/ecma262/#sec-function-instances-name
6323         if (DESCRIPTORS$b && !FUNCTION_NAME_EXISTS) {
6324           defineProperty$5(FunctionPrototype, NAME, {
6325             configurable: true,
6326             get: function () {
6327               try {
6328                 return regExpExec$2(nameRE, functionToString(this))[1];
6329               } catch (error) {
6330                 return '';
6331               }
6332             }
6333           });
6334         }
6335
6336         var $$V = _export;
6337         var DESCRIPTORS$a = descriptors;
6338         var create$5 = objectCreate;
6339
6340         // `Object.create` method
6341         // https://tc39.es/ecma262/#sec-object.create
6342         $$V({ target: 'Object', stat: true, sham: !DESCRIPTORS$a }, {
6343           create: create$5
6344         });
6345
6346         var $$U = _export;
6347         var global$l = global$1m;
6348         var apply$1 = functionApply;
6349         var isCallable$2 = isCallable$r;
6350         var userAgent$1 = engineUserAgent;
6351         var arraySlice$3 = arraySlice$c;
6352
6353         var MSIE = /MSIE .\./.test(userAgent$1); // <- dirty ie9- check
6354         var Function$2 = global$l.Function;
6355
6356         var wrap$1 = function (scheduler) {
6357           return function (handler, timeout /* , ...arguments */) {
6358             var boundArgs = arguments.length > 2;
6359             var args = boundArgs ? arraySlice$3(arguments, 2) : undefined;
6360             return scheduler(boundArgs ? function () {
6361               apply$1(isCallable$2(handler) ? handler : Function$2(handler), this, args);
6362             } : handler, timeout);
6363           };
6364         };
6365
6366         // ie9- setTimeout & setInterval additional parameters fix
6367         // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers
6368         $$U({ global: true, bind: true, forced: MSIE }, {
6369           // `setTimeout` method
6370           // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-settimeout
6371           setTimeout: wrap$1(global$l.setTimeout),
6372           // `setInterval` method
6373           // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-setinterval
6374           setInterval: wrap$1(global$l.setInterval)
6375         });
6376
6377         var global$k = typeof globalThis !== 'undefined' && globalThis || typeof self !== 'undefined' && self || typeof global$k !== 'undefined' && global$k;
6378         var support = {
6379           searchParams: 'URLSearchParams' in global$k,
6380           iterable: 'Symbol' in global$k && 'iterator' in Symbol,
6381           blob: 'FileReader' in global$k && 'Blob' in global$k && function () {
6382             try {
6383               new Blob();
6384               return true;
6385             } catch (e) {
6386               return false;
6387             }
6388           }(),
6389           formData: 'FormData' in global$k,
6390           arrayBuffer: 'ArrayBuffer' in global$k
6391         };
6392
6393         function isDataView(obj) {
6394           return obj && DataView.prototype.isPrototypeOf(obj);
6395         }
6396
6397         if (support.arrayBuffer) {
6398           var viewClasses = ['[object Int8Array]', '[object Uint8Array]', '[object Uint8ClampedArray]', '[object Int16Array]', '[object Uint16Array]', '[object Int32Array]', '[object Uint32Array]', '[object Float32Array]', '[object Float64Array]'];
6399
6400           var isArrayBufferView = ArrayBuffer.isView || function (obj) {
6401             return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1;
6402           };
6403         }
6404
6405         function normalizeName(name) {
6406           if (typeof name !== 'string') {
6407             name = String(name);
6408           }
6409
6410           if (/[^a-z0-9\-#$%&'*+.^_`|~!]/i.test(name) || name === '') {
6411             throw new TypeError('Invalid character in header field name: "' + name + '"');
6412           }
6413
6414           return name.toLowerCase();
6415         }
6416
6417         function normalizeValue(value) {
6418           if (typeof value !== 'string') {
6419             value = String(value);
6420           }
6421
6422           return value;
6423         } // Build a destructive iterator for the value list
6424
6425
6426         function iteratorFor(items) {
6427           var iterator = {
6428             next: function next() {
6429               var value = items.shift();
6430               return {
6431                 done: value === undefined,
6432                 value: value
6433               };
6434             }
6435           };
6436
6437           if (support.iterable) {
6438             iterator[Symbol.iterator] = function () {
6439               return iterator;
6440             };
6441           }
6442
6443           return iterator;
6444         }
6445
6446         function Headers(headers) {
6447           this.map = {};
6448
6449           if (headers instanceof Headers) {
6450             headers.forEach(function (value, name) {
6451               this.append(name, value);
6452             }, this);
6453           } else if (Array.isArray(headers)) {
6454             headers.forEach(function (header) {
6455               this.append(header[0], header[1]);
6456             }, this);
6457           } else if (headers) {
6458             Object.getOwnPropertyNames(headers).forEach(function (name) {
6459               this.append(name, headers[name]);
6460             }, this);
6461           }
6462         }
6463
6464         Headers.prototype.append = function (name, value) {
6465           name = normalizeName(name);
6466           value = normalizeValue(value);
6467           var oldValue = this.map[name];
6468           this.map[name] = oldValue ? oldValue + ', ' + value : value;
6469         };
6470
6471         Headers.prototype['delete'] = function (name) {
6472           delete this.map[normalizeName(name)];
6473         };
6474
6475         Headers.prototype.get = function (name) {
6476           name = normalizeName(name);
6477           return this.has(name) ? this.map[name] : null;
6478         };
6479
6480         Headers.prototype.has = function (name) {
6481           return this.map.hasOwnProperty(normalizeName(name));
6482         };
6483
6484         Headers.prototype.set = function (name, value) {
6485           this.map[normalizeName(name)] = normalizeValue(value);
6486         };
6487
6488         Headers.prototype.forEach = function (callback, thisArg) {
6489           for (var name in this.map) {
6490             if (this.map.hasOwnProperty(name)) {
6491               callback.call(thisArg, this.map[name], name, this);
6492             }
6493           }
6494         };
6495
6496         Headers.prototype.keys = function () {
6497           var items = [];
6498           this.forEach(function (value, name) {
6499             items.push(name);
6500           });
6501           return iteratorFor(items);
6502         };
6503
6504         Headers.prototype.values = function () {
6505           var items = [];
6506           this.forEach(function (value) {
6507             items.push(value);
6508           });
6509           return iteratorFor(items);
6510         };
6511
6512         Headers.prototype.entries = function () {
6513           var items = [];
6514           this.forEach(function (value, name) {
6515             items.push([name, value]);
6516           });
6517           return iteratorFor(items);
6518         };
6519
6520         if (support.iterable) {
6521           Headers.prototype[Symbol.iterator] = Headers.prototype.entries;
6522         }
6523
6524         function consumed(body) {
6525           if (body.bodyUsed) {
6526             return Promise.reject(new TypeError('Already read'));
6527           }
6528
6529           body.bodyUsed = true;
6530         }
6531
6532         function fileReaderReady(reader) {
6533           return new Promise(function (resolve, reject) {
6534             reader.onload = function () {
6535               resolve(reader.result);
6536             };
6537
6538             reader.onerror = function () {
6539               reject(reader.error);
6540             };
6541           });
6542         }
6543
6544         function readBlobAsArrayBuffer(blob) {
6545           var reader = new FileReader();
6546           var promise = fileReaderReady(reader);
6547           reader.readAsArrayBuffer(blob);
6548           return promise;
6549         }
6550
6551         function readBlobAsText(blob) {
6552           var reader = new FileReader();
6553           var promise = fileReaderReady(reader);
6554           reader.readAsText(blob);
6555           return promise;
6556         }
6557
6558         function readArrayBufferAsText(buf) {
6559           var view = new Uint8Array(buf);
6560           var chars = new Array(view.length);
6561
6562           for (var i = 0; i < view.length; i++) {
6563             chars[i] = String.fromCharCode(view[i]);
6564           }
6565
6566           return chars.join('');
6567         }
6568
6569         function bufferClone(buf) {
6570           if (buf.slice) {
6571             return buf.slice(0);
6572           } else {
6573             var view = new Uint8Array(buf.byteLength);
6574             view.set(new Uint8Array(buf));
6575             return view.buffer;
6576           }
6577         }
6578
6579         function Body() {
6580           this.bodyUsed = false;
6581
6582           this._initBody = function (body) {
6583             /*
6584               fetch-mock wraps the Response object in an ES6 Proxy to
6585               provide useful test harness features such as flush. However, on
6586               ES5 browsers without fetch or Proxy support pollyfills must be used;
6587               the proxy-pollyfill is unable to proxy an attribute unless it exists
6588               on the object before the Proxy is created. This change ensures
6589               Response.bodyUsed exists on the instance, while maintaining the
6590               semantic of setting Request.bodyUsed in the constructor before
6591               _initBody is called.
6592             */
6593             this.bodyUsed = this.bodyUsed;
6594             this._bodyInit = body;
6595
6596             if (!body) {
6597               this._bodyText = '';
6598             } else if (typeof body === 'string') {
6599               this._bodyText = body;
6600             } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
6601               this._bodyBlob = body;
6602             } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
6603               this._bodyFormData = body;
6604             } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
6605               this._bodyText = body.toString();
6606             } else if (support.arrayBuffer && support.blob && isDataView(body)) {
6607               this._bodyArrayBuffer = bufferClone(body.buffer); // IE 10-11 can't handle a DataView body.
6608
6609               this._bodyInit = new Blob([this._bodyArrayBuffer]);
6610             } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {
6611               this._bodyArrayBuffer = bufferClone(body);
6612             } else {
6613               this._bodyText = body = Object.prototype.toString.call(body);
6614             }
6615
6616             if (!this.headers.get('content-type')) {
6617               if (typeof body === 'string') {
6618                 this.headers.set('content-type', 'text/plain;charset=UTF-8');
6619               } else if (this._bodyBlob && this._bodyBlob.type) {
6620                 this.headers.set('content-type', this._bodyBlob.type);
6621               } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
6622                 this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8');
6623               }
6624             }
6625           };
6626
6627           if (support.blob) {
6628             this.blob = function () {
6629               var rejected = consumed(this);
6630
6631               if (rejected) {
6632                 return rejected;
6633               }
6634
6635               if (this._bodyBlob) {
6636                 return Promise.resolve(this._bodyBlob);
6637               } else if (this._bodyArrayBuffer) {
6638                 return Promise.resolve(new Blob([this._bodyArrayBuffer]));
6639               } else if (this._bodyFormData) {
6640                 throw new Error('could not read FormData body as blob');
6641               } else {
6642                 return Promise.resolve(new Blob([this._bodyText]));
6643               }
6644             };
6645
6646             this.arrayBuffer = function () {
6647               if (this._bodyArrayBuffer) {
6648                 var isConsumed = consumed(this);
6649
6650                 if (isConsumed) {
6651                   return isConsumed;
6652                 }
6653
6654                 if (ArrayBuffer.isView(this._bodyArrayBuffer)) {
6655                   return Promise.resolve(this._bodyArrayBuffer.buffer.slice(this._bodyArrayBuffer.byteOffset, this._bodyArrayBuffer.byteOffset + this._bodyArrayBuffer.byteLength));
6656                 } else {
6657                   return Promise.resolve(this._bodyArrayBuffer);
6658                 }
6659               } else {
6660                 return this.blob().then(readBlobAsArrayBuffer);
6661               }
6662             };
6663           }
6664
6665           this.text = function () {
6666             var rejected = consumed(this);
6667
6668             if (rejected) {
6669               return rejected;
6670             }
6671
6672             if (this._bodyBlob) {
6673               return readBlobAsText(this._bodyBlob);
6674             } else if (this._bodyArrayBuffer) {
6675               return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer));
6676             } else if (this._bodyFormData) {
6677               throw new Error('could not read FormData body as text');
6678             } else {
6679               return Promise.resolve(this._bodyText);
6680             }
6681           };
6682
6683           if (support.formData) {
6684             this.formData = function () {
6685               return this.text().then(decode);
6686             };
6687           }
6688
6689           this.json = function () {
6690             return this.text().then(JSON.parse);
6691           };
6692
6693           return this;
6694         } // HTTP methods whose capitalization should be normalized
6695
6696
6697         var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT'];
6698
6699         function normalizeMethod(method) {
6700           var upcased = method.toUpperCase();
6701           return methods.indexOf(upcased) > -1 ? upcased : method;
6702         }
6703
6704         function Request(input, options) {
6705           if (!(this instanceof Request)) {
6706             throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.');
6707           }
6708
6709           options = options || {};
6710           var body = options.body;
6711
6712           if (input instanceof Request) {
6713             if (input.bodyUsed) {
6714               throw new TypeError('Already read');
6715             }
6716
6717             this.url = input.url;
6718             this.credentials = input.credentials;
6719
6720             if (!options.headers) {
6721               this.headers = new Headers(input.headers);
6722             }
6723
6724             this.method = input.method;
6725             this.mode = input.mode;
6726             this.signal = input.signal;
6727
6728             if (!body && input._bodyInit != null) {
6729               body = input._bodyInit;
6730               input.bodyUsed = true;
6731             }
6732           } else {
6733             this.url = String(input);
6734           }
6735
6736           this.credentials = options.credentials || this.credentials || 'same-origin';
6737
6738           if (options.headers || !this.headers) {
6739             this.headers = new Headers(options.headers);
6740           }
6741
6742           this.method = normalizeMethod(options.method || this.method || 'GET');
6743           this.mode = options.mode || this.mode || null;
6744           this.signal = options.signal || this.signal;
6745           this.referrer = null;
6746
6747           if ((this.method === 'GET' || this.method === 'HEAD') && body) {
6748             throw new TypeError('Body not allowed for GET or HEAD requests');
6749           }
6750
6751           this._initBody(body);
6752
6753           if (this.method === 'GET' || this.method === 'HEAD') {
6754             if (options.cache === 'no-store' || options.cache === 'no-cache') {
6755               // Search for a '_' parameter in the query string
6756               var reParamSearch = /([?&])_=[^&]*/;
6757
6758               if (reParamSearch.test(this.url)) {
6759                 // If it already exists then set the value with the current time
6760                 this.url = this.url.replace(reParamSearch, '$1_=' + new Date().getTime());
6761               } else {
6762                 // Otherwise add a new '_' parameter to the end with the current time
6763                 var reQueryString = /\?/;
6764                 this.url += (reQueryString.test(this.url) ? '&' : '?') + '_=' + new Date().getTime();
6765               }
6766             }
6767           }
6768         }
6769
6770         Request.prototype.clone = function () {
6771           return new Request(this, {
6772             body: this._bodyInit
6773           });
6774         };
6775
6776         function decode(body) {
6777           var form = new FormData();
6778           body.trim().split('&').forEach(function (bytes) {
6779             if (bytes) {
6780               var split = bytes.split('=');
6781               var name = split.shift().replace(/\+/g, ' ');
6782               var value = split.join('=').replace(/\+/g, ' ');
6783               form.append(decodeURIComponent(name), decodeURIComponent(value));
6784             }
6785           });
6786           return form;
6787         }
6788
6789         function parseHeaders(rawHeaders) {
6790           var headers = new Headers(); // Replace instances of \r\n and \n followed by at least one space or horizontal tab with a space
6791           // https://tools.ietf.org/html/rfc7230#section-3.2
6792
6793           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
6794           // https://github.com/github/fetch/issues/748
6795           // https://github.com/zloirock/core-js/issues/751
6796
6797           preProcessedHeaders.split('\r').map(function (header) {
6798             return header.indexOf('\n') === 0 ? header.substr(1, header.length) : header;
6799           }).forEach(function (line) {
6800             var parts = line.split(':');
6801             var key = parts.shift().trim();
6802
6803             if (key) {
6804               var value = parts.join(':').trim();
6805               headers.append(key, value);
6806             }
6807           });
6808           return headers;
6809         }
6810
6811         Body.call(Request.prototype);
6812         function Response(bodyInit, options) {
6813           if (!(this instanceof Response)) {
6814             throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.');
6815           }
6816
6817           if (!options) {
6818             options = {};
6819           }
6820
6821           this.type = 'default';
6822           this.status = options.status === undefined ? 200 : options.status;
6823           this.ok = this.status >= 200 && this.status < 300;
6824           this.statusText = options.statusText === undefined ? '' : '' + options.statusText;
6825           this.headers = new Headers(options.headers);
6826           this.url = options.url || '';
6827
6828           this._initBody(bodyInit);
6829         }
6830         Body.call(Response.prototype);
6831
6832         Response.prototype.clone = function () {
6833           return new Response(this._bodyInit, {
6834             status: this.status,
6835             statusText: this.statusText,
6836             headers: new Headers(this.headers),
6837             url: this.url
6838           });
6839         };
6840
6841         Response.error = function () {
6842           var response = new Response(null, {
6843             status: 0,
6844             statusText: ''
6845           });
6846           response.type = 'error';
6847           return response;
6848         };
6849
6850         var redirectStatuses = [301, 302, 303, 307, 308];
6851
6852         Response.redirect = function (url, status) {
6853           if (redirectStatuses.indexOf(status) === -1) {
6854             throw new RangeError('Invalid status code');
6855           }
6856
6857           return new Response(null, {
6858             status: status,
6859             headers: {
6860               location: url
6861             }
6862           });
6863         };
6864
6865         var DOMException$1 = global$k.DOMException;
6866
6867         try {
6868           new DOMException$1();
6869         } catch (err) {
6870           DOMException$1 = function DOMException(message, name) {
6871             this.message = message;
6872             this.name = name;
6873             var error = Error(message);
6874             this.stack = error.stack;
6875           };
6876
6877           DOMException$1.prototype = Object.create(Error.prototype);
6878           DOMException$1.prototype.constructor = DOMException$1;
6879         }
6880
6881         function fetch$1(input, init) {
6882           return new Promise(function (resolve, reject) {
6883             var request = new Request(input, init);
6884
6885             if (request.signal && request.signal.aborted) {
6886               return reject(new DOMException$1('Aborted', 'AbortError'));
6887             }
6888
6889             var xhr = new XMLHttpRequest();
6890
6891             function abortXhr() {
6892               xhr.abort();
6893             }
6894
6895             xhr.onload = function () {
6896               var options = {
6897                 status: xhr.status,
6898                 statusText: xhr.statusText,
6899                 headers: parseHeaders(xhr.getAllResponseHeaders() || '')
6900               };
6901               options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL');
6902               var body = 'response' in xhr ? xhr.response : xhr.responseText;
6903               setTimeout(function () {
6904                 resolve(new Response(body, options));
6905               }, 0);
6906             };
6907
6908             xhr.onerror = function () {
6909               setTimeout(function () {
6910                 reject(new TypeError('Network request failed'));
6911               }, 0);
6912             };
6913
6914             xhr.ontimeout = function () {
6915               setTimeout(function () {
6916                 reject(new TypeError('Network request failed'));
6917               }, 0);
6918             };
6919
6920             xhr.onabort = function () {
6921               setTimeout(function () {
6922                 reject(new DOMException$1('Aborted', 'AbortError'));
6923               }, 0);
6924             };
6925
6926             function fixUrl(url) {
6927               try {
6928                 return url === '' && global$k.location.href ? global$k.location.href : url;
6929               } catch (e) {
6930                 return url;
6931               }
6932             }
6933
6934             xhr.open(request.method, fixUrl(request.url), true);
6935
6936             if (request.credentials === 'include') {
6937               xhr.withCredentials = true;
6938             } else if (request.credentials === 'omit') {
6939               xhr.withCredentials = false;
6940             }
6941
6942             if ('responseType' in xhr) {
6943               if (support.blob) {
6944                 xhr.responseType = 'blob';
6945               } else if (support.arrayBuffer && request.headers.get('Content-Type') && request.headers.get('Content-Type').indexOf('application/octet-stream') !== -1) {
6946                 xhr.responseType = 'arraybuffer';
6947               }
6948             }
6949
6950             if (init && _typeof(init.headers) === 'object' && !(init.headers instanceof Headers)) {
6951               Object.getOwnPropertyNames(init.headers).forEach(function (name) {
6952                 xhr.setRequestHeader(name, normalizeValue(init.headers[name]));
6953               });
6954             } else {
6955               request.headers.forEach(function (value, name) {
6956                 xhr.setRequestHeader(name, value);
6957               });
6958             }
6959
6960             if (request.signal) {
6961               request.signal.addEventListener('abort', abortXhr);
6962
6963               xhr.onreadystatechange = function () {
6964                 // DONE (success or failure)
6965                 if (xhr.readyState === 4) {
6966                   request.signal.removeEventListener('abort', abortXhr);
6967                 }
6968               };
6969             }
6970
6971             xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit);
6972           });
6973         }
6974         fetch$1.polyfill = true;
6975
6976         if (!global$k.fetch) {
6977           global$k.fetch = fetch$1;
6978           global$k.Headers = Headers;
6979           global$k.Request = Request;
6980           global$k.Response = Response;
6981         }
6982
6983         var $$T = _export;
6984         var DESCRIPTORS$9 = descriptors;
6985         var objectDefinePropertyModile = objectDefineProperty;
6986
6987         // `Object.defineProperty` method
6988         // https://tc39.es/ecma262/#sec-object.defineproperty
6989         $$T({ target: 'Object', stat: true, forced: !DESCRIPTORS$9, sham: !DESCRIPTORS$9 }, {
6990           defineProperty: objectDefinePropertyModile.f
6991         });
6992
6993         var $$S = _export;
6994         var setPrototypeOf = objectSetPrototypeOf;
6995
6996         // `Object.setPrototypeOf` method
6997         // https://tc39.es/ecma262/#sec-object.setprototypeof
6998         $$S({ target: 'Object', stat: true }, {
6999           setPrototypeOf: setPrototypeOf
7000         });
7001
7002         var $$R = _export;
7003         var fails$n = fails$S;
7004         var toObject$8 = toObject$j;
7005         var nativeGetPrototypeOf = objectGetPrototypeOf;
7006         var CORRECT_PROTOTYPE_GETTER = correctPrototypeGetter;
7007
7008         var FAILS_ON_PRIMITIVES$4 = fails$n(function () { nativeGetPrototypeOf(1); });
7009
7010         // `Object.getPrototypeOf` method
7011         // https://tc39.es/ecma262/#sec-object.getprototypeof
7012         $$R({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES$4, sham: !CORRECT_PROTOTYPE_GETTER }, {
7013           getPrototypeOf: function getPrototypeOf(it) {
7014             return nativeGetPrototypeOf(toObject$8(it));
7015           }
7016         });
7017
7018         var global$j = global$1m;
7019         var uncurryThis$m = functionUncurryThis;
7020         var aCallable$2 = aCallable$a;
7021         var isObject$b = isObject$s;
7022         var hasOwn$5 = hasOwnProperty_1;
7023         var arraySlice$2 = arraySlice$c;
7024
7025         var Function$1 = global$j.Function;
7026         var concat$1 = uncurryThis$m([].concat);
7027         var join$3 = uncurryThis$m([].join);
7028         var factories = {};
7029
7030         var construct = function (C, argsLength, args) {
7031           if (!hasOwn$5(factories, argsLength)) {
7032             for (var list = [], i = 0; i < argsLength; i++) list[i] = 'a[' + i + ']';
7033             factories[argsLength] = Function$1('C,a', 'return new C(' + join$3(list, ',') + ')');
7034           } return factories[argsLength](C, args);
7035         };
7036
7037         // `Function.prototype.bind` method implementation
7038         // https://tc39.es/ecma262/#sec-function.prototype.bind
7039         var functionBind = Function$1.bind || function bind(that /* , ...args */) {
7040           var F = aCallable$2(this);
7041           var Prototype = F.prototype;
7042           var partArgs = arraySlice$2(arguments, 1);
7043           var boundFunction = function bound(/* args... */) {
7044             var args = concat$1(partArgs, arraySlice$2(arguments));
7045             return this instanceof boundFunction ? construct(F, args.length, args) : F.apply(that, args);
7046           };
7047           if (isObject$b(Prototype)) boundFunction.prototype = Prototype;
7048           return boundFunction;
7049         };
7050
7051         var $$Q = _export;
7052         var getBuiltIn$1 = getBuiltIn$b;
7053         var apply = functionApply;
7054         var bind$7 = functionBind;
7055         var aConstructor = aConstructor$3;
7056         var anObject$4 = anObject$n;
7057         var isObject$a = isObject$s;
7058         var create$4 = objectCreate;
7059         var fails$m = fails$S;
7060
7061         var nativeConstruct = getBuiltIn$1('Reflect', 'construct');
7062         var ObjectPrototype = Object.prototype;
7063         var push$4 = [].push;
7064
7065         // `Reflect.construct` method
7066         // https://tc39.es/ecma262/#sec-reflect.construct
7067         // MS Edge supports only 2 arguments and argumentsList argument is optional
7068         // FF Nightly sets third argument as `new.target`, but does not create `this` from it
7069         var NEW_TARGET_BUG = fails$m(function () {
7070           function F() { /* empty */ }
7071           return !(nativeConstruct(function () { /* empty */ }, [], F) instanceof F);
7072         });
7073
7074         var ARGS_BUG = !fails$m(function () {
7075           nativeConstruct(function () { /* empty */ });
7076         });
7077
7078         var FORCED$c = NEW_TARGET_BUG || ARGS_BUG;
7079
7080         $$Q({ target: 'Reflect', stat: true, forced: FORCED$c, sham: FORCED$c }, {
7081           construct: function construct(Target, args /* , newTarget */) {
7082             aConstructor(Target);
7083             anObject$4(args);
7084             var newTarget = arguments.length < 3 ? Target : aConstructor(arguments[2]);
7085             if (ARGS_BUG && !NEW_TARGET_BUG) return nativeConstruct(Target, args, newTarget);
7086             if (Target == newTarget) {
7087               // w/o altered newTarget, optimization for 0-4 arguments
7088               switch (args.length) {
7089                 case 0: return new Target();
7090                 case 1: return new Target(args[0]);
7091                 case 2: return new Target(args[0], args[1]);
7092                 case 3: return new Target(args[0], args[1], args[2]);
7093                 case 4: return new Target(args[0], args[1], args[2], args[3]);
7094               }
7095               // w/o altered newTarget, lot of arguments case
7096               var $args = [null];
7097               apply(push$4, $args, args);
7098               return new (apply(bind$7, Target, $args))();
7099             }
7100             // with altered newTarget, not support built-in constructors
7101             var proto = newTarget.prototype;
7102             var instance = create$4(isObject$a(proto) ? proto : ObjectPrototype);
7103             var result = apply(Target, instance, args);
7104             return isObject$a(result) ? result : instance;
7105           }
7106         });
7107
7108         var hasOwn$4 = hasOwnProperty_1;
7109
7110         var isDataDescriptor$1 = function (descriptor) {
7111           return descriptor !== undefined && (hasOwn$4(descriptor, 'value') || hasOwn$4(descriptor, 'writable'));
7112         };
7113
7114         var $$P = _export;
7115         var call$6 = functionCall;
7116         var isObject$9 = isObject$s;
7117         var anObject$3 = anObject$n;
7118         var isDataDescriptor = isDataDescriptor$1;
7119         var getOwnPropertyDescriptorModule = objectGetOwnPropertyDescriptor;
7120         var getPrototypeOf = objectGetPrototypeOf;
7121
7122         // `Reflect.get` method
7123         // https://tc39.es/ecma262/#sec-reflect.get
7124         function get$3(target, propertyKey /* , receiver */) {
7125           var receiver = arguments.length < 3 ? target : arguments[2];
7126           var descriptor, prototype;
7127           if (anObject$3(target) === receiver) return target[propertyKey];
7128           descriptor = getOwnPropertyDescriptorModule.f(target, propertyKey);
7129           if (descriptor) return isDataDescriptor(descriptor)
7130             ? descriptor.value
7131             : descriptor.get === undefined ? undefined : call$6(descriptor.get, receiver);
7132           if (isObject$9(prototype = getPrototypeOf(target))) return get$3(prototype, propertyKey, receiver);
7133         }
7134
7135         $$P({ target: 'Reflect', stat: true }, {
7136           get: get$3
7137         });
7138
7139         var $$O = _export;
7140         var fails$l = fails$S;
7141         var toIndexedObject$1 = toIndexedObject$c;
7142         var nativeGetOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f;
7143         var DESCRIPTORS$8 = descriptors;
7144
7145         var FAILS_ON_PRIMITIVES$3 = fails$l(function () { nativeGetOwnPropertyDescriptor(1); });
7146         var FORCED$b = !DESCRIPTORS$8 || FAILS_ON_PRIMITIVES$3;
7147
7148         // `Object.getOwnPropertyDescriptor` method
7149         // https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
7150         $$O({ target: 'Object', stat: true, forced: FORCED$b, sham: !DESCRIPTORS$8 }, {
7151           getOwnPropertyDescriptor: function getOwnPropertyDescriptor(it, key) {
7152             return nativeGetOwnPropertyDescriptor(toIndexedObject$1(it), key);
7153           }
7154         });
7155
7156         var $$N = _export;
7157         var global$i = global$1m;
7158         var toAbsoluteIndex$1 = toAbsoluteIndex$8;
7159         var toIntegerOrInfinity$2 = toIntegerOrInfinity$b;
7160         var lengthOfArrayLike$5 = lengthOfArrayLike$g;
7161         var toObject$7 = toObject$j;
7162         var arraySpeciesCreate$2 = arraySpeciesCreate$4;
7163         var createProperty$2 = createProperty$4;
7164         var arrayMethodHasSpeciesSupport$2 = arrayMethodHasSpeciesSupport$5;
7165
7166         var HAS_SPECIES_SUPPORT$1 = arrayMethodHasSpeciesSupport$2('splice');
7167
7168         var TypeError$6 = global$i.TypeError;
7169         var max$1 = Math.max;
7170         var min$3 = Math.min;
7171         var MAX_SAFE_INTEGER$1 = 0x1FFFFFFFFFFFFF;
7172         var MAXIMUM_ALLOWED_LENGTH_EXCEEDED = 'Maximum allowed length exceeded';
7173
7174         // `Array.prototype.splice` method
7175         // https://tc39.es/ecma262/#sec-array.prototype.splice
7176         // with adding support of @@species
7177         $$N({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$1 }, {
7178           splice: function splice(start, deleteCount /* , ...items */) {
7179             var O = toObject$7(this);
7180             var len = lengthOfArrayLike$5(O);
7181             var actualStart = toAbsoluteIndex$1(start, len);
7182             var argumentsLength = arguments.length;
7183             var insertCount, actualDeleteCount, A, k, from, to;
7184             if (argumentsLength === 0) {
7185               insertCount = actualDeleteCount = 0;
7186             } else if (argumentsLength === 1) {
7187               insertCount = 0;
7188               actualDeleteCount = len - actualStart;
7189             } else {
7190               insertCount = argumentsLength - 2;
7191               actualDeleteCount = min$3(max$1(toIntegerOrInfinity$2(deleteCount), 0), len - actualStart);
7192             }
7193             if (len + insertCount - actualDeleteCount > MAX_SAFE_INTEGER$1) {
7194               throw TypeError$6(MAXIMUM_ALLOWED_LENGTH_EXCEEDED);
7195             }
7196             A = arraySpeciesCreate$2(O, actualDeleteCount);
7197             for (k = 0; k < actualDeleteCount; k++) {
7198               from = actualStart + k;
7199               if (from in O) createProperty$2(A, k, O[from]);
7200             }
7201             A.length = actualDeleteCount;
7202             if (insertCount < actualDeleteCount) {
7203               for (k = actualStart; k < len - actualDeleteCount; k++) {
7204                 from = k + actualDeleteCount;
7205                 to = k + insertCount;
7206                 if (from in O) O[to] = O[from];
7207                 else delete O[to];
7208               }
7209               for (k = len; k > len - actualDeleteCount + insertCount; k--) delete O[k - 1];
7210             } else if (insertCount > actualDeleteCount) {
7211               for (k = len - actualDeleteCount; k > actualStart; k--) {
7212                 from = k + actualDeleteCount - 1;
7213                 to = k + insertCount - 1;
7214                 if (from in O) O[to] = O[from];
7215                 else delete O[to];
7216               }
7217             }
7218             for (k = 0; k < insertCount; k++) {
7219               O[k + actualStart] = arguments[k + 2];
7220             }
7221             O.length = len - actualDeleteCount + insertCount;
7222             return A;
7223           }
7224         });
7225
7226         var defineWellKnownSymbol$1 = defineWellKnownSymbol$4;
7227
7228         // `Symbol.toStringTag` well-known symbol
7229         // https://tc39.es/ecma262/#sec-symbol.tostringtag
7230         defineWellKnownSymbol$1('toStringTag');
7231
7232         var global$h = global$1m;
7233         var setToStringTag$3 = setToStringTag$a;
7234
7235         // JSON[@@toStringTag] property
7236         // https://tc39.es/ecma262/#sec-json-@@tostringtag
7237         setToStringTag$3(global$h.JSON, 'JSON', true);
7238
7239         var setToStringTag$2 = setToStringTag$a;
7240
7241         // Math[@@toStringTag] property
7242         // https://tc39.es/ecma262/#sec-math-@@tostringtag
7243         setToStringTag$2(Math, 'Math', true);
7244
7245         (function (factory) {
7246           factory();
7247         })(function () {
7248
7249           function _classCallCheck(instance, Constructor) {
7250             if (!(instance instanceof Constructor)) {
7251               throw new TypeError("Cannot call a class as a function");
7252             }
7253           }
7254
7255           function _defineProperties(target, props) {
7256             for (var i = 0; i < props.length; i++) {
7257               var descriptor = props[i];
7258               descriptor.enumerable = descriptor.enumerable || false;
7259               descriptor.configurable = true;
7260               if ("value" in descriptor) descriptor.writable = true;
7261               Object.defineProperty(target, descriptor.key, descriptor);
7262             }
7263           }
7264
7265           function _createClass(Constructor, protoProps, staticProps) {
7266             if (protoProps) _defineProperties(Constructor.prototype, protoProps);
7267             if (staticProps) _defineProperties(Constructor, staticProps);
7268             return Constructor;
7269           }
7270
7271           function _inherits(subClass, superClass) {
7272             if (typeof superClass !== "function" && superClass !== null) {
7273               throw new TypeError("Super expression must either be null or a function");
7274             }
7275
7276             subClass.prototype = Object.create(superClass && superClass.prototype, {
7277               constructor: {
7278                 value: subClass,
7279                 writable: true,
7280                 configurable: true
7281               }
7282             });
7283             if (superClass) _setPrototypeOf(subClass, superClass);
7284           }
7285
7286           function _getPrototypeOf(o) {
7287             _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
7288               return o.__proto__ || Object.getPrototypeOf(o);
7289             };
7290             return _getPrototypeOf(o);
7291           }
7292
7293           function _setPrototypeOf(o, p) {
7294             _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
7295               o.__proto__ = p;
7296               return o;
7297             };
7298
7299             return _setPrototypeOf(o, p);
7300           }
7301
7302           function _isNativeReflectConstruct() {
7303             if (typeof Reflect === "undefined" || !Reflect.construct) return false;
7304             if (Reflect.construct.sham) return false;
7305             if (typeof Proxy === "function") return true;
7306
7307             try {
7308               Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
7309               return true;
7310             } catch (e) {
7311               return false;
7312             }
7313           }
7314
7315           function _assertThisInitialized(self) {
7316             if (self === void 0) {
7317               throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
7318             }
7319
7320             return self;
7321           }
7322
7323           function _possibleConstructorReturn(self, call) {
7324             if (call && (_typeof(call) === "object" || typeof call === "function")) {
7325               return call;
7326             }
7327
7328             return _assertThisInitialized(self);
7329           }
7330
7331           function _createSuper(Derived) {
7332             var hasNativeReflectConstruct = _isNativeReflectConstruct();
7333
7334             return function _createSuperInternal() {
7335               var Super = _getPrototypeOf(Derived),
7336                   result;
7337
7338               if (hasNativeReflectConstruct) {
7339                 var NewTarget = _getPrototypeOf(this).constructor;
7340
7341                 result = Reflect.construct(Super, arguments, NewTarget);
7342               } else {
7343                 result = Super.apply(this, arguments);
7344               }
7345
7346               return _possibleConstructorReturn(this, result);
7347             };
7348           }
7349
7350           function _superPropBase(object, property) {
7351             while (!Object.prototype.hasOwnProperty.call(object, property)) {
7352               object = _getPrototypeOf(object);
7353               if (object === null) break;
7354             }
7355
7356             return object;
7357           }
7358
7359           function _get(target, property, receiver) {
7360             if (typeof Reflect !== "undefined" && Reflect.get) {
7361               _get = Reflect.get;
7362             } else {
7363               _get = function _get(target, property, receiver) {
7364                 var base = _superPropBase(target, property);
7365
7366                 if (!base) return;
7367                 var desc = Object.getOwnPropertyDescriptor(base, property);
7368
7369                 if (desc.get) {
7370                   return desc.get.call(receiver);
7371                 }
7372
7373                 return desc.value;
7374               };
7375             }
7376
7377             return _get(target, property, receiver || target);
7378           }
7379
7380           var Emitter = /*#__PURE__*/function () {
7381             function Emitter() {
7382               _classCallCheck(this, Emitter);
7383
7384               Object.defineProperty(this, 'listeners', {
7385                 value: {},
7386                 writable: true,
7387                 configurable: true
7388               });
7389             }
7390
7391             _createClass(Emitter, [{
7392               key: "addEventListener",
7393               value: function addEventListener(type, callback, options) {
7394                 if (!(type in this.listeners)) {
7395                   this.listeners[type] = [];
7396                 }
7397
7398                 this.listeners[type].push({
7399                   callback: callback,
7400                   options: options
7401                 });
7402               }
7403             }, {
7404               key: "removeEventListener",
7405               value: function removeEventListener(type, callback) {
7406                 if (!(type in this.listeners)) {
7407                   return;
7408                 }
7409
7410                 var stack = this.listeners[type];
7411
7412                 for (var i = 0, l = stack.length; i < l; i++) {
7413                   if (stack[i].callback === callback) {
7414                     stack.splice(i, 1);
7415                     return;
7416                   }
7417                 }
7418               }
7419             }, {
7420               key: "dispatchEvent",
7421               value: function dispatchEvent(event) {
7422                 if (!(event.type in this.listeners)) {
7423                   return;
7424                 }
7425
7426                 var stack = this.listeners[event.type];
7427                 var stackToCall = stack.slice();
7428
7429                 for (var i = 0, l = stackToCall.length; i < l; i++) {
7430                   var listener = stackToCall[i];
7431
7432                   try {
7433                     listener.callback.call(this, event);
7434                   } catch (e) {
7435                     Promise.resolve().then(function () {
7436                       throw e;
7437                     });
7438                   }
7439
7440                   if (listener.options && listener.options.once) {
7441                     this.removeEventListener(event.type, listener.callback);
7442                   }
7443                 }
7444
7445                 return !event.defaultPrevented;
7446               }
7447             }]);
7448
7449             return Emitter;
7450           }();
7451
7452           var AbortSignal = /*#__PURE__*/function (_Emitter) {
7453             _inherits(AbortSignal, _Emitter);
7454
7455             var _super = _createSuper(AbortSignal);
7456
7457             function AbortSignal() {
7458               var _this;
7459
7460               _classCallCheck(this, AbortSignal);
7461
7462               _this = _super.call(this); // Some versions of babel does not transpile super() correctly for IE <= 10, if the parent
7463               // constructor has failed to run, then "this.listeners" will still be undefined and then we call
7464               // the parent constructor directly instead as a workaround. For general details, see babel bug:
7465               // https://github.com/babel/babel/issues/3041
7466               // This hack was added as a fix for the issue described here:
7467               // https://github.com/Financial-Times/polyfill-library/pull/59#issuecomment-477558042
7468
7469               if (!_this.listeners) {
7470                 Emitter.call(_assertThisInitialized(_this));
7471               } // Compared to assignment, Object.defineProperty makes properties non-enumerable by default and
7472               // we want Object.keys(new AbortController().signal) to be [] for compat with the native impl
7473
7474
7475               Object.defineProperty(_assertThisInitialized(_this), 'aborted', {
7476                 value: false,
7477                 writable: true,
7478                 configurable: true
7479               });
7480               Object.defineProperty(_assertThisInitialized(_this), 'onabort', {
7481                 value: null,
7482                 writable: true,
7483                 configurable: true
7484               });
7485               return _this;
7486             }
7487
7488             _createClass(AbortSignal, [{
7489               key: "toString",
7490               value: function toString() {
7491                 return '[object AbortSignal]';
7492               }
7493             }, {
7494               key: "dispatchEvent",
7495               value: function dispatchEvent(event) {
7496                 if (event.type === 'abort') {
7497                   this.aborted = true;
7498
7499                   if (typeof this.onabort === 'function') {
7500                     this.onabort.call(this, event);
7501                   }
7502                 }
7503
7504                 _get(_getPrototypeOf(AbortSignal.prototype), "dispatchEvent", this).call(this, event);
7505               }
7506             }]);
7507
7508             return AbortSignal;
7509           }(Emitter);
7510
7511           var AbortController = /*#__PURE__*/function () {
7512             function AbortController() {
7513               _classCallCheck(this, AbortController); // Compared to assignment, Object.defineProperty makes properties non-enumerable by default and
7514               // we want Object.keys(new AbortController()) to be [] for compat with the native impl
7515
7516
7517               Object.defineProperty(this, 'signal', {
7518                 value: new AbortSignal(),
7519                 writable: true,
7520                 configurable: true
7521               });
7522             }
7523
7524             _createClass(AbortController, [{
7525               key: "abort",
7526               value: function abort() {
7527                 var event;
7528
7529                 try {
7530                   event = new Event('abort');
7531                 } catch (e) {
7532                   if (typeof document !== 'undefined') {
7533                     if (!document.createEvent) {
7534                       // For Internet Explorer 8:
7535                       event = document.createEventObject();
7536                       event.type = 'abort';
7537                     } else {
7538                       // For Internet Explorer 11:
7539                       event = document.createEvent('Event');
7540                       event.initEvent('abort', false, false);
7541                     }
7542                   } else {
7543                     // Fallback where document isn't available:
7544                     event = {
7545                       type: 'abort',
7546                       bubbles: false,
7547                       cancelable: false
7548                     };
7549                   }
7550                 }
7551
7552                 this.signal.dispatchEvent(event);
7553               }
7554             }, {
7555               key: "toString",
7556               value: function toString() {
7557                 return '[object AbortController]';
7558               }
7559             }]);
7560
7561             return AbortController;
7562           }();
7563
7564           if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
7565             // These are necessary to make sure that we get correct output for:
7566             // Object.prototype.toString.call(new AbortController())
7567             AbortController.prototype[Symbol.toStringTag] = 'AbortController';
7568             AbortSignal.prototype[Symbol.toStringTag] = 'AbortSignal';
7569           }
7570
7571           function polyfillNeeded(self) {
7572             if (self.__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL) {
7573               console.log('__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL=true is set, will force install polyfill');
7574               return true;
7575             } // Note that the "unfetch" minimal fetch polyfill defines fetch() without
7576             // defining window.Request, and this polyfill need to work on top of unfetch
7577             // so the below feature detection needs the !self.AbortController part.
7578             // The Request.prototype check is also needed because Safari versions 11.1.2
7579             // up to and including 12.1.x has a window.AbortController present but still
7580             // does NOT correctly implement abortable fetch:
7581             // https://bugs.webkit.org/show_bug.cgi?id=174980#c2
7582
7583
7584             return typeof self.Request === 'function' && !self.Request.prototype.hasOwnProperty('signal') || !self.AbortController;
7585           }
7586           /**
7587            * Note: the "fetch.Request" default value is available for fetch imported from
7588            * the "node-fetch" package and not in browsers. This is OK since browsers
7589            * will be importing umd-polyfill.js from that path "self" is passed the
7590            * decorator so the default value will not be used (because browsers that define
7591            * fetch also has Request). One quirky setup where self.fetch exists but
7592            * self.Request does not is when the "unfetch" minimal fetch polyfill is used
7593            * on top of IE11; for this case the browser will try to use the fetch.Request
7594            * default value which in turn will be undefined but then then "if (Request)"
7595            * will ensure that you get a patched fetch but still no Request (as expected).
7596            * @param {fetch, Request = fetch.Request}
7597            * @returns {fetch: abortableFetch, Request: AbortableRequest}
7598            */
7599
7600
7601           function abortableFetchDecorator(patchTargets) {
7602             if ('function' === typeof patchTargets) {
7603               patchTargets = {
7604                 fetch: patchTargets
7605               };
7606             }
7607
7608             var _patchTargets = patchTargets,
7609                 fetch = _patchTargets.fetch,
7610                 _patchTargets$Request = _patchTargets.Request,
7611                 NativeRequest = _patchTargets$Request === void 0 ? fetch.Request : _patchTargets$Request,
7612                 NativeAbortController = _patchTargets.AbortController,
7613                 _patchTargets$__FORCE = _patchTargets.__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL,
7614                 __FORCE_INSTALL_ABORTCONTROLLER_POLYFILL = _patchTargets$__FORCE === void 0 ? false : _patchTargets$__FORCE;
7615
7616             if (!polyfillNeeded({
7617               fetch: fetch,
7618               Request: NativeRequest,
7619               AbortController: NativeAbortController,
7620               __FORCE_INSTALL_ABORTCONTROLLER_POLYFILL: __FORCE_INSTALL_ABORTCONTROLLER_POLYFILL
7621             })) {
7622               return {
7623                 fetch: fetch,
7624                 Request: Request
7625               };
7626             }
7627
7628             var Request = NativeRequest; // Note that the "unfetch" minimal fetch polyfill defines fetch() without
7629             // defining window.Request, and this polyfill need to work on top of unfetch
7630             // hence we only patch it if it's available. Also we don't patch it if signal
7631             // is already available on the Request prototype because in this case support
7632             // is present and the patching below can cause a crash since it assigns to
7633             // request.signal which is technically a read-only property. This latter error
7634             // happens when you run the main5.js node-fetch example in the repo
7635             // "abortcontroller-polyfill-examples". The exact error is:
7636             //   request.signal = init.signal;
7637             //   ^
7638             // TypeError: Cannot set property signal of #<Request> which has only a getter
7639
7640             if (Request && !Request.prototype.hasOwnProperty('signal') || __FORCE_INSTALL_ABORTCONTROLLER_POLYFILL) {
7641               Request = function Request(input, init) {
7642                 var signal;
7643
7644                 if (init && init.signal) {
7645                   signal = init.signal; // Never pass init.signal to the native Request implementation when the polyfill has
7646                   // been installed because if we're running on top of a browser with a
7647                   // working native AbortController (i.e. the polyfill was installed due to
7648                   // __FORCE_INSTALL_ABORTCONTROLLER_POLYFILL being set), then passing our
7649                   // fake AbortSignal to the native fetch will trigger:
7650                   // TypeError: Failed to construct 'Request': member signal is not of type AbortSignal.
7651
7652                   delete init.signal;
7653                 }
7654
7655                 var request = new NativeRequest(input, init);
7656
7657                 if (signal) {
7658                   Object.defineProperty(request, 'signal', {
7659                     writable: false,
7660                     enumerable: false,
7661                     configurable: true,
7662                     value: signal
7663                   });
7664                 }
7665
7666                 return request;
7667               };
7668
7669               Request.prototype = NativeRequest.prototype;
7670             }
7671
7672             var realFetch = fetch;
7673
7674             var abortableFetch = function abortableFetch(input, init) {
7675               var signal = Request && Request.prototype.isPrototypeOf(input) ? input.signal : init ? init.signal : undefined;
7676
7677               if (signal) {
7678                 var abortError;
7679
7680                 try {
7681                   abortError = new DOMException('Aborted', 'AbortError');
7682                 } catch (err) {
7683                   // IE 11 does not support calling the DOMException constructor, use a
7684                   // regular error object on it instead.
7685                   abortError = new Error('Aborted');
7686                   abortError.name = 'AbortError';
7687                 } // Return early if already aborted, thus avoiding making an HTTP request
7688
7689
7690                 if (signal.aborted) {
7691                   return Promise.reject(abortError);
7692                 } // Turn an event into a promise, reject it once `abort` is dispatched
7693
7694
7695                 var cancellation = new Promise(function (_, reject) {
7696                   signal.addEventListener('abort', function () {
7697                     return reject(abortError);
7698                   }, {
7699                     once: true
7700                   });
7701                 });
7702
7703                 if (init && init.signal) {
7704                   // Never pass .signal to the native implementation when the polyfill has
7705                   // been installed because if we're running on top of a browser with a
7706                   // working native AbortController (i.e. the polyfill was installed due to
7707                   // __FORCE_INSTALL_ABORTCONTROLLER_POLYFILL being set), then passing our
7708                   // fake AbortSignal to the native fetch will trigger:
7709                   // TypeError: Failed to execute 'fetch' on 'Window': member signal is not of type AbortSignal.
7710                   delete init.signal;
7711                 } // Return the fastest promise (don't need to wait for request to finish)
7712
7713
7714                 return Promise.race([cancellation, realFetch(input, init)]);
7715               }
7716
7717               return realFetch(input, init);
7718             };
7719
7720             return {
7721               fetch: abortableFetch,
7722               Request: Request
7723             };
7724           }
7725
7726           (function (self) {
7727             if (!polyfillNeeded(self)) {
7728               return;
7729             }
7730
7731             if (!self.fetch) {
7732               console.warn('fetch() is not available, cannot install abortcontroller-polyfill');
7733               return;
7734             }
7735
7736             var _abortableFetch = abortableFetchDecorator(self),
7737                 fetch = _abortableFetch.fetch,
7738                 Request = _abortableFetch.Request;
7739
7740             self.fetch = fetch;
7741             self.Request = Request;
7742             Object.defineProperty(self, 'AbortController', {
7743               writable: true,
7744               enumerable: false,
7745               configurable: true,
7746               value: AbortController
7747             });
7748             Object.defineProperty(self, 'AbortSignal', {
7749               writable: true,
7750               enumerable: false,
7751               configurable: true,
7752               value: AbortSignal
7753             });
7754           })(typeof self !== 'undefined' ? self : commonjsGlobal);
7755         });
7756
7757         function actionAddEntity(way) {
7758           return function (graph) {
7759             return graph.replace(way);
7760           };
7761         }
7762
7763         var $$M = _export;
7764         var global$g = global$1m;
7765         var fails$k = fails$S;
7766         var isArray$3 = isArray$8;
7767         var isObject$8 = isObject$s;
7768         var toObject$6 = toObject$j;
7769         var lengthOfArrayLike$4 = lengthOfArrayLike$g;
7770         var createProperty$1 = createProperty$4;
7771         var arraySpeciesCreate$1 = arraySpeciesCreate$4;
7772         var arrayMethodHasSpeciesSupport$1 = arrayMethodHasSpeciesSupport$5;
7773         var wellKnownSymbol$2 = wellKnownSymbol$t;
7774         var V8_VERSION = engineV8Version;
7775
7776         var IS_CONCAT_SPREADABLE = wellKnownSymbol$2('isConcatSpreadable');
7777         var MAX_SAFE_INTEGER = 0x1FFFFFFFFFFFFF;
7778         var MAXIMUM_ALLOWED_INDEX_EXCEEDED = 'Maximum allowed index exceeded';
7779         var TypeError$5 = global$g.TypeError;
7780
7781         // We can't use this feature detection in V8 since it causes
7782         // deoptimization and serious performance degradation
7783         // https://github.com/zloirock/core-js/issues/679
7784         var IS_CONCAT_SPREADABLE_SUPPORT = V8_VERSION >= 51 || !fails$k(function () {
7785           var array = [];
7786           array[IS_CONCAT_SPREADABLE] = false;
7787           return array.concat()[0] !== array;
7788         });
7789
7790         var SPECIES_SUPPORT = arrayMethodHasSpeciesSupport$1('concat');
7791
7792         var isConcatSpreadable = function (O) {
7793           if (!isObject$8(O)) return false;
7794           var spreadable = O[IS_CONCAT_SPREADABLE];
7795           return spreadable !== undefined ? !!spreadable : isArray$3(O);
7796         };
7797
7798         var FORCED$a = !IS_CONCAT_SPREADABLE_SUPPORT || !SPECIES_SUPPORT;
7799
7800         // `Array.prototype.concat` method
7801         // https://tc39.es/ecma262/#sec-array.prototype.concat
7802         // with adding support of @@isConcatSpreadable and @@species
7803         $$M({ target: 'Array', proto: true, forced: FORCED$a }, {
7804           // eslint-disable-next-line no-unused-vars -- required for `.length`
7805           concat: function concat(arg) {
7806             var O = toObject$6(this);
7807             var A = arraySpeciesCreate$1(O, 0);
7808             var n = 0;
7809             var i, k, length, len, E;
7810             for (i = -1, length = arguments.length; i < length; i++) {
7811               E = i === -1 ? O : arguments[i];
7812               if (isConcatSpreadable(E)) {
7813                 len = lengthOfArrayLike$4(E);
7814                 if (n + len > MAX_SAFE_INTEGER) throw TypeError$5(MAXIMUM_ALLOWED_INDEX_EXCEEDED);
7815                 for (k = 0; k < len; k++, n++) if (k in E) createProperty$1(A, n, E[k]);
7816               } else {
7817                 if (n >= MAX_SAFE_INTEGER) throw TypeError$5(MAXIMUM_ALLOWED_INDEX_EXCEEDED);
7818                 createProperty$1(A, n++, E);
7819               }
7820             }
7821             A.length = n;
7822             return A;
7823           }
7824         });
7825
7826         var DESCRIPTORS$7 = descriptors;
7827         var uncurryThis$l = functionUncurryThis;
7828         var call$5 = functionCall;
7829         var fails$j = fails$S;
7830         var objectKeys$1 = objectKeys$4;
7831         var getOwnPropertySymbolsModule = objectGetOwnPropertySymbols;
7832         var propertyIsEnumerableModule = objectPropertyIsEnumerable;
7833         var toObject$5 = toObject$j;
7834         var IndexedObject = indexedObject;
7835
7836         // eslint-disable-next-line es/no-object-assign -- safe
7837         var $assign = Object.assign;
7838         // eslint-disable-next-line es/no-object-defineproperty -- required for testing
7839         var defineProperty$4 = Object.defineProperty;
7840         var concat = uncurryThis$l([].concat);
7841
7842         // `Object.assign` method
7843         // https://tc39.es/ecma262/#sec-object.assign
7844         var objectAssign = !$assign || fails$j(function () {
7845           // should have correct order of operations (Edge bug)
7846           if (DESCRIPTORS$7 && $assign({ b: 1 }, $assign(defineProperty$4({}, 'a', {
7847             enumerable: true,
7848             get: function () {
7849               defineProperty$4(this, 'b', {
7850                 value: 3,
7851                 enumerable: false
7852               });
7853             }
7854           }), { b: 2 })).b !== 1) return true;
7855           // should work with symbols and should have deterministic property order (V8 bug)
7856           var A = {};
7857           var B = {};
7858           // eslint-disable-next-line es/no-symbol -- safe
7859           var symbol = Symbol();
7860           var alphabet = 'abcdefghijklmnopqrst';
7861           A[symbol] = 7;
7862           alphabet.split('').forEach(function (chr) { B[chr] = chr; });
7863           return $assign({}, A)[symbol] != 7 || objectKeys$1($assign({}, B)).join('') != alphabet;
7864         }) ? function assign(target, source) { // eslint-disable-line no-unused-vars -- required for `.length`
7865           var T = toObject$5(target);
7866           var argumentsLength = arguments.length;
7867           var index = 1;
7868           var getOwnPropertySymbols = getOwnPropertySymbolsModule.f;
7869           var propertyIsEnumerable = propertyIsEnumerableModule.f;
7870           while (argumentsLength > index) {
7871             var S = IndexedObject(arguments[index++]);
7872             var keys = getOwnPropertySymbols ? concat(objectKeys$1(S), getOwnPropertySymbols(S)) : objectKeys$1(S);
7873             var length = keys.length;
7874             var j = 0;
7875             var key;
7876             while (length > j) {
7877               key = keys[j++];
7878               if (!DESCRIPTORS$7 || call$5(propertyIsEnumerable, S, key)) T[key] = S[key];
7879             }
7880           } return T;
7881         } : $assign;
7882
7883         var $$L = _export;
7884         var assign$2 = objectAssign;
7885
7886         // `Object.assign` method
7887         // https://tc39.es/ecma262/#sec-object.assign
7888         // eslint-disable-next-line es/no-object-assign -- required for testing
7889         $$L({ target: 'Object', stat: true, forced: Object.assign !== assign$2 }, {
7890           assign: assign$2
7891         });
7892
7893         var $$K = _export;
7894         var $filter = arrayIteration.filter;
7895         var arrayMethodHasSpeciesSupport = arrayMethodHasSpeciesSupport$5;
7896
7897         var HAS_SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('filter');
7898
7899         // `Array.prototype.filter` method
7900         // https://tc39.es/ecma262/#sec-array.prototype.filter
7901         // with adding support of @@species
7902         $$K({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT }, {
7903           filter: function filter(callbackfn /* , thisArg */) {
7904             return $filter(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
7905           }
7906         });
7907
7908         var $$J = _export;
7909         var toObject$4 = toObject$j;
7910         var nativeKeys = objectKeys$4;
7911         var fails$i = fails$S;
7912
7913         var FAILS_ON_PRIMITIVES$2 = fails$i(function () { nativeKeys(1); });
7914
7915         // `Object.keys` method
7916         // https://tc39.es/ecma262/#sec-object.keys
7917         $$J({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES$2 }, {
7918           keys: function keys(it) {
7919             return nativeKeys(toObject$4(it));
7920           }
7921         });
7922
7923         var $$I = _export;
7924         var uncurryThis$k = functionUncurryThis;
7925         var isArray$2 = isArray$8;
7926
7927         var un$Reverse = uncurryThis$k([].reverse);
7928         var test$1 = [1, 2];
7929
7930         // `Array.prototype.reverse` method
7931         // https://tc39.es/ecma262/#sec-array.prototype.reverse
7932         // fix for Safari 12.0 bug
7933         // https://bugs.webkit.org/show_bug.cgi?id=188794
7934         $$I({ target: 'Array', proto: true, forced: String(test$1) === String(test$1.reverse()) }, {
7935           reverse: function reverse() {
7936             // eslint-disable-next-line no-self-assign -- dirty hack
7937             if (isArray$2(this)) this.length = this.length;
7938             return un$Reverse(this);
7939           }
7940         });
7941
7942         var global$f = global$1m;
7943         var fails$h = fails$S;
7944         var uncurryThis$j = functionUncurryThis;
7945         var toString$c = toString$k;
7946         var trim$4 = stringTrim.trim;
7947         var whitespaces$1 = whitespaces$4;
7948
7949         var charAt$2 = uncurryThis$j(''.charAt);
7950         var n$ParseFloat = global$f.parseFloat;
7951         var Symbol$2 = global$f.Symbol;
7952         var ITERATOR$1 = Symbol$2 && Symbol$2.iterator;
7953         var FORCED$9 = 1 / n$ParseFloat(whitespaces$1 + '-0') !== -Infinity
7954           // MS Edge 18- broken with boxed symbols
7955           || (ITERATOR$1 && !fails$h(function () { n$ParseFloat(Object(ITERATOR$1)); }));
7956
7957         // `parseFloat` method
7958         // https://tc39.es/ecma262/#sec-parsefloat-string
7959         var numberParseFloat = FORCED$9 ? function parseFloat(string) {
7960           var trimmedString = trim$4(toString$c(string));
7961           var result = n$ParseFloat(trimmedString);
7962           return result === 0 && charAt$2(trimmedString, 0) == '-' ? -0 : result;
7963         } : n$ParseFloat;
7964
7965         var $$H = _export;
7966         var $parseFloat = numberParseFloat;
7967
7968         // `parseFloat` method
7969         // https://tc39.es/ecma262/#sec-parsefloat-string
7970         $$H({ global: true, forced: parseFloat != $parseFloat }, {
7971           parseFloat: $parseFloat
7972         });
7973
7974         /*
7975         Order the nodes of a way in reverse order and reverse any direction dependent tags
7976         other than `oneway`. (We assume that correcting a backwards oneway is the primary
7977         reason for reversing a way.)
7978
7979         In addition, numeric-valued `incline` tags are negated.
7980
7981         The JOSM implementation was used as a guide, but transformations that were of unclear benefit
7982         or adjusted tags that don't seem to be used in practice were omitted.
7983
7984         References:
7985             http://wiki.openstreetmap.org/wiki/Forward_%26_backward,_left_%26_right
7986             http://wiki.openstreetmap.org/wiki/Key:direction#Steps
7987             http://wiki.openstreetmap.org/wiki/Key:incline
7988             http://wiki.openstreetmap.org/wiki/Route#Members
7989             http://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java
7990             http://wiki.openstreetmap.org/wiki/Tag:highway%3Dstop
7991             http://wiki.openstreetmap.org/wiki/Key:traffic_sign#On_a_way_or_area
7992         */
7993         function actionReverse(entityID, options) {
7994           var ignoreKey = /^.*(_|:)?(description|name|note|website|ref|source|comment|watch|attribution)(_|:)?/;
7995           var numeric = /^([+\-]?)(?=[\d.])/;
7996           var directionKey = /direction$/;
7997           var turn_lanes = /^turn:lanes:?/;
7998           var keyReplacements = [[/:right$/, ':left'], [/:left$/, ':right'], [/:forward$/, ':backward'], [/:backward$/, ':forward'], [/:right:/, ':left:'], [/:left:/, ':right:'], [/:forward:/, ':backward:'], [/:backward:/, ':forward:']];
7999           var valueReplacements = {
8000             left: 'right',
8001             right: 'left',
8002             up: 'down',
8003             down: 'up',
8004             forward: 'backward',
8005             backward: 'forward',
8006             forwards: 'backward',
8007             backwards: 'forward'
8008           };
8009           var roleReplacements = {
8010             forward: 'backward',
8011             backward: 'forward',
8012             forwards: 'backward',
8013             backwards: 'forward'
8014           };
8015           var onewayReplacements = {
8016             yes: '-1',
8017             '1': '-1',
8018             '-1': 'yes'
8019           };
8020           var compassReplacements = {
8021             N: 'S',
8022             NNE: 'SSW',
8023             NE: 'SW',
8024             ENE: 'WSW',
8025             E: 'W',
8026             ESE: 'WNW',
8027             SE: 'NW',
8028             SSE: 'NNW',
8029             S: 'N',
8030             SSW: 'NNE',
8031             SW: 'NE',
8032             WSW: 'ENE',
8033             W: 'E',
8034             WNW: 'ESE',
8035             NW: 'SE',
8036             NNW: 'SSE'
8037           };
8038
8039           function reverseKey(key) {
8040             for (var i = 0; i < keyReplacements.length; ++i) {
8041               var replacement = keyReplacements[i];
8042
8043               if (replacement[0].test(key)) {
8044                 return key.replace(replacement[0], replacement[1]);
8045               }
8046             }
8047
8048             return key;
8049           }
8050
8051           function reverseValue(key, value, includeAbsolute) {
8052             if (ignoreKey.test(key)) return value; // Turn lanes are left/right to key (not way) direction - #5674
8053
8054             if (turn_lanes.test(key)) {
8055               return value;
8056             } else if (key === 'incline' && numeric.test(value)) {
8057               return value.replace(numeric, function (_, sign) {
8058                 return sign === '-' ? '' : '-';
8059               });
8060             } else if (options && options.reverseOneway && key === 'oneway') {
8061               return onewayReplacements[value] || value;
8062             } else if (includeAbsolute && directionKey.test(key)) {
8063               if (compassReplacements[value]) return compassReplacements[value];
8064               var degrees = parseFloat(value);
8065
8066               if (typeof degrees === 'number' && !isNaN(degrees)) {
8067                 if (degrees < 180) {
8068                   degrees += 180;
8069                 } else {
8070                   degrees -= 180;
8071                 }
8072
8073                 return degrees.toString();
8074               }
8075             }
8076
8077             return valueReplacements[value] || value;
8078           } // Reverse the direction of tags attached to the nodes - #3076
8079
8080
8081           function reverseNodeTags(graph, nodeIDs) {
8082             for (var i = 0; i < nodeIDs.length; i++) {
8083               var node = graph.hasEntity(nodeIDs[i]);
8084               if (!node || !Object.keys(node.tags).length) continue;
8085               var tags = {};
8086
8087               for (var key in node.tags) {
8088                 tags[reverseKey(key)] = reverseValue(key, node.tags[key], node.id === entityID);
8089               }
8090
8091               graph = graph.replace(node.update({
8092                 tags: tags
8093               }));
8094             }
8095
8096             return graph;
8097           }
8098
8099           function reverseWay(graph, way) {
8100             var nodes = way.nodes.slice().reverse();
8101             var tags = {};
8102             var role;
8103
8104             for (var key in way.tags) {
8105               tags[reverseKey(key)] = reverseValue(key, way.tags[key]);
8106             }
8107
8108             graph.parentRelations(way).forEach(function (relation) {
8109               relation.members.forEach(function (member, index) {
8110                 if (member.id === way.id && (role = roleReplacements[member.role])) {
8111                   relation = relation.updateMember({
8112                     role: role
8113                   }, index);
8114                   graph = graph.replace(relation);
8115                 }
8116               });
8117             }); // Reverse any associated directions on nodes on the way and then replace
8118             // the way itself with the reversed node ids and updated way tags
8119
8120             return reverseNodeTags(graph, nodes).replace(way.update({
8121               nodes: nodes,
8122               tags: tags
8123             }));
8124           }
8125
8126           var action = function action(graph) {
8127             var entity = graph.entity(entityID);
8128
8129             if (entity.type === 'way') {
8130               return reverseWay(graph, entity);
8131             }
8132
8133             return reverseNodeTags(graph, [entityID]);
8134           };
8135
8136           action.disabled = function (graph) {
8137             var entity = graph.hasEntity(entityID);
8138             if (!entity || entity.type === 'way') return false;
8139
8140             for (var key in entity.tags) {
8141               var value = entity.tags[key];
8142
8143               if (reverseKey(key) !== key || reverseValue(key, value, true) !== value) {
8144                 return false;
8145               }
8146             }
8147
8148             return 'nondirectional_node';
8149           };
8150
8151           action.entityID = function () {
8152             return entityID;
8153           };
8154
8155           return action;
8156         }
8157
8158         function osmIsInterestingTag(key) {
8159           return key !== 'attribution' && key !== 'created_by' && key !== 'source' && key !== 'odbl' && key.indexOf('source:') !== 0 && key.indexOf('source_ref') !== 0 && // purposely exclude colon
8160           key.indexOf('tiger:') !== 0;
8161         }
8162         var osmAreaKeys = {};
8163         function osmSetAreaKeys(value) {
8164           osmAreaKeys = value;
8165         } // returns an object with the tag from `tags` that implies an area geometry, if any
8166
8167         function osmTagSuggestingArea(tags) {
8168           if (tags.area === 'yes') return {
8169             area: 'yes'
8170           };
8171           if (tags.area === 'no') return null; // `highway` and `railway` are typically linear features, but there
8172           // are a few exceptions that should be treated as areas, even in the
8173           // absence of a proper `area=yes` or `areaKeys` tag.. see #4194
8174
8175           var lineKeys = {
8176             highway: {
8177               rest_area: true,
8178               services: true
8179             },
8180             railway: {
8181               roundhouse: true,
8182               station: true,
8183               traverser: true,
8184               turntable: true,
8185               wash: true
8186             }
8187           };
8188           var returnTags = {};
8189
8190           for (var key in tags) {
8191             if (key in osmAreaKeys && !(tags[key] in osmAreaKeys[key])) {
8192               returnTags[key] = tags[key];
8193               return returnTags;
8194             }
8195
8196             if (key in lineKeys && tags[key] in lineKeys[key]) {
8197               returnTags[key] = tags[key];
8198               return returnTags;
8199             }
8200           }
8201
8202           return null;
8203         } // Tags that indicate a node can be a standalone point
8204         // e.g. { amenity: { bar: true, parking: true, ... } ... }
8205
8206         var osmPointTags = {};
8207         function osmSetPointTags(value) {
8208           osmPointTags = value;
8209         } // Tags that indicate a node can be part of a way
8210         // e.g. { amenity: { parking: true, ... }, highway: { stop: true ... } ... }
8211
8212         var osmVertexTags = {};
8213         function osmSetVertexTags(value) {
8214           osmVertexTags = value;
8215         }
8216         function osmNodeGeometriesForTags(nodeTags) {
8217           var geometries = {};
8218
8219           for (var key in nodeTags) {
8220             if (osmPointTags[key] && (osmPointTags[key]['*'] || osmPointTags[key][nodeTags[key]])) {
8221               geometries.point = true;
8222             }
8223
8224             if (osmVertexTags[key] && (osmVertexTags[key]['*'] || osmVertexTags[key][nodeTags[key]])) {
8225               geometries.vertex = true;
8226             } // break early if both are already supported
8227
8228
8229             if (geometries.point && geometries.vertex) break;
8230           }
8231
8232           return geometries;
8233         }
8234         var osmOneWayTags = {
8235           'aerialway': {
8236             'chair_lift': true,
8237             'drag_lift': true,
8238             'j-bar': true,
8239             'magic_carpet': true,
8240             'mixed_lift': true,
8241             'platter': true,
8242             'rope_tow': true,
8243             't-bar': true,
8244             'zip_line': true
8245           },
8246           'highway': {
8247             'motorway': true
8248           },
8249           'junction': {
8250             'circular': true,
8251             'roundabout': true
8252           },
8253           'man_made': {
8254             'goods_conveyor': true,
8255             'piste:halfpipe': true
8256           },
8257           'piste:type': {
8258             'downhill': true,
8259             'sled': true,
8260             'yes': true
8261           },
8262           'seamark:type': {
8263             'separation_lane': true,
8264             'separation_roundabout': true
8265           },
8266           'waterway': {
8267             'canal': true,
8268             'ditch': true,
8269             'drain': true,
8270             'fish_pass': true,
8271             'river': true,
8272             'stream': true,
8273             'tidal_channel': true
8274           }
8275         }; // solid and smooth surfaces akin to the assumed default road surface in OSM
8276
8277         var osmPavedTags = {
8278           'surface': {
8279             'paved': true,
8280             'asphalt': true,
8281             'concrete': true,
8282             'concrete:lanes': true,
8283             'concrete:plates': true
8284           },
8285           'tracktype': {
8286             'grade1': true
8287           }
8288         }; // solid, if somewhat uncommon surfaces with a high range of smoothness
8289
8290         var osmSemipavedTags = {
8291           'surface': {
8292             'cobblestone': true,
8293             'cobblestone:flattened': true,
8294             'unhewn_cobblestone': true,
8295             'sett': true,
8296             'paving_stones': true,
8297             'metal': true,
8298             'wood': true
8299           }
8300         };
8301         var osmRightSideIsInsideTags = {
8302           'natural': {
8303             'cliff': true,
8304             'coastline': 'coastline'
8305           },
8306           'barrier': {
8307             'retaining_wall': true,
8308             'kerb': true,
8309             'guard_rail': true,
8310             'city_wall': true
8311           },
8312           'man_made': {
8313             'embankment': true
8314           },
8315           'waterway': {
8316             'weir': true
8317           }
8318         }; // "highway" tag values for pedestrian or vehicle right-of-ways that make up the routable network
8319         // (does not include `raceway`)
8320
8321         var osmRoutableHighwayTagValues = {
8322           motorway: true,
8323           trunk: true,
8324           primary: true,
8325           secondary: true,
8326           tertiary: true,
8327           residential: true,
8328           motorway_link: true,
8329           trunk_link: true,
8330           primary_link: true,
8331           secondary_link: true,
8332           tertiary_link: true,
8333           unclassified: true,
8334           road: true,
8335           service: true,
8336           track: true,
8337           living_street: true,
8338           bus_guideway: true,
8339           path: true,
8340           footway: true,
8341           cycleway: true,
8342           bridleway: true,
8343           pedestrian: true,
8344           corridor: true,
8345           steps: true
8346         }; // "highway" tag values that generally do not allow motor vehicles
8347
8348         var osmPathHighwayTagValues = {
8349           path: true,
8350           footway: true,
8351           cycleway: true,
8352           bridleway: true,
8353           pedestrian: true,
8354           corridor: true,
8355           steps: true
8356         }; // "railway" tag values representing existing railroad tracks (purposely does not include 'abandoned')
8357
8358         var osmRailwayTrackTagValues = {
8359           rail: true,
8360           light_rail: true,
8361           tram: true,
8362           subway: true,
8363           monorail: true,
8364           funicular: true,
8365           miniature: true,
8366           narrow_gauge: true,
8367           disused: true,
8368           preserved: true
8369         }; // "waterway" tag values for line features representing water flow
8370
8371         var osmFlowingWaterwayTagValues = {
8372           canal: true,
8373           ditch: true,
8374           drain: true,
8375           fish_pass: true,
8376           river: true,
8377           stream: true,
8378           tidal_channel: true
8379         };
8380
8381         var global$e = global$1m;
8382         var fails$g = fails$S;
8383         var uncurryThis$i = functionUncurryThis;
8384         var toString$b = toString$k;
8385         var trim$3 = stringTrim.trim;
8386         var whitespaces = whitespaces$4;
8387
8388         var $parseInt$1 = global$e.parseInt;
8389         var Symbol$1 = global$e.Symbol;
8390         var ITERATOR = Symbol$1 && Symbol$1.iterator;
8391         var hex$2 = /^[+-]?0x/i;
8392         var exec$3 = uncurryThis$i(hex$2.exec);
8393         var FORCED$8 = $parseInt$1(whitespaces + '08') !== 8 || $parseInt$1(whitespaces + '0x16') !== 22
8394           // MS Edge 18- broken with boxed symbols
8395           || (ITERATOR && !fails$g(function () { $parseInt$1(Object(ITERATOR)); }));
8396
8397         // `parseInt` method
8398         // https://tc39.es/ecma262/#sec-parseint-string-radix
8399         var numberParseInt = FORCED$8 ? function parseInt(string, radix) {
8400           var S = trim$3(toString$b(string));
8401           return $parseInt$1(S, (radix >>> 0) || (exec$3(hex$2, S) ? 16 : 10));
8402         } : $parseInt$1;
8403
8404         var $$G = _export;
8405         var $parseInt = numberParseInt;
8406
8407         // `parseInt` method
8408         // https://tc39.es/ecma262/#sec-parseint-string-radix
8409         $$G({ global: true, forced: parseInt != $parseInt }, {
8410           parseInt: $parseInt
8411         });
8412
8413         var internalMetadata = {exports: {}};
8414
8415         // FF26- bug: ArrayBuffers are non-extensible, but Object.isExtensible does not report it
8416         var fails$f = fails$S;
8417
8418         var arrayBufferNonExtensible = fails$f(function () {
8419           if (typeof ArrayBuffer == 'function') {
8420             var buffer = new ArrayBuffer(8);
8421             // eslint-disable-next-line es/no-object-isextensible, es/no-object-defineproperty -- safe
8422             if (Object.isExtensible(buffer)) Object.defineProperty(buffer, 'a', { value: 8 });
8423           }
8424         });
8425
8426         var fails$e = fails$S;
8427         var isObject$7 = isObject$s;
8428         var classof = classofRaw$1;
8429         var ARRAY_BUFFER_NON_EXTENSIBLE = arrayBufferNonExtensible;
8430
8431         // eslint-disable-next-line es/no-object-isextensible -- safe
8432         var $isExtensible = Object.isExtensible;
8433         var FAILS_ON_PRIMITIVES$1 = fails$e(function () { $isExtensible(1); });
8434
8435         // `Object.isExtensible` method
8436         // https://tc39.es/ecma262/#sec-object.isextensible
8437         var objectIsExtensible = (FAILS_ON_PRIMITIVES$1 || ARRAY_BUFFER_NON_EXTENSIBLE) ? function isExtensible(it) {
8438           if (!isObject$7(it)) return false;
8439           if (ARRAY_BUFFER_NON_EXTENSIBLE && classof(it) == 'ArrayBuffer') return false;
8440           return $isExtensible ? $isExtensible(it) : true;
8441         } : $isExtensible;
8442
8443         var fails$d = fails$S;
8444
8445         var freezing = !fails$d(function () {
8446           // eslint-disable-next-line es/no-object-isextensible, es/no-object-preventextensions -- required for testing
8447           return Object.isExtensible(Object.preventExtensions({}));
8448         });
8449
8450         var $$F = _export;
8451         var uncurryThis$h = functionUncurryThis;
8452         var hiddenKeys = hiddenKeys$6;
8453         var isObject$6 = isObject$s;
8454         var hasOwn$3 = hasOwnProperty_1;
8455         var defineProperty$3 = objectDefineProperty.f;
8456         var getOwnPropertyNamesModule = objectGetOwnPropertyNames;
8457         var getOwnPropertyNamesExternalModule = objectGetOwnPropertyNamesExternal;
8458         var isExtensible = objectIsExtensible;
8459         var uid = uid$5;
8460         var FREEZING$1 = freezing;
8461
8462         var REQUIRED = false;
8463         var METADATA = uid('meta');
8464         var id$1 = 0;
8465
8466         var setMetadata = function (it) {
8467           defineProperty$3(it, METADATA, { value: {
8468             objectID: 'O' + id$1++, // object ID
8469             weakData: {}          // weak collections IDs
8470           } });
8471         };
8472
8473         var fastKey$1 = function (it, create) {
8474           // return a primitive with prefix
8475           if (!isObject$6(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;
8476           if (!hasOwn$3(it, METADATA)) {
8477             // can't set metadata to uncaught frozen object
8478             if (!isExtensible(it)) return 'F';
8479             // not necessary to add metadata
8480             if (!create) return 'E';
8481             // add missing metadata
8482             setMetadata(it);
8483           // return object ID
8484           } return it[METADATA].objectID;
8485         };
8486
8487         var getWeakData = function (it, create) {
8488           if (!hasOwn$3(it, METADATA)) {
8489             // can't set metadata to uncaught frozen object
8490             if (!isExtensible(it)) return true;
8491             // not necessary to add metadata
8492             if (!create) return false;
8493             // add missing metadata
8494             setMetadata(it);
8495           // return the store of weak collections IDs
8496           } return it[METADATA].weakData;
8497         };
8498
8499         // add metadata on freeze-family methods calling
8500         var onFreeze$1 = function (it) {
8501           if (FREEZING$1 && REQUIRED && isExtensible(it) && !hasOwn$3(it, METADATA)) setMetadata(it);
8502           return it;
8503         };
8504
8505         var enable = function () {
8506           meta.enable = function () { /* empty */ };
8507           REQUIRED = true;
8508           var getOwnPropertyNames = getOwnPropertyNamesModule.f;
8509           var splice = uncurryThis$h([].splice);
8510           var test = {};
8511           test[METADATA] = 1;
8512
8513           // prevent exposing of metadata key
8514           if (getOwnPropertyNames(test).length) {
8515             getOwnPropertyNamesModule.f = function (it) {
8516               var result = getOwnPropertyNames(it);
8517               for (var i = 0, length = result.length; i < length; i++) {
8518                 if (result[i] === METADATA) {
8519                   splice(result, i, 1);
8520                   break;
8521                 }
8522               } return result;
8523             };
8524
8525             $$F({ target: 'Object', stat: true, forced: true }, {
8526               getOwnPropertyNames: getOwnPropertyNamesExternalModule.f
8527             });
8528           }
8529         };
8530
8531         var meta = internalMetadata.exports = {
8532           enable: enable,
8533           fastKey: fastKey$1,
8534           getWeakData: getWeakData,
8535           onFreeze: onFreeze$1
8536         };
8537
8538         hiddenKeys[METADATA] = true;
8539
8540         var $$E = _export;
8541         var global$d = global$1m;
8542         var uncurryThis$g = functionUncurryThis;
8543         var isForced$2 = isForced_1;
8544         var redefine$4 = redefine$h.exports;
8545         var InternalMetadataModule = internalMetadata.exports;
8546         var iterate$1 = iterate$3;
8547         var anInstance$2 = anInstance$7;
8548         var isCallable$1 = isCallable$r;
8549         var isObject$5 = isObject$s;
8550         var fails$c = fails$S;
8551         var checkCorrectnessOfIteration$1 = checkCorrectnessOfIteration$4;
8552         var setToStringTag$1 = setToStringTag$a;
8553         var inheritIfRequired$2 = inheritIfRequired$4;
8554
8555         var collection$2 = function (CONSTRUCTOR_NAME, wrapper, common) {
8556           var IS_MAP = CONSTRUCTOR_NAME.indexOf('Map') !== -1;
8557           var IS_WEAK = CONSTRUCTOR_NAME.indexOf('Weak') !== -1;
8558           var ADDER = IS_MAP ? 'set' : 'add';
8559           var NativeConstructor = global$d[CONSTRUCTOR_NAME];
8560           var NativePrototype = NativeConstructor && NativeConstructor.prototype;
8561           var Constructor = NativeConstructor;
8562           var exported = {};
8563
8564           var fixMethod = function (KEY) {
8565             var uncurriedNativeMethod = uncurryThis$g(NativePrototype[KEY]);
8566             redefine$4(NativePrototype, KEY,
8567               KEY == 'add' ? function add(value) {
8568                 uncurriedNativeMethod(this, value === 0 ? 0 : value);
8569                 return this;
8570               } : KEY == 'delete' ? function (key) {
8571                 return IS_WEAK && !isObject$5(key) ? false : uncurriedNativeMethod(this, key === 0 ? 0 : key);
8572               } : KEY == 'get' ? function get(key) {
8573                 return IS_WEAK && !isObject$5(key) ? undefined : uncurriedNativeMethod(this, key === 0 ? 0 : key);
8574               } : KEY == 'has' ? function has(key) {
8575                 return IS_WEAK && !isObject$5(key) ? false : uncurriedNativeMethod(this, key === 0 ? 0 : key);
8576               } : function set(key, value) {
8577                 uncurriedNativeMethod(this, key === 0 ? 0 : key, value);
8578                 return this;
8579               }
8580             );
8581           };
8582
8583           var REPLACE = isForced$2(
8584             CONSTRUCTOR_NAME,
8585             !isCallable$1(NativeConstructor) || !(IS_WEAK || NativePrototype.forEach && !fails$c(function () {
8586               new NativeConstructor().entries().next();
8587             }))
8588           );
8589
8590           if (REPLACE) {
8591             // create collection constructor
8592             Constructor = common.getConstructor(wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER);
8593             InternalMetadataModule.enable();
8594           } else if (isForced$2(CONSTRUCTOR_NAME, true)) {
8595             var instance = new Constructor();
8596             // early implementations not supports chaining
8597             var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance;
8598             // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false
8599             var THROWS_ON_PRIMITIVES = fails$c(function () { instance.has(1); });
8600             // most early implementations doesn't supports iterables, most modern - not close it correctly
8601             // eslint-disable-next-line no-new -- required for testing
8602             var ACCEPT_ITERABLES = checkCorrectnessOfIteration$1(function (iterable) { new NativeConstructor(iterable); });
8603             // for early implementations -0 and +0 not the same
8604             var BUGGY_ZERO = !IS_WEAK && fails$c(function () {
8605               // V8 ~ Chromium 42- fails only with 5+ elements
8606               var $instance = new NativeConstructor();
8607               var index = 5;
8608               while (index--) $instance[ADDER](index, index);
8609               return !$instance.has(-0);
8610             });
8611
8612             if (!ACCEPT_ITERABLES) {
8613               Constructor = wrapper(function (dummy, iterable) {
8614                 anInstance$2(dummy, NativePrototype);
8615                 var that = inheritIfRequired$2(new NativeConstructor(), dummy, Constructor);
8616                 if (iterable != undefined) iterate$1(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
8617                 return that;
8618               });
8619               Constructor.prototype = NativePrototype;
8620               NativePrototype.constructor = Constructor;
8621             }
8622
8623             if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {
8624               fixMethod('delete');
8625               fixMethod('has');
8626               IS_MAP && fixMethod('get');
8627             }
8628
8629             if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER);
8630
8631             // weak collections should not contains .clear method
8632             if (IS_WEAK && NativePrototype.clear) delete NativePrototype.clear;
8633           }
8634
8635           exported[CONSTRUCTOR_NAME] = Constructor;
8636           $$E({ global: true, forced: Constructor != NativeConstructor }, exported);
8637
8638           setToStringTag$1(Constructor, CONSTRUCTOR_NAME);
8639
8640           if (!IS_WEAK) common.setStrong(Constructor, CONSTRUCTOR_NAME, IS_MAP);
8641
8642           return Constructor;
8643         };
8644
8645         var defineProperty$2 = objectDefineProperty.f;
8646         var create$3 = objectCreate;
8647         var redefineAll = redefineAll$4;
8648         var bind$6 = functionBindContext;
8649         var anInstance$1 = anInstance$7;
8650         var iterate = iterate$3;
8651         var defineIterator = defineIterator$3;
8652         var setSpecies$1 = setSpecies$5;
8653         var DESCRIPTORS$6 = descriptors;
8654         var fastKey = internalMetadata.exports.fastKey;
8655         var InternalStateModule$1 = internalState;
8656
8657         var setInternalState$1 = InternalStateModule$1.set;
8658         var internalStateGetterFor = InternalStateModule$1.getterFor;
8659
8660         var collectionStrong$2 = {
8661           getConstructor: function (wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER) {
8662             var Constructor = wrapper(function (that, iterable) {
8663               anInstance$1(that, Prototype);
8664               setInternalState$1(that, {
8665                 type: CONSTRUCTOR_NAME,
8666                 index: create$3(null),
8667                 first: undefined,
8668                 last: undefined,
8669                 size: 0
8670               });
8671               if (!DESCRIPTORS$6) that.size = 0;
8672               if (iterable != undefined) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
8673             });
8674
8675             var Prototype = Constructor.prototype;
8676
8677             var getInternalState = internalStateGetterFor(CONSTRUCTOR_NAME);
8678
8679             var define = function (that, key, value) {
8680               var state = getInternalState(that);
8681               var entry = getEntry(that, key);
8682               var previous, index;
8683               // change existing entry
8684               if (entry) {
8685                 entry.value = value;
8686               // create new entry
8687               } else {
8688                 state.last = entry = {
8689                   index: index = fastKey(key, true),
8690                   key: key,
8691                   value: value,
8692                   previous: previous = state.last,
8693                   next: undefined,
8694                   removed: false
8695                 };
8696                 if (!state.first) state.first = entry;
8697                 if (previous) previous.next = entry;
8698                 if (DESCRIPTORS$6) state.size++;
8699                 else that.size++;
8700                 // add to index
8701                 if (index !== 'F') state.index[index] = entry;
8702               } return that;
8703             };
8704
8705             var getEntry = function (that, key) {
8706               var state = getInternalState(that);
8707               // fast case
8708               var index = fastKey(key);
8709               var entry;
8710               if (index !== 'F') return state.index[index];
8711               // frozen object case
8712               for (entry = state.first; entry; entry = entry.next) {
8713                 if (entry.key == key) return entry;
8714               }
8715             };
8716
8717             redefineAll(Prototype, {
8718               // `{ Map, Set }.prototype.clear()` methods
8719               // https://tc39.es/ecma262/#sec-map.prototype.clear
8720               // https://tc39.es/ecma262/#sec-set.prototype.clear
8721               clear: function clear() {
8722                 var that = this;
8723                 var state = getInternalState(that);
8724                 var data = state.index;
8725                 var entry = state.first;
8726                 while (entry) {
8727                   entry.removed = true;
8728                   if (entry.previous) entry.previous = entry.previous.next = undefined;
8729                   delete data[entry.index];
8730                   entry = entry.next;
8731                 }
8732                 state.first = state.last = undefined;
8733                 if (DESCRIPTORS$6) state.size = 0;
8734                 else that.size = 0;
8735               },
8736               // `{ Map, Set }.prototype.delete(key)` methods
8737               // https://tc39.es/ecma262/#sec-map.prototype.delete
8738               // https://tc39.es/ecma262/#sec-set.prototype.delete
8739               'delete': function (key) {
8740                 var that = this;
8741                 var state = getInternalState(that);
8742                 var entry = getEntry(that, key);
8743                 if (entry) {
8744                   var next = entry.next;
8745                   var prev = entry.previous;
8746                   delete state.index[entry.index];
8747                   entry.removed = true;
8748                   if (prev) prev.next = next;
8749                   if (next) next.previous = prev;
8750                   if (state.first == entry) state.first = next;
8751                   if (state.last == entry) state.last = prev;
8752                   if (DESCRIPTORS$6) state.size--;
8753                   else that.size--;
8754                 } return !!entry;
8755               },
8756               // `{ Map, Set }.prototype.forEach(callbackfn, thisArg = undefined)` methods
8757               // https://tc39.es/ecma262/#sec-map.prototype.foreach
8758               // https://tc39.es/ecma262/#sec-set.prototype.foreach
8759               forEach: function forEach(callbackfn /* , that = undefined */) {
8760                 var state = getInternalState(this);
8761                 var boundFunction = bind$6(callbackfn, arguments.length > 1 ? arguments[1] : undefined);
8762                 var entry;
8763                 while (entry = entry ? entry.next : state.first) {
8764                   boundFunction(entry.value, entry.key, this);
8765                   // revert to the last existing entry
8766                   while (entry && entry.removed) entry = entry.previous;
8767                 }
8768               },
8769               // `{ Map, Set}.prototype.has(key)` methods
8770               // https://tc39.es/ecma262/#sec-map.prototype.has
8771               // https://tc39.es/ecma262/#sec-set.prototype.has
8772               has: function has(key) {
8773                 return !!getEntry(this, key);
8774               }
8775             });
8776
8777             redefineAll(Prototype, IS_MAP ? {
8778               // `Map.prototype.get(key)` method
8779               // https://tc39.es/ecma262/#sec-map.prototype.get
8780               get: function get(key) {
8781                 var entry = getEntry(this, key);
8782                 return entry && entry.value;
8783               },
8784               // `Map.prototype.set(key, value)` method
8785               // https://tc39.es/ecma262/#sec-map.prototype.set
8786               set: function set(key, value) {
8787                 return define(this, key === 0 ? 0 : key, value);
8788               }
8789             } : {
8790               // `Set.prototype.add(value)` method
8791               // https://tc39.es/ecma262/#sec-set.prototype.add
8792               add: function add(value) {
8793                 return define(this, value = value === 0 ? 0 : value, value);
8794               }
8795             });
8796             if (DESCRIPTORS$6) defineProperty$2(Prototype, 'size', {
8797               get: function () {
8798                 return getInternalState(this).size;
8799               }
8800             });
8801             return Constructor;
8802           },
8803           setStrong: function (Constructor, CONSTRUCTOR_NAME, IS_MAP) {
8804             var ITERATOR_NAME = CONSTRUCTOR_NAME + ' Iterator';
8805             var getInternalCollectionState = internalStateGetterFor(CONSTRUCTOR_NAME);
8806             var getInternalIteratorState = internalStateGetterFor(ITERATOR_NAME);
8807             // `{ Map, Set }.prototype.{ keys, values, entries, @@iterator }()` methods
8808             // https://tc39.es/ecma262/#sec-map.prototype.entries
8809             // https://tc39.es/ecma262/#sec-map.prototype.keys
8810             // https://tc39.es/ecma262/#sec-map.prototype.values
8811             // https://tc39.es/ecma262/#sec-map.prototype-@@iterator
8812             // https://tc39.es/ecma262/#sec-set.prototype.entries
8813             // https://tc39.es/ecma262/#sec-set.prototype.keys
8814             // https://tc39.es/ecma262/#sec-set.prototype.values
8815             // https://tc39.es/ecma262/#sec-set.prototype-@@iterator
8816             defineIterator(Constructor, CONSTRUCTOR_NAME, function (iterated, kind) {
8817               setInternalState$1(this, {
8818                 type: ITERATOR_NAME,
8819                 target: iterated,
8820                 state: getInternalCollectionState(iterated),
8821                 kind: kind,
8822                 last: undefined
8823               });
8824             }, function () {
8825               var state = getInternalIteratorState(this);
8826               var kind = state.kind;
8827               var entry = state.last;
8828               // revert to the last existing entry
8829               while (entry && entry.removed) entry = entry.previous;
8830               // get next entry
8831               if (!state.target || !(state.last = entry = entry ? entry.next : state.state.first)) {
8832                 // or finish the iteration
8833                 state.target = undefined;
8834                 return { value: undefined, done: true };
8835               }
8836               // return step by kind
8837               if (kind == 'keys') return { value: entry.key, done: false };
8838               if (kind == 'values') return { value: entry.value, done: false };
8839               return { value: [entry.key, entry.value], done: false };
8840             }, IS_MAP ? 'entries' : 'values', !IS_MAP, true);
8841
8842             // `{ Map, Set }.prototype[@@species]` accessors
8843             // https://tc39.es/ecma262/#sec-get-map-@@species
8844             // https://tc39.es/ecma262/#sec-get-set-@@species
8845             setSpecies$1(CONSTRUCTOR_NAME);
8846           }
8847         };
8848
8849         var collection$1 = collection$2;
8850         var collectionStrong$1 = collectionStrong$2;
8851
8852         // `Set` constructor
8853         // https://tc39.es/ecma262/#sec-set-objects
8854         collection$1('Set', function (init) {
8855           return function Set() { return init(this, arguments.length ? arguments[0] : undefined); };
8856         }, collectionStrong$1);
8857
8858         function d3_ascending (a, b) {
8859           return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
8860         }
8861
8862         function d3_bisector (f) {
8863           var delta = f;
8864           var compare = f;
8865
8866           if (f.length === 1) {
8867             delta = function delta(d, x) {
8868               return f(d) - x;
8869             };
8870
8871             compare = ascendingComparator(f);
8872           }
8873
8874           function left(a, x, lo, hi) {
8875             if (lo == null) lo = 0;
8876             if (hi == null) hi = a.length;
8877
8878             while (lo < hi) {
8879               var mid = lo + hi >>> 1;
8880               if (compare(a[mid], x) < 0) lo = mid + 1;else hi = mid;
8881             }
8882
8883             return lo;
8884           }
8885
8886           function right(a, x, lo, hi) {
8887             if (lo == null) lo = 0;
8888             if (hi == null) hi = a.length;
8889
8890             while (lo < hi) {
8891               var mid = lo + hi >>> 1;
8892               if (compare(a[mid], x) > 0) hi = mid;else lo = mid + 1;
8893             }
8894
8895             return lo;
8896           }
8897
8898           function center(a, x, lo, hi) {
8899             if (lo == null) lo = 0;
8900             if (hi == null) hi = a.length;
8901             var i = left(a, x, lo, hi - 1);
8902             return i > lo && delta(a[i - 1], x) > -delta(a[i], x) ? i - 1 : i;
8903           }
8904
8905           return {
8906             left: left,
8907             center: center,
8908             right: right
8909           };
8910         }
8911
8912         function ascendingComparator(f) {
8913           return function (d, x) {
8914             return d3_ascending(f(d), x);
8915           };
8916         }
8917
8918         var defineWellKnownSymbol = defineWellKnownSymbol$4;
8919
8920         // `Symbol.asyncIterator` well-known symbol
8921         // https://tc39.es/ecma262/#sec-symbol.asynciterator
8922         defineWellKnownSymbol('asyncIterator');
8923
8924         var runtime = {exports: {}};
8925
8926         (function (module) {
8927           var runtime = function (exports) {
8928
8929             var Op = Object.prototype;
8930             var hasOwn = Op.hasOwnProperty;
8931             var undefined$1; // More compressible than void 0.
8932
8933             var $Symbol = typeof Symbol === "function" ? Symbol : {};
8934             var iteratorSymbol = $Symbol.iterator || "@@iterator";
8935             var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator";
8936             var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
8937
8938             function define(obj, key, value) {
8939               Object.defineProperty(obj, key, {
8940                 value: value,
8941                 enumerable: true,
8942                 configurable: true,
8943                 writable: true
8944               });
8945               return obj[key];
8946             }
8947
8948             try {
8949               // IE 8 has a broken Object.defineProperty that only works on DOM objects.
8950               define({}, "");
8951             } catch (err) {
8952               define = function define(obj, key, value) {
8953                 return obj[key] = value;
8954               };
8955             }
8956
8957             function wrap(innerFn, outerFn, self, tryLocsList) {
8958               // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator.
8959               var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;
8960               var generator = Object.create(protoGenerator.prototype);
8961               var context = new Context(tryLocsList || []); // The ._invoke method unifies the implementations of the .next,
8962               // .throw, and .return methods.
8963
8964               generator._invoke = makeInvokeMethod(innerFn, self, context);
8965               return generator;
8966             }
8967
8968             exports.wrap = wrap; // Try/catch helper to minimize deoptimizations. Returns a completion
8969             // record like context.tryEntries[i].completion. This interface could
8970             // have been (and was previously) designed to take a closure to be
8971             // invoked without arguments, but in all the cases we care about we
8972             // already have an existing method we want to call, so there's no need
8973             // to create a new function object. We can even get away with assuming
8974             // the method takes exactly one argument, since that happens to be true
8975             // in every case, so we don't have to touch the arguments object. The
8976             // only additional allocation required is the completion record, which
8977             // has a stable shape and so hopefully should be cheap to allocate.
8978
8979             function tryCatch(fn, obj, arg) {
8980               try {
8981                 return {
8982                   type: "normal",
8983                   arg: fn.call(obj, arg)
8984                 };
8985               } catch (err) {
8986                 return {
8987                   type: "throw",
8988                   arg: err
8989                 };
8990               }
8991             }
8992
8993             var GenStateSuspendedStart = "suspendedStart";
8994             var GenStateSuspendedYield = "suspendedYield";
8995             var GenStateExecuting = "executing";
8996             var GenStateCompleted = "completed"; // Returning this object from the innerFn has the same effect as
8997             // breaking out of the dispatch switch statement.
8998
8999             var ContinueSentinel = {}; // Dummy constructor functions that we use as the .constructor and
9000             // .constructor.prototype properties for functions that return Generator
9001             // objects. For full spec compliance, you may wish to configure your
9002             // minifier not to mangle the names of these two functions.
9003
9004             function Generator() {}
9005
9006             function GeneratorFunction() {}
9007
9008             function GeneratorFunctionPrototype() {} // This is a polyfill for %IteratorPrototype% for environments that
9009             // don't natively support it.
9010
9011
9012             var IteratorPrototype = {};
9013             define(IteratorPrototype, iteratorSymbol, function () {
9014               return this;
9015             });
9016             var getProto = Object.getPrototypeOf;
9017             var NativeIteratorPrototype = getProto && getProto(getProto(values([])));
9018
9019             if (NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {
9020               // This environment has a native %IteratorPrototype%; use it instead
9021               // of the polyfill.
9022               IteratorPrototype = NativeIteratorPrototype;
9023             }
9024
9025             var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);
9026             GeneratorFunction.prototype = GeneratorFunctionPrototype;
9027             define(Gp, "constructor", GeneratorFunctionPrototype);
9028             define(GeneratorFunctionPrototype, "constructor", GeneratorFunction);
9029             GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"); // Helper for defining the .next, .throw, and .return methods of the
9030             // Iterator interface in terms of a single ._invoke method.
9031
9032             function defineIteratorMethods(prototype) {
9033               ["next", "throw", "return"].forEach(function (method) {
9034                 define(prototype, method, function (arg) {
9035                   return this._invoke(method, arg);
9036                 });
9037               });
9038             }
9039
9040             exports.isGeneratorFunction = function (genFun) {
9041               var ctor = typeof genFun === "function" && genFun.constructor;
9042               return ctor ? ctor === GeneratorFunction || // For the native GeneratorFunction constructor, the best we can
9043               // do is to check its .name property.
9044               (ctor.displayName || ctor.name) === "GeneratorFunction" : false;
9045             };
9046
9047             exports.mark = function (genFun) {
9048               if (Object.setPrototypeOf) {
9049                 Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);
9050               } else {
9051                 genFun.__proto__ = GeneratorFunctionPrototype;
9052                 define(genFun, toStringTagSymbol, "GeneratorFunction");
9053               }
9054
9055               genFun.prototype = Object.create(Gp);
9056               return genFun;
9057             }; // Within the body of any async function, `await x` is transformed to
9058             // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test
9059             // `hasOwn.call(value, "__await")` to determine if the yielded value is
9060             // meant to be awaited.
9061
9062
9063             exports.awrap = function (arg) {
9064               return {
9065                 __await: arg
9066               };
9067             };
9068
9069             function AsyncIterator(generator, PromiseImpl) {
9070               function invoke(method, arg, resolve, reject) {
9071                 var record = tryCatch(generator[method], generator, arg);
9072
9073                 if (record.type === "throw") {
9074                   reject(record.arg);
9075                 } else {
9076                   var result = record.arg;
9077                   var value = result.value;
9078
9079                   if (value && _typeof(value) === "object" && hasOwn.call(value, "__await")) {
9080                     return PromiseImpl.resolve(value.__await).then(function (value) {
9081                       invoke("next", value, resolve, reject);
9082                     }, function (err) {
9083                       invoke("throw", err, resolve, reject);
9084                     });
9085                   }
9086
9087                   return PromiseImpl.resolve(value).then(function (unwrapped) {
9088                     // When a yielded Promise is resolved, its final value becomes
9089                     // the .value of the Promise<{value,done}> result for the
9090                     // current iteration.
9091                     result.value = unwrapped;
9092                     resolve(result);
9093                   }, function (error) {
9094                     // If a rejected Promise was yielded, throw the rejection back
9095                     // into the async generator function so it can be handled there.
9096                     return invoke("throw", error, resolve, reject);
9097                   });
9098                 }
9099               }
9100
9101               var previousPromise;
9102
9103               function enqueue(method, arg) {
9104                 function callInvokeWithMethodAndArg() {
9105                   return new PromiseImpl(function (resolve, reject) {
9106                     invoke(method, arg, resolve, reject);
9107                   });
9108                 }
9109
9110                 return previousPromise = // If enqueue has been called before, then we want to wait until
9111                 // all previous Promises have been resolved before calling invoke,
9112                 // so that results are always delivered in the correct order. If
9113                 // enqueue has not been called before, then it is important to
9114                 // call invoke immediately, without waiting on a callback to fire,
9115                 // so that the async generator function has the opportunity to do
9116                 // any necessary setup in a predictable way. This predictability
9117                 // is why the Promise constructor synchronously invokes its
9118                 // executor callback, and why async functions synchronously
9119                 // execute code before the first await. Since we implement simple
9120                 // async functions in terms of async generators, it is especially
9121                 // important to get this right, even though it requires care.
9122                 previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, // Avoid propagating failures to Promises returned by later
9123                 // invocations of the iterator.
9124                 callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
9125               } // Define the unified helper method that is used to implement .next,
9126               // .throw, and .return (see defineIteratorMethods).
9127
9128
9129               this._invoke = enqueue;
9130             }
9131
9132             defineIteratorMethods(AsyncIterator.prototype);
9133             define(AsyncIterator.prototype, asyncIteratorSymbol, function () {
9134               return this;
9135             });
9136             exports.AsyncIterator = AsyncIterator; // Note that simple async functions are implemented on top of
9137             // AsyncIterator objects; they just return a Promise for the value of
9138             // the final result produced by the iterator.
9139
9140             exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) {
9141               if (PromiseImpl === void 0) PromiseImpl = Promise;
9142               var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl);
9143               return exports.isGeneratorFunction(outerFn) ? iter // If outerFn is a generator, return the full iterator.
9144               : iter.next().then(function (result) {
9145                 return result.done ? result.value : iter.next();
9146               });
9147             };
9148
9149             function makeInvokeMethod(innerFn, self, context) {
9150               var state = GenStateSuspendedStart;
9151               return function invoke(method, arg) {
9152                 if (state === GenStateExecuting) {
9153                   throw new Error("Generator is already running");
9154                 }
9155
9156                 if (state === GenStateCompleted) {
9157                   if (method === "throw") {
9158                     throw arg;
9159                   } // Be forgiving, per 25.3.3.3.3 of the spec:
9160                   // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume
9161
9162
9163                   return doneResult();
9164                 }
9165
9166                 context.method = method;
9167                 context.arg = arg;
9168
9169                 while (true) {
9170                   var delegate = context.delegate;
9171
9172                   if (delegate) {
9173                     var delegateResult = maybeInvokeDelegate(delegate, context);
9174
9175                     if (delegateResult) {
9176                       if (delegateResult === ContinueSentinel) continue;
9177                       return delegateResult;
9178                     }
9179                   }
9180
9181                   if (context.method === "next") {
9182                     // Setting context._sent for legacy support of Babel's
9183                     // function.sent implementation.
9184                     context.sent = context._sent = context.arg;
9185                   } else if (context.method === "throw") {
9186                     if (state === GenStateSuspendedStart) {
9187                       state = GenStateCompleted;
9188                       throw context.arg;
9189                     }
9190
9191                     context.dispatchException(context.arg);
9192                   } else if (context.method === "return") {
9193                     context.abrupt("return", context.arg);
9194                   }
9195
9196                   state = GenStateExecuting;
9197                   var record = tryCatch(innerFn, self, context);
9198
9199                   if (record.type === "normal") {
9200                     // If an exception is thrown from innerFn, we leave state ===
9201                     // GenStateExecuting and loop back for another invocation.
9202                     state = context.done ? GenStateCompleted : GenStateSuspendedYield;
9203
9204                     if (record.arg === ContinueSentinel) {
9205                       continue;
9206                     }
9207
9208                     return {
9209                       value: record.arg,
9210                       done: context.done
9211                     };
9212                   } else if (record.type === "throw") {
9213                     state = GenStateCompleted; // Dispatch the exception by looping back around to the
9214                     // context.dispatchException(context.arg) call above.
9215
9216                     context.method = "throw";
9217                     context.arg = record.arg;
9218                   }
9219                 }
9220               };
9221             } // Call delegate.iterator[context.method](context.arg) and handle the
9222             // result, either by returning a { value, done } result from the
9223             // delegate iterator, or by modifying context.method and context.arg,
9224             // setting context.delegate to null, and returning the ContinueSentinel.
9225
9226
9227             function maybeInvokeDelegate(delegate, context) {
9228               var method = delegate.iterator[context.method];
9229
9230               if (method === undefined$1) {
9231                 // A .throw or .return when the delegate iterator has no .throw
9232                 // method always terminates the yield* loop.
9233                 context.delegate = null;
9234
9235                 if (context.method === "throw") {
9236                   // Note: ["return"] must be used for ES3 parsing compatibility.
9237                   if (delegate.iterator["return"]) {
9238                     // If the delegate iterator has a return method, give it a
9239                     // chance to clean up.
9240                     context.method = "return";
9241                     context.arg = undefined$1;
9242                     maybeInvokeDelegate(delegate, context);
9243
9244                     if (context.method === "throw") {
9245                       // If maybeInvokeDelegate(context) changed context.method from
9246                       // "return" to "throw", let that override the TypeError below.
9247                       return ContinueSentinel;
9248                     }
9249                   }
9250
9251                   context.method = "throw";
9252                   context.arg = new TypeError("The iterator does not provide a 'throw' method");
9253                 }
9254
9255                 return ContinueSentinel;
9256               }
9257
9258               var record = tryCatch(method, delegate.iterator, context.arg);
9259
9260               if (record.type === "throw") {
9261                 context.method = "throw";
9262                 context.arg = record.arg;
9263                 context.delegate = null;
9264                 return ContinueSentinel;
9265               }
9266
9267               var info = record.arg;
9268
9269               if (!info) {
9270                 context.method = "throw";
9271                 context.arg = new TypeError("iterator result is not an object");
9272                 context.delegate = null;
9273                 return ContinueSentinel;
9274               }
9275
9276               if (info.done) {
9277                 // Assign the result of the finished delegate to the temporary
9278                 // variable specified by delegate.resultName (see delegateYield).
9279                 context[delegate.resultName] = info.value; // Resume execution at the desired location (see delegateYield).
9280
9281                 context.next = delegate.nextLoc; // If context.method was "throw" but the delegate handled the
9282                 // exception, let the outer generator proceed normally. If
9283                 // context.method was "next", forget context.arg since it has been
9284                 // "consumed" by the delegate iterator. If context.method was
9285                 // "return", allow the original .return call to continue in the
9286                 // outer generator.
9287
9288                 if (context.method !== "return") {
9289                   context.method = "next";
9290                   context.arg = undefined$1;
9291                 }
9292               } else {
9293                 // Re-yield the result returned by the delegate method.
9294                 return info;
9295               } // The delegate iterator is finished, so forget it and continue with
9296               // the outer generator.
9297
9298
9299               context.delegate = null;
9300               return ContinueSentinel;
9301             } // Define Generator.prototype.{next,throw,return} in terms of the
9302             // unified ._invoke helper method.
9303
9304
9305             defineIteratorMethods(Gp);
9306             define(Gp, toStringTagSymbol, "Generator"); // A Generator should always return itself as the iterator object when the
9307             // @@iterator function is called on it. Some browsers' implementations of the
9308             // iterator prototype chain incorrectly implement this, causing the Generator
9309             // object to not be returned from this call. This ensures that doesn't happen.
9310             // See https://github.com/facebook/regenerator/issues/274 for more details.
9311
9312             define(Gp, iteratorSymbol, function () {
9313               return this;
9314             });
9315             define(Gp, "toString", function () {
9316               return "[object Generator]";
9317             });
9318
9319             function pushTryEntry(locs) {
9320               var entry = {
9321                 tryLoc: locs[0]
9322               };
9323
9324               if (1 in locs) {
9325                 entry.catchLoc = locs[1];
9326               }
9327
9328               if (2 in locs) {
9329                 entry.finallyLoc = locs[2];
9330                 entry.afterLoc = locs[3];
9331               }
9332
9333               this.tryEntries.push(entry);
9334             }
9335
9336             function resetTryEntry(entry) {
9337               var record = entry.completion || {};
9338               record.type = "normal";
9339               delete record.arg;
9340               entry.completion = record;
9341             }
9342
9343             function Context(tryLocsList) {
9344               // The root entry object (effectively a try statement without a catch
9345               // or a finally block) gives us a place to store values thrown from
9346               // locations where there is no enclosing try statement.
9347               this.tryEntries = [{
9348                 tryLoc: "root"
9349               }];
9350               tryLocsList.forEach(pushTryEntry, this);
9351               this.reset(true);
9352             }
9353
9354             exports.keys = function (object) {
9355               var keys = [];
9356
9357               for (var key in object) {
9358                 keys.push(key);
9359               }
9360
9361               keys.reverse(); // Rather than returning an object with a next method, we keep
9362               // things simple and return the next function itself.
9363
9364               return function next() {
9365                 while (keys.length) {
9366                   var key = keys.pop();
9367
9368                   if (key in object) {
9369                     next.value = key;
9370                     next.done = false;
9371                     return next;
9372                   }
9373                 } // To avoid creating an additional object, we just hang the .value
9374                 // and .done properties off the next function object itself. This
9375                 // also ensures that the minifier will not anonymize the function.
9376
9377
9378                 next.done = true;
9379                 return next;
9380               };
9381             };
9382
9383             function values(iterable) {
9384               if (iterable) {
9385                 var iteratorMethod = iterable[iteratorSymbol];
9386
9387                 if (iteratorMethod) {
9388                   return iteratorMethod.call(iterable);
9389                 }
9390
9391                 if (typeof iterable.next === "function") {
9392                   return iterable;
9393                 }
9394
9395                 if (!isNaN(iterable.length)) {
9396                   var i = -1,
9397                       next = function next() {
9398                     while (++i < iterable.length) {
9399                       if (hasOwn.call(iterable, i)) {
9400                         next.value = iterable[i];
9401                         next.done = false;
9402                         return next;
9403                       }
9404                     }
9405
9406                     next.value = undefined$1;
9407                     next.done = true;
9408                     return next;
9409                   };
9410
9411                   return next.next = next;
9412                 }
9413               } // Return an iterator with no values.
9414
9415
9416               return {
9417                 next: doneResult
9418               };
9419             }
9420
9421             exports.values = values;
9422
9423             function doneResult() {
9424               return {
9425                 value: undefined$1,
9426                 done: true
9427               };
9428             }
9429
9430             Context.prototype = {
9431               constructor: Context,
9432               reset: function reset(skipTempReset) {
9433                 this.prev = 0;
9434                 this.next = 0; // Resetting context._sent for legacy support of Babel's
9435                 // function.sent implementation.
9436
9437                 this.sent = this._sent = undefined$1;
9438                 this.done = false;
9439                 this.delegate = null;
9440                 this.method = "next";
9441                 this.arg = undefined$1;
9442                 this.tryEntries.forEach(resetTryEntry);
9443
9444                 if (!skipTempReset) {
9445                   for (var name in this) {
9446                     // Not sure about the optimal order of these conditions:
9447                     if (name.charAt(0) === "t" && hasOwn.call(this, name) && !isNaN(+name.slice(1))) {
9448                       this[name] = undefined$1;
9449                     }
9450                   }
9451                 }
9452               },
9453               stop: function stop() {
9454                 this.done = true;
9455                 var rootEntry = this.tryEntries[0];
9456                 var rootRecord = rootEntry.completion;
9457
9458                 if (rootRecord.type === "throw") {
9459                   throw rootRecord.arg;
9460                 }
9461
9462                 return this.rval;
9463               },
9464               dispatchException: function dispatchException(exception) {
9465                 if (this.done) {
9466                   throw exception;
9467                 }
9468
9469                 var context = this;
9470
9471                 function handle(loc, caught) {
9472                   record.type = "throw";
9473                   record.arg = exception;
9474                   context.next = loc;
9475
9476                   if (caught) {
9477                     // If the dispatched exception was caught by a catch block,
9478                     // then let that catch block handle the exception normally.
9479                     context.method = "next";
9480                     context.arg = undefined$1;
9481                   }
9482
9483                   return !!caught;
9484                 }
9485
9486                 for (var i = this.tryEntries.length - 1; i >= 0; --i) {
9487                   var entry = this.tryEntries[i];
9488                   var record = entry.completion;
9489
9490                   if (entry.tryLoc === "root") {
9491                     // Exception thrown outside of any try block that could handle
9492                     // it, so set the completion value of the entire function to
9493                     // throw the exception.
9494                     return handle("end");
9495                   }
9496
9497                   if (entry.tryLoc <= this.prev) {
9498                     var hasCatch = hasOwn.call(entry, "catchLoc");
9499                     var hasFinally = hasOwn.call(entry, "finallyLoc");
9500
9501                     if (hasCatch && hasFinally) {
9502                       if (this.prev < entry.catchLoc) {
9503                         return handle(entry.catchLoc, true);
9504                       } else if (this.prev < entry.finallyLoc) {
9505                         return handle(entry.finallyLoc);
9506                       }
9507                     } else if (hasCatch) {
9508                       if (this.prev < entry.catchLoc) {
9509                         return handle(entry.catchLoc, true);
9510                       }
9511                     } else if (hasFinally) {
9512                       if (this.prev < entry.finallyLoc) {
9513                         return handle(entry.finallyLoc);
9514                       }
9515                     } else {
9516                       throw new Error("try statement without catch or finally");
9517                     }
9518                   }
9519                 }
9520               },
9521               abrupt: function abrupt(type, arg) {
9522                 for (var i = this.tryEntries.length - 1; i >= 0; --i) {
9523                   var entry = this.tryEntries[i];
9524
9525                   if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
9526                     var finallyEntry = entry;
9527                     break;
9528                   }
9529                 }
9530
9531                 if (finallyEntry && (type === "break" || type === "continue") && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc) {
9532                   // Ignore the finally entry if control is not jumping to a
9533                   // location outside the try/catch block.
9534                   finallyEntry = null;
9535                 }
9536
9537                 var record = finallyEntry ? finallyEntry.completion : {};
9538                 record.type = type;
9539                 record.arg = arg;
9540
9541                 if (finallyEntry) {
9542                   this.method = "next";
9543                   this.next = finallyEntry.finallyLoc;
9544                   return ContinueSentinel;
9545                 }
9546
9547                 return this.complete(record);
9548               },
9549               complete: function complete(record, afterLoc) {
9550                 if (record.type === "throw") {
9551                   throw record.arg;
9552                 }
9553
9554                 if (record.type === "break" || record.type === "continue") {
9555                   this.next = record.arg;
9556                 } else if (record.type === "return") {
9557                   this.rval = this.arg = record.arg;
9558                   this.method = "return";
9559                   this.next = "end";
9560                 } else if (record.type === "normal" && afterLoc) {
9561                   this.next = afterLoc;
9562                 }
9563
9564                 return ContinueSentinel;
9565               },
9566               finish: function finish(finallyLoc) {
9567                 for (var i = this.tryEntries.length - 1; i >= 0; --i) {
9568                   var entry = this.tryEntries[i];
9569
9570                   if (entry.finallyLoc === finallyLoc) {
9571                     this.complete(entry.completion, entry.afterLoc);
9572                     resetTryEntry(entry);
9573                     return ContinueSentinel;
9574                   }
9575                 }
9576               },
9577               "catch": function _catch(tryLoc) {
9578                 for (var i = this.tryEntries.length - 1; i >= 0; --i) {
9579                   var entry = this.tryEntries[i];
9580
9581                   if (entry.tryLoc === tryLoc) {
9582                     var record = entry.completion;
9583
9584                     if (record.type === "throw") {
9585                       var thrown = record.arg;
9586                       resetTryEntry(entry);
9587                     }
9588
9589                     return thrown;
9590                   }
9591                 } // The context.catch method must only be called with a location
9592                 // argument that corresponds to a known catch block.
9593
9594
9595                 throw new Error("illegal catch attempt");
9596               },
9597               delegateYield: function delegateYield(iterable, resultName, nextLoc) {
9598                 this.delegate = {
9599                   iterator: values(iterable),
9600                   resultName: resultName,
9601                   nextLoc: nextLoc
9602                 };
9603
9604                 if (this.method === "next") {
9605                   // Deliberately forget the last sent value so that we don't
9606                   // accidentally pass it on to the delegate.
9607                   this.arg = undefined$1;
9608                 }
9609
9610                 return ContinueSentinel;
9611               }
9612             }; // Regardless of whether this script is executing as a CommonJS module
9613             // or not, return the runtime object so that we can declare the variable
9614             // regeneratorRuntime in the outer scope, which allows this module to be
9615             // injected easily by `bin/regenerator --include-runtime script.js`.
9616
9617             return exports;
9618           }( // If this script is executing as a CommonJS module, use module.exports
9619           // as the regeneratorRuntime namespace. Otherwise create a new empty
9620           // object. Either way, the resulting object will be used to initialize
9621           // the regeneratorRuntime variable at the top of this file.
9622           module.exports );
9623
9624           try {
9625             regeneratorRuntime = runtime;
9626           } catch (accidentalStrictMode) {
9627             // This module should not be running in strict mode, so the above
9628             // assignment should always work unless something is misconfigured. Just
9629             // in case runtime.js accidentally runs in strict mode, in modern engines
9630             // we can explicitly access globalThis. In older engines we can escape
9631             // strict mode using a global Function call. This could conceivably fail
9632             // if a Content Security Policy forbids using Function, but in that case
9633             // the proper solution is to fix the accidental strict mode problem. If
9634             // you've misconfigured your bundler to force strict mode and applied a
9635             // CSP to forbid Function, and you're not willing to fix either of those
9636             // problems, please detail your unique predicament in a GitHub issue.
9637             if ((typeof globalThis === "undefined" ? "undefined" : _typeof(globalThis)) === "object") {
9638               globalThis.regeneratorRuntime = runtime;
9639             } else {
9640               Function("r", "regeneratorRuntime = r")(runtime);
9641             }
9642           }
9643         })(runtime);
9644
9645         var _marked$3 = /*#__PURE__*/regeneratorRuntime.mark(numbers);
9646
9647         function number$1 (x) {
9648           return x === null ? NaN : +x;
9649         }
9650         function numbers(values, valueof) {
9651           var _iterator, _step, value, index, _iterator2, _step2, _value;
9652
9653           return regeneratorRuntime.wrap(function numbers$(_context) {
9654             while (1) {
9655               switch (_context.prev = _context.next) {
9656                 case 0:
9657                   if (!(valueof === undefined)) {
9658                     _context.next = 21;
9659                     break;
9660                   }
9661
9662                   _iterator = _createForOfIteratorHelper(values);
9663                   _context.prev = 2;
9664
9665                   _iterator.s();
9666
9667                 case 4:
9668                   if ((_step = _iterator.n()).done) {
9669                     _context.next = 11;
9670                     break;
9671                   }
9672
9673                   value = _step.value;
9674
9675                   if (!(value != null && (value = +value) >= value)) {
9676                     _context.next = 9;
9677                     break;
9678                   }
9679
9680                   _context.next = 9;
9681                   return value;
9682
9683                 case 9:
9684                   _context.next = 4;
9685                   break;
9686
9687                 case 11:
9688                   _context.next = 16;
9689                   break;
9690
9691                 case 13:
9692                   _context.prev = 13;
9693                   _context.t0 = _context["catch"](2);
9694
9695                   _iterator.e(_context.t0);
9696
9697                 case 16:
9698                   _context.prev = 16;
9699
9700                   _iterator.f();
9701
9702                   return _context.finish(16);
9703
9704                 case 19:
9705                   _context.next = 40;
9706                   break;
9707
9708                 case 21:
9709                   index = -1;
9710                   _iterator2 = _createForOfIteratorHelper(values);
9711                   _context.prev = 23;
9712
9713                   _iterator2.s();
9714
9715                 case 25:
9716                   if ((_step2 = _iterator2.n()).done) {
9717                     _context.next = 32;
9718                     break;
9719                   }
9720
9721                   _value = _step2.value;
9722
9723                   if (!((_value = valueof(_value, ++index, values)) != null && (_value = +_value) >= _value)) {
9724                     _context.next = 30;
9725                     break;
9726                   }
9727
9728                   _context.next = 30;
9729                   return _value;
9730
9731                 case 30:
9732                   _context.next = 25;
9733                   break;
9734
9735                 case 32:
9736                   _context.next = 37;
9737                   break;
9738
9739                 case 34:
9740                   _context.prev = 34;
9741                   _context.t1 = _context["catch"](23);
9742
9743                   _iterator2.e(_context.t1);
9744
9745                 case 37:
9746                   _context.prev = 37;
9747
9748                   _iterator2.f();
9749
9750                   return _context.finish(37);
9751
9752                 case 40:
9753                 case "end":
9754                   return _context.stop();
9755               }
9756             }
9757           }, _marked$3, null, [[2, 13, 16, 19], [23, 34, 37, 40]]);
9758         }
9759
9760         var ascendingBisect = d3_bisector(d3_ascending);
9761         var bisectRight = ascendingBisect.right;
9762         d3_bisector(number$1).center;
9763
9764         var anObject$2 = anObject$n;
9765         var iteratorClose = iteratorClose$2;
9766
9767         // call something on iterator step with safe closing on error
9768         var callWithSafeIterationClosing$1 = function (iterator, fn, value, ENTRIES) {
9769           try {
9770             return ENTRIES ? fn(anObject$2(value)[0], value[1]) : fn(value);
9771           } catch (error) {
9772             iteratorClose(iterator, 'throw', error);
9773           }
9774         };
9775
9776         var global$c = global$1m;
9777         var bind$5 = functionBindContext;
9778         var call$4 = functionCall;
9779         var toObject$3 = toObject$j;
9780         var callWithSafeIterationClosing = callWithSafeIterationClosing$1;
9781         var isArrayIteratorMethod = isArrayIteratorMethod$3;
9782         var isConstructor = isConstructor$4;
9783         var lengthOfArrayLike$3 = lengthOfArrayLike$g;
9784         var createProperty = createProperty$4;
9785         var getIterator = getIterator$4;
9786         var getIteratorMethod = getIteratorMethod$5;
9787
9788         var Array$1 = global$c.Array;
9789
9790         // `Array.from` method implementation
9791         // https://tc39.es/ecma262/#sec-array.from
9792         var arrayFrom$1 = function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) {
9793           var O = toObject$3(arrayLike);
9794           var IS_CONSTRUCTOR = isConstructor(this);
9795           var argumentsLength = arguments.length;
9796           var mapfn = argumentsLength > 1 ? arguments[1] : undefined;
9797           var mapping = mapfn !== undefined;
9798           if (mapping) mapfn = bind$5(mapfn, argumentsLength > 2 ? arguments[2] : undefined);
9799           var iteratorMethod = getIteratorMethod(O);
9800           var index = 0;
9801           var length, result, step, iterator, next, value;
9802           // if the target is not iterable or it's an array with the default iterator - use a simple case
9803           if (iteratorMethod && !(this == Array$1 && isArrayIteratorMethod(iteratorMethod))) {
9804             iterator = getIterator(O, iteratorMethod);
9805             next = iterator.next;
9806             result = IS_CONSTRUCTOR ? new this() : [];
9807             for (;!(step = call$4(next, iterator)).done; index++) {
9808               value = mapping ? callWithSafeIterationClosing(iterator, mapfn, [step.value, index], true) : step.value;
9809               createProperty(result, index, value);
9810             }
9811           } else {
9812             length = lengthOfArrayLike$3(O);
9813             result = IS_CONSTRUCTOR ? new this(length) : Array$1(length);
9814             for (;length > index; index++) {
9815               value = mapping ? mapfn(O[index], index) : O[index];
9816               createProperty(result, index, value);
9817             }
9818           }
9819           result.length = index;
9820           return result;
9821         };
9822
9823         var $$D = _export;
9824         var from = arrayFrom$1;
9825         var checkCorrectnessOfIteration = checkCorrectnessOfIteration$4;
9826
9827         var INCORRECT_ITERATION = !checkCorrectnessOfIteration(function (iterable) {
9828           // eslint-disable-next-line es/no-array-from -- required for testing
9829           Array.from(iterable);
9830         });
9831
9832         // `Array.from` method
9833         // https://tc39.es/ecma262/#sec-array.from
9834         $$D({ target: 'Array', stat: true, forced: INCORRECT_ITERATION }, {
9835           from: from
9836         });
9837
9838         var $$C = _export;
9839         var fill = arrayFill$1;
9840         var addToUnscopables$4 = addToUnscopables$6;
9841
9842         // `Array.prototype.fill` method
9843         // https://tc39.es/ecma262/#sec-array.prototype.fill
9844         $$C({ target: 'Array', proto: true }, {
9845           fill: fill
9846         });
9847
9848         // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
9849         addToUnscopables$4('fill');
9850
9851         var $$B = _export;
9852         var $some = arrayIteration.some;
9853         var arrayMethodIsStrict$4 = arrayMethodIsStrict$9;
9854
9855         var STRICT_METHOD$4 = arrayMethodIsStrict$4('some');
9856
9857         // `Array.prototype.some` method
9858         // https://tc39.es/ecma262/#sec-array.prototype.some
9859         $$B({ target: 'Array', proto: true, forced: !STRICT_METHOD$4 }, {
9860           some: function some(callbackfn /* , thisArg */) {
9861             return $some(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
9862           }
9863         });
9864
9865         var TYPED_ARRAYS_CONSTRUCTORS_REQUIRES_WRAPPERS = typedArrayConstructorsRequireWrappers;
9866         var exportTypedArrayStaticMethod = arrayBufferViewCore.exportTypedArrayStaticMethod;
9867         var typedArrayFrom = typedArrayFrom$2;
9868
9869         // `%TypedArray%.from` method
9870         // https://tc39.es/ecma262/#sec-%typedarray%.from
9871         exportTypedArrayStaticMethod('from', typedArrayFrom, TYPED_ARRAYS_CONSTRUCTORS_REQUIRES_WRAPPERS);
9872
9873         var createTypedArrayConstructor = typedArrayConstructor.exports;
9874
9875         // `Float64Array` constructor
9876         // https://tc39.es/ecma262/#sec-typedarray-objects
9877         createTypedArrayConstructor('Float64', function (init) {
9878           return function Float64Array(data, byteOffset, length) {
9879             return init(this, data, byteOffset, length);
9880           };
9881         });
9882
9883         function d3_descending (a, b) {
9884           return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
9885         }
9886
9887         // https://github.com/python/cpython/blob/a74eea238f5baba15797e2e8b570d153bc8690a7/Modules/mathmodule.c#L1423
9888         var Adder = /*#__PURE__*/function () {
9889           function Adder() {
9890             _classCallCheck$1(this, Adder);
9891
9892             this._partials = new Float64Array(32);
9893             this._n = 0;
9894           }
9895
9896           _createClass$1(Adder, [{
9897             key: "add",
9898             value: function add(x) {
9899               var p = this._partials;
9900               var i = 0;
9901
9902               for (var j = 0; j < this._n && j < 32; j++) {
9903                 var y = p[j],
9904                     hi = x + y,
9905                     lo = Math.abs(x) < Math.abs(y) ? x - (hi - y) : y - (hi - x);
9906                 if (lo) p[i++] = lo;
9907                 x = hi;
9908               }
9909
9910               p[i] = x;
9911               this._n = i + 1;
9912               return this;
9913             }
9914           }, {
9915             key: "valueOf",
9916             value: function valueOf() {
9917               var p = this._partials;
9918               var n = this._n,
9919                   x,
9920                   y,
9921                   lo,
9922                   hi = 0;
9923
9924               if (n > 0) {
9925                 hi = p[--n];
9926
9927                 while (n > 0) {
9928                   x = hi;
9929                   y = p[--n];
9930                   hi = x + y;
9931                   lo = y - (hi - x);
9932                   if (lo) break;
9933                 }
9934
9935                 if (n > 0 && (lo < 0 && p[n - 1] < 0 || lo > 0 && p[n - 1] > 0)) {
9936                   y = lo * 2;
9937                   x = hi + y;
9938                   if (y == x - hi) hi = x;
9939                 }
9940               }
9941
9942               return hi;
9943             }
9944           }]);
9945
9946           return Adder;
9947         }();
9948
9949         var $$A = _export;
9950         var DESCRIPTORS$5 = descriptors;
9951         var defineProperties$1 = objectDefineProperties;
9952
9953         // `Object.defineProperties` method
9954         // https://tc39.es/ecma262/#sec-object.defineproperties
9955         $$A({ target: 'Object', stat: true, forced: !DESCRIPTORS$5, sham: !DESCRIPTORS$5 }, {
9956           defineProperties: defineProperties$1
9957         });
9958
9959         var collection = collection$2;
9960         var collectionStrong = collectionStrong$2;
9961
9962         // `Map` constructor
9963         // https://tc39.es/ecma262/#sec-map-objects
9964         collection('Map', function (init) {
9965           return function Map() { return init(this, arguments.length ? arguments[0] : undefined); };
9966         }, collectionStrong);
9967
9968         var $$z = _export;
9969         var uncurryThis$f = functionUncurryThis;
9970         var aCallable$1 = aCallable$a;
9971         var toObject$2 = toObject$j;
9972         var lengthOfArrayLike$2 = lengthOfArrayLike$g;
9973         var toString$a = toString$k;
9974         var fails$b = fails$S;
9975         var internalSort = arraySort$1;
9976         var arrayMethodIsStrict$3 = arrayMethodIsStrict$9;
9977         var FF = engineFfVersion;
9978         var IE_OR_EDGE = engineIsIeOrEdge;
9979         var V8 = engineV8Version;
9980         var WEBKIT = engineWebkitVersion;
9981
9982         var test = [];
9983         var un$Sort = uncurryThis$f(test.sort);
9984         var push$3 = uncurryThis$f(test.push);
9985
9986         // IE8-
9987         var FAILS_ON_UNDEFINED = fails$b(function () {
9988           test.sort(undefined);
9989         });
9990         // V8 bug
9991         var FAILS_ON_NULL = fails$b(function () {
9992           test.sort(null);
9993         });
9994         // Old WebKit
9995         var STRICT_METHOD$3 = arrayMethodIsStrict$3('sort');
9996
9997         var STABLE_SORT = !fails$b(function () {
9998           // feature detection can be too slow, so check engines versions
9999           if (V8) return V8 < 70;
10000           if (FF && FF > 3) return;
10001           if (IE_OR_EDGE) return true;
10002           if (WEBKIT) return WEBKIT < 603;
10003
10004           var result = '';
10005           var code, chr, value, index;
10006
10007           // generate an array with more 512 elements (Chakra and old V8 fails only in this case)
10008           for (code = 65; code < 76; code++) {
10009             chr = String.fromCharCode(code);
10010
10011             switch (code) {
10012               case 66: case 69: case 70: case 72: value = 3; break;
10013               case 68: case 71: value = 4; break;
10014               default: value = 2;
10015             }
10016
10017             for (index = 0; index < 47; index++) {
10018               test.push({ k: chr + index, v: value });
10019             }
10020           }
10021
10022           test.sort(function (a, b) { return b.v - a.v; });
10023
10024           for (index = 0; index < test.length; index++) {
10025             chr = test[index].k.charAt(0);
10026             if (result.charAt(result.length - 1) !== chr) result += chr;
10027           }
10028
10029           return result !== 'DGBEFHACIJK';
10030         });
10031
10032         var FORCED$7 = FAILS_ON_UNDEFINED || !FAILS_ON_NULL || !STRICT_METHOD$3 || !STABLE_SORT;
10033
10034         var getSortCompare = function (comparefn) {
10035           return function (x, y) {
10036             if (y === undefined) return -1;
10037             if (x === undefined) return 1;
10038             if (comparefn !== undefined) return +comparefn(x, y) || 0;
10039             return toString$a(x) > toString$a(y) ? 1 : -1;
10040           };
10041         };
10042
10043         // `Array.prototype.sort` method
10044         // https://tc39.es/ecma262/#sec-array.prototype.sort
10045         $$z({ target: 'Array', proto: true, forced: FORCED$7 }, {
10046           sort: function sort(comparefn) {
10047             if (comparefn !== undefined) aCallable$1(comparefn);
10048
10049             var array = toObject$2(this);
10050
10051             if (STABLE_SORT) return comparefn === undefined ? un$Sort(array) : un$Sort(array, comparefn);
10052
10053             var items = [];
10054             var arrayLength = lengthOfArrayLike$2(array);
10055             var itemsLength, index;
10056
10057             for (index = 0; index < arrayLength; index++) {
10058               if (index in array) push$3(items, array[index]);
10059             }
10060
10061             internalSort(items, getSortCompare(comparefn));
10062
10063             itemsLength = items.length;
10064             index = 0;
10065
10066             while (index < itemsLength) array[index] = items[index++];
10067             while (index < arrayLength) delete array[index++];
10068
10069             return array;
10070           }
10071         });
10072
10073         var e10 = Math.sqrt(50),
10074             e5 = Math.sqrt(10),
10075             e2 = Math.sqrt(2);
10076         function ticks (start, stop, count) {
10077           var reverse,
10078               i = -1,
10079               n,
10080               ticks,
10081               step;
10082           stop = +stop, start = +start, count = +count;
10083           if (start === stop && count > 0) return [start];
10084           if (reverse = stop < start) n = start, start = stop, stop = n;
10085           if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) return [];
10086
10087           if (step > 0) {
10088             var r0 = Math.round(start / step),
10089                 r1 = Math.round(stop / step);
10090             if (r0 * step < start) ++r0;
10091             if (r1 * step > stop) --r1;
10092             ticks = new Array(n = r1 - r0 + 1);
10093
10094             while (++i < n) {
10095               ticks[i] = (r0 + i) * step;
10096             }
10097           } else {
10098             step = -step;
10099
10100             var _r = Math.round(start * step),
10101                 _r2 = Math.round(stop * step);
10102
10103             if (_r / step < start) ++_r;
10104             if (_r2 / step > stop) --_r2;
10105             ticks = new Array(n = _r2 - _r + 1);
10106
10107             while (++i < n) {
10108               ticks[i] = (_r + i) / step;
10109             }
10110           }
10111
10112           if (reverse) ticks.reverse();
10113           return ticks;
10114         }
10115         function tickIncrement(start, stop, count) {
10116           var step = (stop - start) / Math.max(0, count),
10117               power = Math.floor(Math.log(step) / Math.LN10),
10118               error = step / Math.pow(10, power);
10119           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);
10120         }
10121         function tickStep(start, stop, count) {
10122           var step0 = Math.abs(stop - start) / Math.max(0, count),
10123               step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)),
10124               error = step0 / step1;
10125           if (error >= e10) step1 *= 10;else if (error >= e5) step1 *= 5;else if (error >= e2) step1 *= 2;
10126           return stop < start ? -step1 : step1;
10127         }
10128
10129         function max(values, valueof) {
10130           var max;
10131
10132           if (valueof === undefined) {
10133             var _iterator = _createForOfIteratorHelper(values),
10134                 _step;
10135
10136             try {
10137               for (_iterator.s(); !(_step = _iterator.n()).done;) {
10138                 var value = _step.value;
10139
10140                 if (value != null && (max < value || max === undefined && value >= value)) {
10141                   max = value;
10142                 }
10143               }
10144             } catch (err) {
10145               _iterator.e(err);
10146             } finally {
10147               _iterator.f();
10148             }
10149           } else {
10150             var index = -1;
10151
10152             var _iterator2 = _createForOfIteratorHelper(values),
10153                 _step2;
10154
10155             try {
10156               for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
10157                 var _value = _step2.value;
10158
10159                 if ((_value = valueof(_value, ++index, values)) != null && (max < _value || max === undefined && _value >= _value)) {
10160                   max = _value;
10161                 }
10162               }
10163             } catch (err) {
10164               _iterator2.e(err);
10165             } finally {
10166               _iterator2.f();
10167             }
10168           }
10169
10170           return max;
10171         }
10172
10173         function min$2(values, valueof) {
10174           var min;
10175
10176           if (valueof === undefined) {
10177             var _iterator = _createForOfIteratorHelper(values),
10178                 _step;
10179
10180             try {
10181               for (_iterator.s(); !(_step = _iterator.n()).done;) {
10182                 var value = _step.value;
10183
10184                 if (value != null && (min > value || min === undefined && value >= value)) {
10185                   min = value;
10186                 }
10187               }
10188             } catch (err) {
10189               _iterator.e(err);
10190             } finally {
10191               _iterator.f();
10192             }
10193           } else {
10194             var index = -1;
10195
10196             var _iterator2 = _createForOfIteratorHelper(values),
10197                 _step2;
10198
10199             try {
10200               for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
10201                 var _value = _step2.value;
10202
10203                 if ((_value = valueof(_value, ++index, values)) != null && (min > _value || min === undefined && _value >= _value)) {
10204                   min = _value;
10205                 }
10206               }
10207             } catch (err) {
10208               _iterator2.e(err);
10209             } finally {
10210               _iterator2.f();
10211             }
10212           }
10213
10214           return min;
10215         }
10216
10217         // ISC license, Copyright 2018 Vladimir Agafonkin.
10218
10219         function quickselect$3(array, k) {
10220           var left = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
10221           var right = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : array.length - 1;
10222           var compare = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : d3_ascending;
10223
10224           while (right > left) {
10225             if (right - left > 600) {
10226               var n = right - left + 1;
10227               var m = k - left + 1;
10228               var z = Math.log(n);
10229               var s = 0.5 * Math.exp(2 * z / 3);
10230               var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
10231               var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
10232               var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
10233               quickselect$3(array, k, newLeft, newRight, compare);
10234             }
10235
10236             var t = array[k];
10237             var i = left;
10238             var j = right;
10239             swap$1(array, left, k);
10240             if (compare(array[right], t) > 0) swap$1(array, left, right);
10241
10242             while (i < j) {
10243               swap$1(array, i, j), ++i, --j;
10244
10245               while (compare(array[i], t) < 0) {
10246                 ++i;
10247               }
10248
10249               while (compare(array[j], t) > 0) {
10250                 --j;
10251               }
10252             }
10253
10254             if (compare(array[left], t) === 0) swap$1(array, left, j);else ++j, swap$1(array, j, right);
10255             if (j <= k) left = j + 1;
10256             if (k <= j) right = j - 1;
10257           }
10258
10259           return array;
10260         }
10261
10262         function swap$1(array, i, j) {
10263           var t = array[i];
10264           array[i] = array[j];
10265           array[j] = t;
10266         }
10267
10268         function quantile(values, p, valueof) {
10269           values = Float64Array.from(numbers(values, valueof));
10270           if (!(n = values.length)) return;
10271           if ((p = +p) <= 0 || n < 2) return min$2(values);
10272           if (p >= 1) return max(values);
10273           var n,
10274               i = (n - 1) * p,
10275               i0 = Math.floor(i),
10276               value0 = max(quickselect$3(values, i0).subarray(0, i0 + 1)),
10277               value1 = min$2(values.subarray(i0 + 1));
10278           return value0 + (value1 - value0) * (i - i0);
10279         }
10280
10281         function d3_median (values, valueof) {
10282           return quantile(values, 0.5, valueof);
10283         }
10284
10285         var _marked$2 = /*#__PURE__*/regeneratorRuntime.mark(flatten);
10286
10287         function flatten(arrays) {
10288           var _iterator, _step, array;
10289
10290           return regeneratorRuntime.wrap(function flatten$(_context) {
10291             while (1) {
10292               switch (_context.prev = _context.next) {
10293                 case 0:
10294                   _iterator = _createForOfIteratorHelper(arrays);
10295                   _context.prev = 1;
10296
10297                   _iterator.s();
10298
10299                 case 3:
10300                   if ((_step = _iterator.n()).done) {
10301                     _context.next = 8;
10302                     break;
10303                   }
10304
10305                   array = _step.value;
10306                   return _context.delegateYield(array, "t0", 6);
10307
10308                 case 6:
10309                   _context.next = 3;
10310                   break;
10311
10312                 case 8:
10313                   _context.next = 13;
10314                   break;
10315
10316                 case 10:
10317                   _context.prev = 10;
10318                   _context.t1 = _context["catch"](1);
10319
10320                   _iterator.e(_context.t1);
10321
10322                 case 13:
10323                   _context.prev = 13;
10324
10325                   _iterator.f();
10326
10327                   return _context.finish(13);
10328
10329                 case 16:
10330                 case "end":
10331                   return _context.stop();
10332               }
10333             }
10334           }, _marked$2, null, [[1, 10, 13, 16]]);
10335         }
10336
10337         function merge$4(arrays) {
10338           return Array.from(flatten(arrays));
10339         }
10340
10341         function range$1 (start, stop, step) {
10342           start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step;
10343           var i = -1,
10344               n = Math.max(0, Math.ceil((stop - start) / step)) | 0,
10345               range = new Array(n);
10346
10347           while (++i < n) {
10348             range[i] = start + i * step;
10349           }
10350
10351           return range;
10352         }
10353
10354         // `SameValue` abstract operation
10355         // https://tc39.es/ecma262/#sec-samevalue
10356         // eslint-disable-next-line es/no-object-is -- safe
10357         var sameValue$1 = Object.is || function is(x, y) {
10358           // eslint-disable-next-line no-self-compare -- NaN check
10359           return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y;
10360         };
10361
10362         var $$y = _export;
10363
10364         // eslint-disable-next-line es/no-math-hypot -- required for testing
10365         var $hypot = Math.hypot;
10366         var abs$3 = Math.abs;
10367         var sqrt$1 = Math.sqrt;
10368
10369         // Chrome 77 bug
10370         // https://bugs.chromium.org/p/v8/issues/detail?id=9546
10371         var BUGGY = !!$hypot && $hypot(Infinity, NaN) !== Infinity;
10372
10373         // `Math.hypot` method
10374         // https://tc39.es/ecma262/#sec-math.hypot
10375         $$y({ target: 'Math', stat: true, forced: BUGGY }, {
10376           // eslint-disable-next-line no-unused-vars -- required for `.length`
10377           hypot: function hypot(value1, value2) {
10378             var sum = 0;
10379             var i = 0;
10380             var aLen = arguments.length;
10381             var larg = 0;
10382             var arg, div;
10383             while (i < aLen) {
10384               arg = abs$3(arguments[i++]);
10385               if (larg < arg) {
10386                 div = larg / arg;
10387                 sum = sum * div * div + 1;
10388                 larg = arg;
10389               } else if (arg > 0) {
10390                 div = arg / larg;
10391                 sum += div * div;
10392               } else sum += arg;
10393             }
10394             return larg === Infinity ? Infinity : larg * sqrt$1(sum);
10395           }
10396         });
10397
10398         // `Math.sign` method implementation
10399         // https://tc39.es/ecma262/#sec-math.sign
10400         // eslint-disable-next-line es/no-math-sign -- safe
10401         var mathSign = Math.sign || function sign(x) {
10402           // eslint-disable-next-line no-self-compare -- NaN check
10403           return (x = +x) == 0 || x != x ? x : x < 0 ? -1 : 1;
10404         };
10405
10406         var $$x = _export;
10407         var sign$1 = mathSign;
10408
10409         // `Math.sign` method
10410         // https://tc39.es/ecma262/#sec-math.sign
10411         $$x({ target: 'Math', stat: true }, {
10412           sign: sign$1
10413         });
10414
10415         var epsilon$1 = 1e-6;
10416         var epsilon2$1 = 1e-12;
10417         var pi = Math.PI;
10418         var halfPi = pi / 2;
10419         var quarterPi = pi / 4;
10420         var tau = pi * 2;
10421         var degrees$1 = 180 / pi;
10422         var radians = pi / 180;
10423         var abs$2 = Math.abs;
10424         var atan = Math.atan;
10425         var atan2 = Math.atan2;
10426         var cos = Math.cos;
10427         var exp$2 = Math.exp;
10428         var log$1 = Math.log;
10429         var sin = Math.sin;
10430         var sign = Math.sign || function (x) {
10431           return x > 0 ? 1 : x < 0 ? -1 : 0;
10432         };
10433         var sqrt = Math.sqrt;
10434         var tan = Math.tan;
10435         function acos(x) {
10436           return x > 1 ? 0 : x < -1 ? pi : Math.acos(x);
10437         }
10438         function asin(x) {
10439           return x > 1 ? halfPi : x < -1 ? -halfPi : Math.asin(x);
10440         }
10441
10442         function noop$1() {}
10443
10444         function streamGeometry(geometry, stream) {
10445           if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) {
10446             streamGeometryType[geometry.type](geometry, stream);
10447           }
10448         }
10449
10450         var streamObjectType = {
10451           Feature: function Feature(object, stream) {
10452             streamGeometry(object.geometry, stream);
10453           },
10454           FeatureCollection: function FeatureCollection(object, stream) {
10455             var features = object.features,
10456                 i = -1,
10457                 n = features.length;
10458
10459             while (++i < n) {
10460               streamGeometry(features[i].geometry, stream);
10461             }
10462           }
10463         };
10464         var streamGeometryType = {
10465           Sphere: function Sphere(object, stream) {
10466             stream.sphere();
10467           },
10468           Point: function Point(object, stream) {
10469             object = object.coordinates;
10470             stream.point(object[0], object[1], object[2]);
10471           },
10472           MultiPoint: function MultiPoint(object, stream) {
10473             var coordinates = object.coordinates,
10474                 i = -1,
10475                 n = coordinates.length;
10476
10477             while (++i < n) {
10478               object = coordinates[i], stream.point(object[0], object[1], object[2]);
10479             }
10480           },
10481           LineString: function LineString(object, stream) {
10482             streamLine(object.coordinates, stream, 0);
10483           },
10484           MultiLineString: function MultiLineString(object, stream) {
10485             var coordinates = object.coordinates,
10486                 i = -1,
10487                 n = coordinates.length;
10488
10489             while (++i < n) {
10490               streamLine(coordinates[i], stream, 0);
10491             }
10492           },
10493           Polygon: function Polygon(object, stream) {
10494             streamPolygon(object.coordinates, stream);
10495           },
10496           MultiPolygon: function MultiPolygon(object, stream) {
10497             var coordinates = object.coordinates,
10498                 i = -1,
10499                 n = coordinates.length;
10500
10501             while (++i < n) {
10502               streamPolygon(coordinates[i], stream);
10503             }
10504           },
10505           GeometryCollection: function GeometryCollection(object, stream) {
10506             var geometries = object.geometries,
10507                 i = -1,
10508                 n = geometries.length;
10509
10510             while (++i < n) {
10511               streamGeometry(geometries[i], stream);
10512             }
10513           }
10514         };
10515
10516         function streamLine(coordinates, stream, closed) {
10517           var i = -1,
10518               n = coordinates.length - closed,
10519               coordinate;
10520           stream.lineStart();
10521
10522           while (++i < n) {
10523             coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]);
10524           }
10525
10526           stream.lineEnd();
10527         }
10528
10529         function streamPolygon(coordinates, stream) {
10530           var i = -1,
10531               n = coordinates.length;
10532           stream.polygonStart();
10533
10534           while (++i < n) {
10535             streamLine(coordinates[i], stream, 1);
10536           }
10537
10538           stream.polygonEnd();
10539         }
10540
10541         function d3_geoStream (object, stream) {
10542           if (object && streamObjectType.hasOwnProperty(object.type)) {
10543             streamObjectType[object.type](object, stream);
10544           } else {
10545             streamGeometry(object, stream);
10546           }
10547         }
10548
10549         var areaRingSum$1 = new Adder(); // hello?
10550
10551         var areaSum$1 = new Adder(),
10552             lambda00$1,
10553             phi00$1,
10554             lambda0$2,
10555             cosPhi0$1,
10556             sinPhi0$1;
10557         var areaStream$1 = {
10558           point: noop$1,
10559           lineStart: noop$1,
10560           lineEnd: noop$1,
10561           polygonStart: function polygonStart() {
10562             areaRingSum$1 = new Adder();
10563             areaStream$1.lineStart = areaRingStart$1;
10564             areaStream$1.lineEnd = areaRingEnd$1;
10565           },
10566           polygonEnd: function polygonEnd() {
10567             var areaRing = +areaRingSum$1;
10568             areaSum$1.add(areaRing < 0 ? tau + areaRing : areaRing);
10569             this.lineStart = this.lineEnd = this.point = noop$1;
10570           },
10571           sphere: function sphere() {
10572             areaSum$1.add(tau);
10573           }
10574         };
10575
10576         function areaRingStart$1() {
10577           areaStream$1.point = areaPointFirst$1;
10578         }
10579
10580         function areaRingEnd$1() {
10581           areaPoint$1(lambda00$1, phi00$1);
10582         }
10583
10584         function areaPointFirst$1(lambda, phi) {
10585           areaStream$1.point = areaPoint$1;
10586           lambda00$1 = lambda, phi00$1 = phi;
10587           lambda *= radians, phi *= radians;
10588           lambda0$2 = lambda, cosPhi0$1 = cos(phi = phi / 2 + quarterPi), sinPhi0$1 = sin(phi);
10589         }
10590
10591         function areaPoint$1(lambda, phi) {
10592           lambda *= radians, phi *= radians;
10593           phi = phi / 2 + quarterPi; // half the angular distance from south pole
10594           // Spherical excess E for a spherical triangle with vertices: south pole,
10595           // previous point, current point.  Uses a formula derived from Cagnoli’s
10596           // theorem.  See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2).
10597
10598           var dLambda = lambda - lambda0$2,
10599               sdLambda = dLambda >= 0 ? 1 : -1,
10600               adLambda = sdLambda * dLambda,
10601               cosPhi = cos(phi),
10602               sinPhi = sin(phi),
10603               k = sinPhi0$1 * sinPhi,
10604               u = cosPhi0$1 * cosPhi + k * cos(adLambda),
10605               v = k * sdLambda * sin(adLambda);
10606           areaRingSum$1.add(atan2(v, u)); // Advance the previous points.
10607
10608           lambda0$2 = lambda, cosPhi0$1 = cosPhi, sinPhi0$1 = sinPhi;
10609         }
10610
10611         function d3_geoArea (object) {
10612           areaSum$1 = new Adder();
10613           d3_geoStream(object, areaStream$1);
10614           return areaSum$1 * 2;
10615         }
10616
10617         function spherical(cartesian) {
10618           return [atan2(cartesian[1], cartesian[0]), asin(cartesian[2])];
10619         }
10620         function cartesian(spherical) {
10621           var lambda = spherical[0],
10622               phi = spherical[1],
10623               cosPhi = cos(phi);
10624           return [cosPhi * cos(lambda), cosPhi * sin(lambda), sin(phi)];
10625         }
10626         function cartesianDot(a, b) {
10627           return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
10628         }
10629         function cartesianCross(a, b) {
10630           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]];
10631         } // TODO return a
10632
10633         function cartesianAddInPlace(a, b) {
10634           a[0] += b[0], a[1] += b[1], a[2] += b[2];
10635         }
10636         function cartesianScale(vector, k) {
10637           return [vector[0] * k, vector[1] * k, vector[2] * k];
10638         } // TODO return d
10639
10640         function cartesianNormalizeInPlace(d) {
10641           var l = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
10642           d[0] /= l, d[1] /= l, d[2] /= l;
10643         }
10644
10645         var lambda0$1, phi0, lambda1, phi1, // bounds
10646         lambda2, // previous lambda-coordinate
10647         lambda00, phi00, // first point
10648         p0, // previous 3D point
10649         deltaSum, ranges, range;
10650         var boundsStream$1 = {
10651           point: boundsPoint$1,
10652           lineStart: boundsLineStart,
10653           lineEnd: boundsLineEnd,
10654           polygonStart: function polygonStart() {
10655             boundsStream$1.point = boundsRingPoint;
10656             boundsStream$1.lineStart = boundsRingStart;
10657             boundsStream$1.lineEnd = boundsRingEnd;
10658             deltaSum = new Adder();
10659             areaStream$1.polygonStart();
10660           },
10661           polygonEnd: function polygonEnd() {
10662             areaStream$1.polygonEnd();
10663             boundsStream$1.point = boundsPoint$1;
10664             boundsStream$1.lineStart = boundsLineStart;
10665             boundsStream$1.lineEnd = boundsLineEnd;
10666             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;
10667             range[0] = lambda0$1, range[1] = lambda1;
10668           },
10669           sphere: function sphere() {
10670             lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90);
10671           }
10672         };
10673
10674         function boundsPoint$1(lambda, phi) {
10675           ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]);
10676           if (phi < phi0) phi0 = phi;
10677           if (phi > phi1) phi1 = phi;
10678         }
10679
10680         function linePoint(lambda, phi) {
10681           var p = cartesian([lambda * radians, phi * radians]);
10682
10683           if (p0) {
10684             var normal = cartesianCross(p0, p),
10685                 equatorial = [normal[1], -normal[0], 0],
10686                 inflection = cartesianCross(equatorial, normal);
10687             cartesianNormalizeInPlace(inflection);
10688             inflection = spherical(inflection);
10689             var delta = lambda - lambda2,
10690                 sign = delta > 0 ? 1 : -1,
10691                 lambdai = inflection[0] * degrees$1 * sign,
10692                 phii,
10693                 antimeridian = abs$2(delta) > 180;
10694
10695             if (antimeridian ^ (sign * lambda2 < lambdai && lambdai < sign * lambda)) {
10696               phii = inflection[1] * degrees$1;
10697               if (phii > phi1) phi1 = phii;
10698             } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign * lambda2 < lambdai && lambdai < sign * lambda)) {
10699               phii = -inflection[1] * degrees$1;
10700               if (phii < phi0) phi0 = phii;
10701             } else {
10702               if (phi < phi0) phi0 = phi;
10703               if (phi > phi1) phi1 = phi;
10704             }
10705
10706             if (antimeridian) {
10707               if (lambda < lambda2) {
10708                 if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
10709               } else {
10710                 if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
10711               }
10712             } else {
10713               if (lambda1 >= lambda0$1) {
10714                 if (lambda < lambda0$1) lambda0$1 = lambda;
10715                 if (lambda > lambda1) lambda1 = lambda;
10716               } else {
10717                 if (lambda > lambda2) {
10718                   if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
10719                 } else {
10720                   if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
10721                 }
10722               }
10723             }
10724           } else {
10725             ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]);
10726           }
10727
10728           if (phi < phi0) phi0 = phi;
10729           if (phi > phi1) phi1 = phi;
10730           p0 = p, lambda2 = lambda;
10731         }
10732
10733         function boundsLineStart() {
10734           boundsStream$1.point = linePoint;
10735         }
10736
10737         function boundsLineEnd() {
10738           range[0] = lambda0$1, range[1] = lambda1;
10739           boundsStream$1.point = boundsPoint$1;
10740           p0 = null;
10741         }
10742
10743         function boundsRingPoint(lambda, phi) {
10744           if (p0) {
10745             var delta = lambda - lambda2;
10746             deltaSum.add(abs$2(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta);
10747           } else {
10748             lambda00 = lambda, phi00 = phi;
10749           }
10750
10751           areaStream$1.point(lambda, phi);
10752           linePoint(lambda, phi);
10753         }
10754
10755         function boundsRingStart() {
10756           areaStream$1.lineStart();
10757         }
10758
10759         function boundsRingEnd() {
10760           boundsRingPoint(lambda00, phi00);
10761           areaStream$1.lineEnd();
10762           if (abs$2(deltaSum) > epsilon$1) lambda0$1 = -(lambda1 = 180);
10763           range[0] = lambda0$1, range[1] = lambda1;
10764           p0 = null;
10765         } // Finds the left-right distance between two longitudes.
10766         // This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want
10767         // the distance between ±180° to be 360°.
10768
10769
10770         function angle(lambda0, lambda1) {
10771           return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1;
10772         }
10773
10774         function rangeCompare(a, b) {
10775           return a[0] - b[0];
10776         }
10777
10778         function rangeContains(range, x) {
10779           return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
10780         }
10781
10782         function d3_geoBounds (feature) {
10783           var i, n, a, b, merged, deltaMax, delta;
10784           phi1 = lambda1 = -(lambda0$1 = phi0 = Infinity);
10785           ranges = [];
10786           d3_geoStream(feature, boundsStream$1); // First, sort ranges by their minimum longitudes.
10787
10788           if (n = ranges.length) {
10789             ranges.sort(rangeCompare); // Then, merge any ranges that overlap.
10790
10791             for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) {
10792               b = ranges[i];
10793
10794               if (rangeContains(a, b[0]) || rangeContains(a, b[1])) {
10795                 if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
10796                 if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
10797               } else {
10798                 merged.push(a = b);
10799               }
10800             } // Finally, find the largest gap between the merged ranges.
10801             // The final bounding box will be the inverse of this gap.
10802
10803
10804             for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) {
10805               b = merged[i];
10806               if ((delta = angle(a[1], b[0])) > deltaMax) deltaMax = delta, lambda0$1 = b[0], lambda1 = a[1];
10807             }
10808           }
10809
10810           ranges = range = null;
10811           return lambda0$1 === Infinity || phi0 === Infinity ? [[NaN, NaN], [NaN, NaN]] : [[lambda0$1, phi0], [lambda1, phi1]];
10812         }
10813
10814         function compose (a, b) {
10815           function compose(x, y) {
10816             return x = a(x, y), b(x[0], x[1]);
10817           }
10818
10819           if (a.invert && b.invert) compose.invert = function (x, y) {
10820             return x = b.invert(x, y), x && a.invert(x[0], x[1]);
10821           };
10822           return compose;
10823         }
10824
10825         function rotationIdentity(lambda, phi) {
10826           return [abs$2(lambda) > pi ? lambda + Math.round(-lambda / tau) * tau : lambda, phi];
10827         }
10828
10829         rotationIdentity.invert = rotationIdentity;
10830         function rotateRadians(deltaLambda, deltaPhi, deltaGamma) {
10831           return (deltaLambda %= tau) ? deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma)) : rotationLambda(deltaLambda) : deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma) : rotationIdentity;
10832         }
10833
10834         function forwardRotationLambda(deltaLambda) {
10835           return function (lambda, phi) {
10836             return lambda += deltaLambda, [lambda > pi ? lambda - tau : lambda < -pi ? lambda + tau : lambda, phi];
10837           };
10838         }
10839
10840         function rotationLambda(deltaLambda) {
10841           var rotation = forwardRotationLambda(deltaLambda);
10842           rotation.invert = forwardRotationLambda(-deltaLambda);
10843           return rotation;
10844         }
10845
10846         function rotationPhiGamma(deltaPhi, deltaGamma) {
10847           var cosDeltaPhi = cos(deltaPhi),
10848               sinDeltaPhi = sin(deltaPhi),
10849               cosDeltaGamma = cos(deltaGamma),
10850               sinDeltaGamma = sin(deltaGamma);
10851
10852           function rotation(lambda, phi) {
10853             var cosPhi = cos(phi),
10854                 x = cos(lambda) * cosPhi,
10855                 y = sin(lambda) * cosPhi,
10856                 z = sin(phi),
10857                 k = z * cosDeltaPhi + x * sinDeltaPhi;
10858             return [atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi), asin(k * cosDeltaGamma + y * sinDeltaGamma)];
10859           }
10860
10861           rotation.invert = function (lambda, phi) {
10862             var cosPhi = cos(phi),
10863                 x = cos(lambda) * cosPhi,
10864                 y = sin(lambda) * cosPhi,
10865                 z = sin(phi),
10866                 k = z * cosDeltaGamma - y * sinDeltaGamma;
10867             return [atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi), asin(k * cosDeltaPhi - x * sinDeltaPhi)];
10868           };
10869
10870           return rotation;
10871         }
10872
10873         function rotation (rotate) {
10874           rotate = rotateRadians(rotate[0] * radians, rotate[1] * radians, rotate.length > 2 ? rotate[2] * radians : 0);
10875
10876           function forward(coordinates) {
10877             coordinates = rotate(coordinates[0] * radians, coordinates[1] * radians);
10878             return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates;
10879           }
10880
10881           forward.invert = function (coordinates) {
10882             coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians);
10883             return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates;
10884           };
10885
10886           return forward;
10887         }
10888
10889         function circleStream(stream, radius, delta, direction, t0, t1) {
10890           if (!delta) return;
10891           var cosRadius = cos(radius),
10892               sinRadius = sin(radius),
10893               step = direction * delta;
10894
10895           if (t0 == null) {
10896             t0 = radius + direction * tau;
10897             t1 = radius - step / 2;
10898           } else {
10899             t0 = circleRadius(cosRadius, t0);
10900             t1 = circleRadius(cosRadius, t1);
10901             if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau;
10902           }
10903
10904           for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) {
10905             point = spherical([cosRadius, -sinRadius * cos(t), -sinRadius * sin(t)]);
10906             stream.point(point[0], point[1]);
10907           }
10908         } // Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0].
10909
10910         function circleRadius(cosRadius, point) {
10911           point = cartesian(point), point[0] -= cosRadius;
10912           cartesianNormalizeInPlace(point);
10913           var radius = acos(-point[1]);
10914           return ((-point[2] < 0 ? -radius : radius) + tau - epsilon$1) % tau;
10915         }
10916
10917         function clipBuffer () {
10918           var lines = [],
10919               line;
10920           return {
10921             point: function point(x, y, m) {
10922               line.push([x, y, m]);
10923             },
10924             lineStart: function lineStart() {
10925               lines.push(line = []);
10926             },
10927             lineEnd: noop$1,
10928             rejoin: function rejoin() {
10929               if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
10930             },
10931             result: function result() {
10932               var result = lines;
10933               lines = [];
10934               line = null;
10935               return result;
10936             }
10937           };
10938         }
10939
10940         function pointEqual (a, b) {
10941           return abs$2(a[0] - b[0]) < epsilon$1 && abs$2(a[1] - b[1]) < epsilon$1;
10942         }
10943
10944         function Intersection(point, points, other, entry) {
10945           this.x = point;
10946           this.z = points;
10947           this.o = other; // another intersection
10948
10949           this.e = entry; // is an entry?
10950
10951           this.v = false; // visited
10952
10953           this.n = this.p = null; // next & previous
10954         } // A generalized polygon clipping algorithm: given a polygon that has been cut
10955         // into its visible line segments, and rejoins the segments by interpolating
10956         // along the clip edge.
10957
10958
10959         function clipRejoin (segments, compareIntersection, startInside, interpolate, stream) {
10960           var subject = [],
10961               clip = [],
10962               i,
10963               n;
10964           segments.forEach(function (segment) {
10965             if ((n = segment.length - 1) <= 0) return;
10966             var n,
10967                 p0 = segment[0],
10968                 p1 = segment[n],
10969                 x;
10970
10971             if (pointEqual(p0, p1)) {
10972               if (!p0[2] && !p1[2]) {
10973                 stream.lineStart();
10974
10975                 for (i = 0; i < n; ++i) {
10976                   stream.point((p0 = segment[i])[0], p0[1]);
10977                 }
10978
10979                 stream.lineEnd();
10980                 return;
10981               } // handle degenerate cases by moving the point
10982
10983
10984               p1[0] += 2 * epsilon$1;
10985             }
10986
10987             subject.push(x = new Intersection(p0, segment, null, true));
10988             clip.push(x.o = new Intersection(p0, null, x, false));
10989             subject.push(x = new Intersection(p1, segment, null, false));
10990             clip.push(x.o = new Intersection(p1, null, x, true));
10991           });
10992           if (!subject.length) return;
10993           clip.sort(compareIntersection);
10994           link(subject);
10995           link(clip);
10996
10997           for (i = 0, n = clip.length; i < n; ++i) {
10998             clip[i].e = startInside = !startInside;
10999           }
11000
11001           var start = subject[0],
11002               points,
11003               point;
11004
11005           while (1) {
11006             // Find first unvisited intersection.
11007             var current = start,
11008                 isSubject = true;
11009
11010             while (current.v) {
11011               if ((current = current.n) === start) return;
11012             }
11013
11014             points = current.z;
11015             stream.lineStart();
11016
11017             do {
11018               current.v = current.o.v = true;
11019
11020               if (current.e) {
11021                 if (isSubject) {
11022                   for (i = 0, n = points.length; i < n; ++i) {
11023                     stream.point((point = points[i])[0], point[1]);
11024                   }
11025                 } else {
11026                   interpolate(current.x, current.n.x, 1, stream);
11027                 }
11028
11029                 current = current.n;
11030               } else {
11031                 if (isSubject) {
11032                   points = current.p.z;
11033
11034                   for (i = points.length - 1; i >= 0; --i) {
11035                     stream.point((point = points[i])[0], point[1]);
11036                   }
11037                 } else {
11038                   interpolate(current.x, current.p.x, -1, stream);
11039                 }
11040
11041                 current = current.p;
11042               }
11043
11044               current = current.o;
11045               points = current.z;
11046               isSubject = !isSubject;
11047             } while (!current.v);
11048
11049             stream.lineEnd();
11050           }
11051         }
11052
11053         function link(array) {
11054           if (!(n = array.length)) return;
11055           var n,
11056               i = 0,
11057               a = array[0],
11058               b;
11059
11060           while (++i < n) {
11061             a.n = b = array[i];
11062             b.p = a;
11063             a = b;
11064           }
11065
11066           a.n = b = array[0];
11067           b.p = a;
11068         }
11069
11070         function longitude(point) {
11071           if (abs$2(point[0]) <= pi) return point[0];else return sign(point[0]) * ((abs$2(point[0]) + pi) % tau - pi);
11072         }
11073
11074         function polygonContains (polygon, point) {
11075           var lambda = longitude(point),
11076               phi = point[1],
11077               sinPhi = sin(phi),
11078               normal = [sin(lambda), -cos(lambda), 0],
11079               angle = 0,
11080               winding = 0;
11081           var sum = new Adder();
11082           if (sinPhi === 1) phi = halfPi + epsilon$1;else if (sinPhi === -1) phi = -halfPi - epsilon$1;
11083
11084           for (var i = 0, n = polygon.length; i < n; ++i) {
11085             if (!(m = (ring = polygon[i]).length)) continue;
11086             var ring,
11087                 m,
11088                 point0 = ring[m - 1],
11089                 lambda0 = longitude(point0),
11090                 phi0 = point0[1] / 2 + quarterPi,
11091                 sinPhi0 = sin(phi0),
11092                 cosPhi0 = cos(phi0);
11093
11094             for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) {
11095               var point1 = ring[j],
11096                   lambda1 = longitude(point1),
11097                   phi1 = point1[1] / 2 + quarterPi,
11098                   sinPhi1 = sin(phi1),
11099                   cosPhi1 = cos(phi1),
11100                   delta = lambda1 - lambda0,
11101                   sign = delta >= 0 ? 1 : -1,
11102                   absDelta = sign * delta,
11103                   antimeridian = absDelta > pi,
11104                   k = sinPhi0 * sinPhi1;
11105               sum.add(atan2(k * sign * sin(absDelta), cosPhi0 * cosPhi1 + k * cos(absDelta)));
11106               angle += antimeridian ? delta + sign * tau : delta; // Are the longitudes either side of the point’s meridian (lambda),
11107               // and are the latitudes smaller than the parallel (phi)?
11108
11109               if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) {
11110                 var arc = cartesianCross(cartesian(point0), cartesian(point1));
11111                 cartesianNormalizeInPlace(arc);
11112                 var intersection = cartesianCross(normal, arc);
11113                 cartesianNormalizeInPlace(intersection);
11114                 var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin(intersection[2]);
11115
11116                 if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) {
11117                   winding += antimeridian ^ delta >= 0 ? 1 : -1;
11118                 }
11119               }
11120             }
11121           } // First, determine whether the South pole is inside or outside:
11122           //
11123           // It is inside if:
11124           // * the polygon winds around it in a clockwise direction.
11125           // * the polygon does not (cumulatively) wind around it, but has a negative
11126           //   (counter-clockwise) area.
11127           //
11128           // Second, count the (signed) number of times a segment crosses a lambda
11129           // from the point to the South pole.  If it is zero, then the point is the
11130           // same side as the South pole.
11131
11132
11133           return (angle < -epsilon$1 || angle < epsilon$1 && sum < -epsilon2$1) ^ winding & 1;
11134         }
11135
11136         function clip (pointVisible, clipLine, interpolate, start) {
11137           return function (sink) {
11138             var line = clipLine(sink),
11139                 ringBuffer = clipBuffer(),
11140                 ringSink = clipLine(ringBuffer),
11141                 polygonStarted = false,
11142                 polygon,
11143                 segments,
11144                 ring;
11145             var clip = {
11146               point: point,
11147               lineStart: lineStart,
11148               lineEnd: lineEnd,
11149               polygonStart: function polygonStart() {
11150                 clip.point = pointRing;
11151                 clip.lineStart = ringStart;
11152                 clip.lineEnd = ringEnd;
11153                 segments = [];
11154                 polygon = [];
11155               },
11156               polygonEnd: function polygonEnd() {
11157                 clip.point = point;
11158                 clip.lineStart = lineStart;
11159                 clip.lineEnd = lineEnd;
11160                 segments = merge$4(segments);
11161                 var startInside = polygonContains(polygon, start);
11162
11163                 if (segments.length) {
11164                   if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
11165                   clipRejoin(segments, compareIntersection, startInside, interpolate, sink);
11166                 } else if (startInside) {
11167                   if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
11168                   sink.lineStart();
11169                   interpolate(null, null, 1, sink);
11170                   sink.lineEnd();
11171                 }
11172
11173                 if (polygonStarted) sink.polygonEnd(), polygonStarted = false;
11174                 segments = polygon = null;
11175               },
11176               sphere: function sphere() {
11177                 sink.polygonStart();
11178                 sink.lineStart();
11179                 interpolate(null, null, 1, sink);
11180                 sink.lineEnd();
11181                 sink.polygonEnd();
11182               }
11183             };
11184
11185             function point(lambda, phi) {
11186               if (pointVisible(lambda, phi)) sink.point(lambda, phi);
11187             }
11188
11189             function pointLine(lambda, phi) {
11190               line.point(lambda, phi);
11191             }
11192
11193             function lineStart() {
11194               clip.point = pointLine;
11195               line.lineStart();
11196             }
11197
11198             function lineEnd() {
11199               clip.point = point;
11200               line.lineEnd();
11201             }
11202
11203             function pointRing(lambda, phi) {
11204               ring.push([lambda, phi]);
11205               ringSink.point(lambda, phi);
11206             }
11207
11208             function ringStart() {
11209               ringSink.lineStart();
11210               ring = [];
11211             }
11212
11213             function ringEnd() {
11214               pointRing(ring[0][0], ring[0][1]);
11215               ringSink.lineEnd();
11216               var clean = ringSink.clean(),
11217                   ringSegments = ringBuffer.result(),
11218                   i,
11219                   n = ringSegments.length,
11220                   m,
11221                   segment,
11222                   point;
11223               ring.pop();
11224               polygon.push(ring);
11225               ring = null;
11226               if (!n) return; // No intersections.
11227
11228               if (clean & 1) {
11229                 segment = ringSegments[0];
11230
11231                 if ((m = segment.length - 1) > 0) {
11232                   if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
11233                   sink.lineStart();
11234
11235                   for (i = 0; i < m; ++i) {
11236                     sink.point((point = segment[i])[0], point[1]);
11237                   }
11238
11239                   sink.lineEnd();
11240                 }
11241
11242                 return;
11243               } // Rejoin connected segments.
11244               // TODO reuse ringBuffer.rejoin()?
11245
11246
11247               if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
11248               segments.push(ringSegments.filter(validSegment));
11249             }
11250
11251             return clip;
11252           };
11253         }
11254
11255         function validSegment(segment) {
11256           return segment.length > 1;
11257         } // Intersections are sorted along the clip edge. For both antimeridian cutting
11258         // and circle clipping, the same comparison is used.
11259
11260
11261         function compareIntersection(a, b) {
11262           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]);
11263         }
11264
11265         var clipAntimeridian = clip(function () {
11266           return true;
11267         }, clipAntimeridianLine, clipAntimeridianInterpolate, [-pi, -halfPi]); // Takes a line and cuts into visible segments. Return values: 0 - there were
11268         // intersections or the line was empty; 1 - no intersections; 2 - there were
11269         // intersections, and the first and last segments should be rejoined.
11270
11271         function clipAntimeridianLine(stream) {
11272           var lambda0 = NaN,
11273               phi0 = NaN,
11274               sign0 = NaN,
11275               _clean; // no intersections
11276
11277
11278           return {
11279             lineStart: function lineStart() {
11280               stream.lineStart();
11281               _clean = 1;
11282             },
11283             point: function point(lambda1, phi1) {
11284               var sign1 = lambda1 > 0 ? pi : -pi,
11285                   delta = abs$2(lambda1 - lambda0);
11286
11287               if (abs$2(delta - pi) < epsilon$1) {
11288                 // line crosses a pole
11289                 stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi : -halfPi);
11290                 stream.point(sign0, phi0);
11291                 stream.lineEnd();
11292                 stream.lineStart();
11293                 stream.point(sign1, phi0);
11294                 stream.point(lambda1, phi0);
11295                 _clean = 0;
11296               } else if (sign0 !== sign1 && delta >= pi) {
11297                 // line crosses antimeridian
11298                 if (abs$2(lambda0 - sign0) < epsilon$1) lambda0 -= sign0 * epsilon$1; // handle degeneracies
11299
11300                 if (abs$2(lambda1 - sign1) < epsilon$1) lambda1 -= sign1 * epsilon$1;
11301                 phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1);
11302                 stream.point(sign0, phi0);
11303                 stream.lineEnd();
11304                 stream.lineStart();
11305                 stream.point(sign1, phi0);
11306                 _clean = 0;
11307               }
11308
11309               stream.point(lambda0 = lambda1, phi0 = phi1);
11310               sign0 = sign1;
11311             },
11312             lineEnd: function lineEnd() {
11313               stream.lineEnd();
11314               lambda0 = phi0 = NaN;
11315             },
11316             clean: function clean() {
11317               return 2 - _clean; // if intersections, rejoin first and last segments
11318             }
11319           };
11320         }
11321
11322         function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) {
11323           var cosPhi0,
11324               cosPhi1,
11325               sinLambda0Lambda1 = sin(lambda0 - lambda1);
11326           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;
11327         }
11328
11329         function clipAntimeridianInterpolate(from, to, direction, stream) {
11330           var phi;
11331
11332           if (from == null) {
11333             phi = direction * halfPi;
11334             stream.point(-pi, phi);
11335             stream.point(0, phi);
11336             stream.point(pi, phi);
11337             stream.point(pi, 0);
11338             stream.point(pi, -phi);
11339             stream.point(0, -phi);
11340             stream.point(-pi, -phi);
11341             stream.point(-pi, 0);
11342             stream.point(-pi, phi);
11343           } else if (abs$2(from[0] - to[0]) > epsilon$1) {
11344             var lambda = from[0] < to[0] ? pi : -pi;
11345             phi = direction * lambda / 2;
11346             stream.point(-lambda, phi);
11347             stream.point(0, phi);
11348             stream.point(lambda, phi);
11349           } else {
11350             stream.point(to[0], to[1]);
11351           }
11352         }
11353
11354         function clipCircle (radius) {
11355           var cr = cos(radius),
11356               delta = 6 * radians,
11357               smallRadius = cr > 0,
11358               notHemisphere = abs$2(cr) > epsilon$1; // TODO optimise for this common case
11359
11360           function interpolate(from, to, direction, stream) {
11361             circleStream(stream, radius, delta, direction, from, to);
11362           }
11363
11364           function visible(lambda, phi) {
11365             return cos(lambda) * cos(phi) > cr;
11366           } // Takes a line and cuts into visible segments. Return values used for polygon
11367           // clipping: 0 - there were intersections or the line was empty; 1 - no
11368           // intersections 2 - there were intersections, and the first and last segments
11369           // should be rejoined.
11370
11371
11372           function clipLine(stream) {
11373             var point0, // previous point
11374             c0, // code for previous point
11375             v0, // visibility of previous point
11376             v00, // visibility of first point
11377             _clean; // no intersections
11378
11379
11380             return {
11381               lineStart: function lineStart() {
11382                 v00 = v0 = false;
11383                 _clean = 1;
11384               },
11385               point: function point(lambda, phi) {
11386                 var point1 = [lambda, phi],
11387                     point2,
11388                     v = visible(lambda, phi),
11389                     c = smallRadius ? v ? 0 : code(lambda, phi) : v ? code(lambda + (lambda < 0 ? pi : -pi), phi) : 0;
11390                 if (!point0 && (v00 = v0 = v)) stream.lineStart();
11391
11392                 if (v !== v0) {
11393                   point2 = intersect(point0, point1);
11394                   if (!point2 || pointEqual(point0, point2) || pointEqual(point1, point2)) point1[2] = 1;
11395                 }
11396
11397                 if (v !== v0) {
11398                   _clean = 0;
11399
11400                   if (v) {
11401                     // outside going in
11402                     stream.lineStart();
11403                     point2 = intersect(point1, point0);
11404                     stream.point(point2[0], point2[1]);
11405                   } else {
11406                     // inside going out
11407                     point2 = intersect(point0, point1);
11408                     stream.point(point2[0], point2[1], 2);
11409                     stream.lineEnd();
11410                   }
11411
11412                   point0 = point2;
11413                 } else if (notHemisphere && point0 && smallRadius ^ v) {
11414                   var t; // If the codes for two points are different, or are both zero,
11415                   // and there this segment intersects with the small circle.
11416
11417                   if (!(c & c0) && (t = intersect(point1, point0, true))) {
11418                     _clean = 0;
11419
11420                     if (smallRadius) {
11421                       stream.lineStart();
11422                       stream.point(t[0][0], t[0][1]);
11423                       stream.point(t[1][0], t[1][1]);
11424                       stream.lineEnd();
11425                     } else {
11426                       stream.point(t[1][0], t[1][1]);
11427                       stream.lineEnd();
11428                       stream.lineStart();
11429                       stream.point(t[0][0], t[0][1], 3);
11430                     }
11431                   }
11432                 }
11433
11434                 if (v && (!point0 || !pointEqual(point0, point1))) {
11435                   stream.point(point1[0], point1[1]);
11436                 }
11437
11438                 point0 = point1, v0 = v, c0 = c;
11439               },
11440               lineEnd: function lineEnd() {
11441                 if (v0) stream.lineEnd();
11442                 point0 = null;
11443               },
11444               // Rejoin first and last segments if there were intersections and the first
11445               // and last points were visible.
11446               clean: function clean() {
11447                 return _clean | (v00 && v0) << 1;
11448               }
11449             };
11450           } // Intersects the great circle between a and b with the clip circle.
11451
11452
11453           function intersect(a, b, two) {
11454             var pa = cartesian(a),
11455                 pb = cartesian(b); // We have two planes, n1.p = d1 and n2.p = d2.
11456             // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2).
11457
11458             var n1 = [1, 0, 0],
11459                 // normal
11460             n2 = cartesianCross(pa, pb),
11461                 n2n2 = cartesianDot(n2, n2),
11462                 n1n2 = n2[0],
11463                 // cartesianDot(n1, n2),
11464             determinant = n2n2 - n1n2 * n1n2; // Two polar points.
11465
11466             if (!determinant) return !two && a;
11467             var c1 = cr * n2n2 / determinant,
11468                 c2 = -cr * n1n2 / determinant,
11469                 n1xn2 = cartesianCross(n1, n2),
11470                 A = cartesianScale(n1, c1),
11471                 B = cartesianScale(n2, c2);
11472             cartesianAddInPlace(A, B); // Solve |p(t)|^2 = 1.
11473
11474             var u = n1xn2,
11475                 w = cartesianDot(A, u),
11476                 uu = cartesianDot(u, u),
11477                 t2 = w * w - uu * (cartesianDot(A, A) - 1);
11478             if (t2 < 0) return;
11479             var t = sqrt(t2),
11480                 q = cartesianScale(u, (-w - t) / uu);
11481             cartesianAddInPlace(q, A);
11482             q = spherical(q);
11483             if (!two) return q; // Two intersection points.
11484
11485             var lambda0 = a[0],
11486                 lambda1 = b[0],
11487                 phi0 = a[1],
11488                 phi1 = b[1],
11489                 z;
11490             if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z;
11491             var delta = lambda1 - lambda0,
11492                 polar = abs$2(delta - pi) < epsilon$1,
11493                 meridian = polar || delta < epsilon$1;
11494             if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z; // Check that the first point is between a and b.
11495
11496             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)) {
11497               var q1 = cartesianScale(u, (-w + t) / uu);
11498               cartesianAddInPlace(q1, A);
11499               return [q, spherical(q1)];
11500             }
11501           } // Generates a 4-bit vector representing the location of a point relative to
11502           // the small circle's bounding box.
11503
11504
11505           function code(lambda, phi) {
11506             var r = smallRadius ? radius : pi - radius,
11507                 code = 0;
11508             if (lambda < -r) code |= 1; // left
11509             else if (lambda > r) code |= 2; // right
11510
11511             if (phi < -r) code |= 4; // below
11512             else if (phi > r) code |= 8; // above
11513
11514             return code;
11515           }
11516
11517           return clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-pi, radius - pi]);
11518         }
11519
11520         function clipLine (a, b, x0, y0, x1, y1) {
11521           var ax = a[0],
11522               ay = a[1],
11523               bx = b[0],
11524               by = b[1],
11525               t0 = 0,
11526               t1 = 1,
11527               dx = bx - ax,
11528               dy = by - ay,
11529               r;
11530           r = x0 - ax;
11531           if (!dx && r > 0) return;
11532           r /= dx;
11533
11534           if (dx < 0) {
11535             if (r < t0) return;
11536             if (r < t1) t1 = r;
11537           } else if (dx > 0) {
11538             if (r > t1) return;
11539             if (r > t0) t0 = r;
11540           }
11541
11542           r = x1 - ax;
11543           if (!dx && r < 0) return;
11544           r /= dx;
11545
11546           if (dx < 0) {
11547             if (r > t1) return;
11548             if (r > t0) t0 = r;
11549           } else if (dx > 0) {
11550             if (r < t0) return;
11551             if (r < t1) t1 = r;
11552           }
11553
11554           r = y0 - ay;
11555           if (!dy && r > 0) return;
11556           r /= dy;
11557
11558           if (dy < 0) {
11559             if (r < t0) return;
11560             if (r < t1) t1 = r;
11561           } else if (dy > 0) {
11562             if (r > t1) return;
11563             if (r > t0) t0 = r;
11564           }
11565
11566           r = y1 - ay;
11567           if (!dy && r < 0) return;
11568           r /= dy;
11569
11570           if (dy < 0) {
11571             if (r > t1) return;
11572             if (r > t0) t0 = r;
11573           } else if (dy > 0) {
11574             if (r < t0) return;
11575             if (r < t1) t1 = r;
11576           }
11577
11578           if (t0 > 0) a[0] = ax + t0 * dx, a[1] = ay + t0 * dy;
11579           if (t1 < 1) b[0] = ax + t1 * dx, b[1] = ay + t1 * dy;
11580           return true;
11581         }
11582
11583         var clipMax = 1e9,
11584             clipMin = -clipMax; // TODO Use d3-polygon’s polygonContains here for the ring check?
11585         // TODO Eliminate duplicate buffering in clipBuffer and polygon.push?
11586
11587         function clipRectangle(x0, y0, x1, y1) {
11588           function visible(x, y) {
11589             return x0 <= x && x <= x1 && y0 <= y && y <= y1;
11590           }
11591
11592           function interpolate(from, to, direction, stream) {
11593             var a = 0,
11594                 a1 = 0;
11595
11596             if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoint(from, to) < 0 ^ direction > 0) {
11597               do {
11598                 stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
11599               } while ((a = (a + direction + 4) % 4) !== a1);
11600             } else {
11601               stream.point(to[0], to[1]);
11602             }
11603           }
11604
11605           function corner(p, direction) {
11606             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
11607           }
11608
11609           function compareIntersection(a, b) {
11610             return comparePoint(a.x, b.x);
11611           }
11612
11613           function comparePoint(a, b) {
11614             var ca = corner(a, 1),
11615                 cb = corner(b, 1);
11616             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];
11617           }
11618
11619           return function (stream) {
11620             var activeStream = stream,
11621                 bufferStream = clipBuffer(),
11622                 segments,
11623                 polygon,
11624                 ring,
11625                 x__,
11626                 y__,
11627                 v__,
11628                 // first point
11629             x_,
11630                 y_,
11631                 v_,
11632                 // previous point
11633             first,
11634                 clean;
11635             var clipStream = {
11636               point: point,
11637               lineStart: lineStart,
11638               lineEnd: lineEnd,
11639               polygonStart: polygonStart,
11640               polygonEnd: polygonEnd
11641             };
11642
11643             function point(x, y) {
11644               if (visible(x, y)) activeStream.point(x, y);
11645             }
11646
11647             function polygonInside() {
11648               var winding = 0;
11649
11650               for (var i = 0, n = polygon.length; i < n; ++i) {
11651                 for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) {
11652                   a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1];
11653
11654                   if (a1 <= y1) {
11655                     if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding;
11656                   } else {
11657                     if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding;
11658                   }
11659                 }
11660               }
11661
11662               return winding;
11663             } // Buffer geometry within a polygon and then clip it en masse.
11664
11665
11666             function polygonStart() {
11667               activeStream = bufferStream, segments = [], polygon = [], clean = true;
11668             }
11669
11670             function polygonEnd() {
11671               var startInside = polygonInside(),
11672                   cleanInside = clean && startInside,
11673                   visible = (segments = merge$4(segments)).length;
11674
11675               if (cleanInside || visible) {
11676                 stream.polygonStart();
11677
11678                 if (cleanInside) {
11679                   stream.lineStart();
11680                   interpolate(null, null, 1, stream);
11681                   stream.lineEnd();
11682                 }
11683
11684                 if (visible) {
11685                   clipRejoin(segments, compareIntersection, startInside, interpolate, stream);
11686                 }
11687
11688                 stream.polygonEnd();
11689               }
11690
11691               activeStream = stream, segments = polygon = ring = null;
11692             }
11693
11694             function lineStart() {
11695               clipStream.point = linePoint;
11696               if (polygon) polygon.push(ring = []);
11697               first = true;
11698               v_ = false;
11699               x_ = y_ = NaN;
11700             } // TODO rather than special-case polygons, simply handle them separately.
11701             // Ideally, coincident intersection points should be jittered to avoid
11702             // clipping issues.
11703
11704
11705             function lineEnd() {
11706               if (segments) {
11707                 linePoint(x__, y__);
11708                 if (v__ && v_) bufferStream.rejoin();
11709                 segments.push(bufferStream.result());
11710               }
11711
11712               clipStream.point = point;
11713               if (v_) activeStream.lineEnd();
11714             }
11715
11716             function linePoint(x, y) {
11717               var v = visible(x, y);
11718               if (polygon) ring.push([x, y]);
11719
11720               if (first) {
11721                 x__ = x, y__ = y, v__ = v;
11722                 first = false;
11723
11724                 if (v) {
11725                   activeStream.lineStart();
11726                   activeStream.point(x, y);
11727                 }
11728               } else {
11729                 if (v && v_) activeStream.point(x, y);else {
11730                   var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))],
11731                       b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))];
11732
11733                   if (clipLine(a, b, x0, y0, x1, y1)) {
11734                     if (!v_) {
11735                       activeStream.lineStart();
11736                       activeStream.point(a[0], a[1]);
11737                     }
11738
11739                     activeStream.point(b[0], b[1]);
11740                     if (!v) activeStream.lineEnd();
11741                     clean = false;
11742                   } else if (v) {
11743                     activeStream.lineStart();
11744                     activeStream.point(x, y);
11745                     clean = false;
11746                   }
11747                 }
11748               }
11749
11750               x_ = x, y_ = y, v_ = v;
11751             }
11752
11753             return clipStream;
11754           };
11755         }
11756
11757         var lengthSum$1, lambda0, sinPhi0, cosPhi0;
11758         var lengthStream$1 = {
11759           sphere: noop$1,
11760           point: noop$1,
11761           lineStart: lengthLineStart,
11762           lineEnd: noop$1,
11763           polygonStart: noop$1,
11764           polygonEnd: noop$1
11765         };
11766
11767         function lengthLineStart() {
11768           lengthStream$1.point = lengthPointFirst$1;
11769           lengthStream$1.lineEnd = lengthLineEnd;
11770         }
11771
11772         function lengthLineEnd() {
11773           lengthStream$1.point = lengthStream$1.lineEnd = noop$1;
11774         }
11775
11776         function lengthPointFirst$1(lambda, phi) {
11777           lambda *= radians, phi *= radians;
11778           lambda0 = lambda, sinPhi0 = sin(phi), cosPhi0 = cos(phi);
11779           lengthStream$1.point = lengthPoint$1;
11780         }
11781
11782         function lengthPoint$1(lambda, phi) {
11783           lambda *= radians, phi *= radians;
11784           var sinPhi = sin(phi),
11785               cosPhi = cos(phi),
11786               delta = abs$2(lambda - lambda0),
11787               cosDelta = cos(delta),
11788               sinDelta = sin(delta),
11789               x = cosPhi * sinDelta,
11790               y = cosPhi0 * sinPhi - sinPhi0 * cosPhi * cosDelta,
11791               z = sinPhi0 * sinPhi + cosPhi0 * cosPhi * cosDelta;
11792           lengthSum$1.add(atan2(sqrt(x * x + y * y), z));
11793           lambda0 = lambda, sinPhi0 = sinPhi, cosPhi0 = cosPhi;
11794         }
11795
11796         function d3_geoLength (object) {
11797           lengthSum$1 = new Adder();
11798           d3_geoStream(object, lengthStream$1);
11799           return +lengthSum$1;
11800         }
11801
11802         var identity$4 = (function (x) {
11803           return x;
11804         });
11805
11806         var areaSum = new Adder(),
11807             areaRingSum = new Adder(),
11808             x00$2,
11809             y00$2,
11810             x0$3,
11811             y0$3;
11812         var areaStream = {
11813           point: noop$1,
11814           lineStart: noop$1,
11815           lineEnd: noop$1,
11816           polygonStart: function polygonStart() {
11817             areaStream.lineStart = areaRingStart;
11818             areaStream.lineEnd = areaRingEnd;
11819           },
11820           polygonEnd: function polygonEnd() {
11821             areaStream.lineStart = areaStream.lineEnd = areaStream.point = noop$1;
11822             areaSum.add(abs$2(areaRingSum));
11823             areaRingSum = new Adder();
11824           },
11825           result: function result() {
11826             var area = areaSum / 2;
11827             areaSum = new Adder();
11828             return area;
11829           }
11830         };
11831
11832         function areaRingStart() {
11833           areaStream.point = areaPointFirst;
11834         }
11835
11836         function areaPointFirst(x, y) {
11837           areaStream.point = areaPoint;
11838           x00$2 = x0$3 = x, y00$2 = y0$3 = y;
11839         }
11840
11841         function areaPoint(x, y) {
11842           areaRingSum.add(y0$3 * x - x0$3 * y);
11843           x0$3 = x, y0$3 = y;
11844         }
11845
11846         function areaRingEnd() {
11847           areaPoint(x00$2, y00$2);
11848         }
11849
11850         var x0$2 = Infinity,
11851             y0$2 = x0$2,
11852             x1 = -x0$2,
11853             y1 = x1;
11854         var boundsStream = {
11855           point: boundsPoint,
11856           lineStart: noop$1,
11857           lineEnd: noop$1,
11858           polygonStart: noop$1,
11859           polygonEnd: noop$1,
11860           result: function result() {
11861             var bounds = [[x0$2, y0$2], [x1, y1]];
11862             x1 = y1 = -(y0$2 = x0$2 = Infinity);
11863             return bounds;
11864           }
11865         };
11866
11867         function boundsPoint(x, y) {
11868           if (x < x0$2) x0$2 = x;
11869           if (x > x1) x1 = x;
11870           if (y < y0$2) y0$2 = y;
11871           if (y > y1) y1 = y;
11872         }
11873
11874         var X0 = 0,
11875             Y0 = 0,
11876             Z0 = 0,
11877             X1 = 0,
11878             Y1 = 0,
11879             Z1 = 0,
11880             X2 = 0,
11881             Y2 = 0,
11882             Z2 = 0,
11883             x00$1,
11884             y00$1,
11885             x0$1,
11886             y0$1;
11887         var centroidStream = {
11888           point: centroidPoint,
11889           lineStart: centroidLineStart,
11890           lineEnd: centroidLineEnd,
11891           polygonStart: function polygonStart() {
11892             centroidStream.lineStart = centroidRingStart;
11893             centroidStream.lineEnd = centroidRingEnd;
11894           },
11895           polygonEnd: function polygonEnd() {
11896             centroidStream.point = centroidPoint;
11897             centroidStream.lineStart = centroidLineStart;
11898             centroidStream.lineEnd = centroidLineEnd;
11899           },
11900           result: function result() {
11901             var centroid = Z2 ? [X2 / Z2, Y2 / Z2] : Z1 ? [X1 / Z1, Y1 / Z1] : Z0 ? [X0 / Z0, Y0 / Z0] : [NaN, NaN];
11902             X0 = Y0 = Z0 = X1 = Y1 = Z1 = X2 = Y2 = Z2 = 0;
11903             return centroid;
11904           }
11905         };
11906
11907         function centroidPoint(x, y) {
11908           X0 += x;
11909           Y0 += y;
11910           ++Z0;
11911         }
11912
11913         function centroidLineStart() {
11914           centroidStream.point = centroidPointFirstLine;
11915         }
11916
11917         function centroidPointFirstLine(x, y) {
11918           centroidStream.point = centroidPointLine;
11919           centroidPoint(x0$1 = x, y0$1 = y);
11920         }
11921
11922         function centroidPointLine(x, y) {
11923           var dx = x - x0$1,
11924               dy = y - y0$1,
11925               z = sqrt(dx * dx + dy * dy);
11926           X1 += z * (x0$1 + x) / 2;
11927           Y1 += z * (y0$1 + y) / 2;
11928           Z1 += z;
11929           centroidPoint(x0$1 = x, y0$1 = y);
11930         }
11931
11932         function centroidLineEnd() {
11933           centroidStream.point = centroidPoint;
11934         }
11935
11936         function centroidRingStart() {
11937           centroidStream.point = centroidPointFirstRing;
11938         }
11939
11940         function centroidRingEnd() {
11941           centroidPointRing(x00$1, y00$1);
11942         }
11943
11944         function centroidPointFirstRing(x, y) {
11945           centroidStream.point = centroidPointRing;
11946           centroidPoint(x00$1 = x0$1 = x, y00$1 = y0$1 = y);
11947         }
11948
11949         function centroidPointRing(x, y) {
11950           var dx = x - x0$1,
11951               dy = y - y0$1,
11952               z = sqrt(dx * dx + dy * dy);
11953           X1 += z * (x0$1 + x) / 2;
11954           Y1 += z * (y0$1 + y) / 2;
11955           Z1 += z;
11956           z = y0$1 * x - x0$1 * y;
11957           X2 += z * (x0$1 + x);
11958           Y2 += z * (y0$1 + y);
11959           Z2 += z * 3;
11960           centroidPoint(x0$1 = x, y0$1 = y);
11961         }
11962
11963         function PathContext(context) {
11964           this._context = context;
11965         }
11966         PathContext.prototype = {
11967           _radius: 4.5,
11968           pointRadius: function pointRadius(_) {
11969             return this._radius = _, this;
11970           },
11971           polygonStart: function polygonStart() {
11972             this._line = 0;
11973           },
11974           polygonEnd: function polygonEnd() {
11975             this._line = NaN;
11976           },
11977           lineStart: function lineStart() {
11978             this._point = 0;
11979           },
11980           lineEnd: function lineEnd() {
11981             if (this._line === 0) this._context.closePath();
11982             this._point = NaN;
11983           },
11984           point: function point(x, y) {
11985             switch (this._point) {
11986               case 0:
11987                 {
11988                   this._context.moveTo(x, y);
11989
11990                   this._point = 1;
11991                   break;
11992                 }
11993
11994               case 1:
11995                 {
11996                   this._context.lineTo(x, y);
11997
11998                   break;
11999                 }
12000
12001               default:
12002                 {
12003                   this._context.moveTo(x + this._radius, y);
12004
12005                   this._context.arc(x, y, this._radius, 0, tau);
12006
12007                   break;
12008                 }
12009             }
12010           },
12011           result: noop$1
12012         };
12013
12014         var lengthSum = new Adder(),
12015             lengthRing,
12016             x00,
12017             y00,
12018             x0,
12019             y0;
12020         var lengthStream = {
12021           point: noop$1,
12022           lineStart: function lineStart() {
12023             lengthStream.point = lengthPointFirst;
12024           },
12025           lineEnd: function lineEnd() {
12026             if (lengthRing) lengthPoint(x00, y00);
12027             lengthStream.point = noop$1;
12028           },
12029           polygonStart: function polygonStart() {
12030             lengthRing = true;
12031           },
12032           polygonEnd: function polygonEnd() {
12033             lengthRing = null;
12034           },
12035           result: function result() {
12036             var length = +lengthSum;
12037             lengthSum = new Adder();
12038             return length;
12039           }
12040         };
12041
12042         function lengthPointFirst(x, y) {
12043           lengthStream.point = lengthPoint;
12044           x00 = x0 = x, y00 = y0 = y;
12045         }
12046
12047         function lengthPoint(x, y) {
12048           x0 -= x, y0 -= y;
12049           lengthSum.add(sqrt(x0 * x0 + y0 * y0));
12050           x0 = x, y0 = y;
12051         }
12052
12053         function PathString() {
12054           this._string = [];
12055         }
12056         PathString.prototype = {
12057           _radius: 4.5,
12058           _circle: circle(4.5),
12059           pointRadius: function pointRadius(_) {
12060             if ((_ = +_) !== this._radius) this._radius = _, this._circle = null;
12061             return this;
12062           },
12063           polygonStart: function polygonStart() {
12064             this._line = 0;
12065           },
12066           polygonEnd: function polygonEnd() {
12067             this._line = NaN;
12068           },
12069           lineStart: function lineStart() {
12070             this._point = 0;
12071           },
12072           lineEnd: function lineEnd() {
12073             if (this._line === 0) this._string.push("Z");
12074             this._point = NaN;
12075           },
12076           point: function point(x, y) {
12077             switch (this._point) {
12078               case 0:
12079                 {
12080                   this._string.push("M", x, ",", y);
12081
12082                   this._point = 1;
12083                   break;
12084                 }
12085
12086               case 1:
12087                 {
12088                   this._string.push("L", x, ",", y);
12089
12090                   break;
12091                 }
12092
12093               default:
12094                 {
12095                   if (this._circle == null) this._circle = circle(this._radius);
12096
12097                   this._string.push("M", x, ",", y, this._circle);
12098
12099                   break;
12100                 }
12101             }
12102           },
12103           result: function result() {
12104             if (this._string.length) {
12105               var result = this._string.join("");
12106
12107               this._string = [];
12108               return result;
12109             } else {
12110               return null;
12111             }
12112           }
12113         };
12114
12115         function circle(radius) {
12116           return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z";
12117         }
12118
12119         function d3_geoPath (projection, context) {
12120           var pointRadius = 4.5,
12121               projectionStream,
12122               contextStream;
12123
12124           function path(object) {
12125             if (object) {
12126               if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
12127               d3_geoStream(object, projectionStream(contextStream));
12128             }
12129
12130             return contextStream.result();
12131           }
12132
12133           path.area = function (object) {
12134             d3_geoStream(object, projectionStream(areaStream));
12135             return areaStream.result();
12136           };
12137
12138           path.measure = function (object) {
12139             d3_geoStream(object, projectionStream(lengthStream));
12140             return lengthStream.result();
12141           };
12142
12143           path.bounds = function (object) {
12144             d3_geoStream(object, projectionStream(boundsStream));
12145             return boundsStream.result();
12146           };
12147
12148           path.centroid = function (object) {
12149             d3_geoStream(object, projectionStream(centroidStream));
12150             return centroidStream.result();
12151           };
12152
12153           path.projection = function (_) {
12154             return arguments.length ? (projectionStream = _ == null ? (projection = null, identity$4) : (projection = _).stream, path) : projection;
12155           };
12156
12157           path.context = function (_) {
12158             if (!arguments.length) return context;
12159             contextStream = _ == null ? (context = null, new PathString()) : new PathContext(context = _);
12160             if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
12161             return path;
12162           };
12163
12164           path.pointRadius = function (_) {
12165             if (!arguments.length) return pointRadius;
12166             pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
12167             return path;
12168           };
12169
12170           return path.projection(projection).context(context);
12171         }
12172
12173         function d3_geoTransform (methods) {
12174           return {
12175             stream: transformer$1(methods)
12176           };
12177         }
12178         function transformer$1(methods) {
12179           return function (stream) {
12180             var s = new TransformStream();
12181
12182             for (var key in methods) {
12183               s[key] = methods[key];
12184             }
12185
12186             s.stream = stream;
12187             return s;
12188           };
12189         }
12190
12191         function TransformStream() {}
12192
12193         TransformStream.prototype = {
12194           constructor: TransformStream,
12195           point: function point(x, y) {
12196             this.stream.point(x, y);
12197           },
12198           sphere: function sphere() {
12199             this.stream.sphere();
12200           },
12201           lineStart: function lineStart() {
12202             this.stream.lineStart();
12203           },
12204           lineEnd: function lineEnd() {
12205             this.stream.lineEnd();
12206           },
12207           polygonStart: function polygonStart() {
12208             this.stream.polygonStart();
12209           },
12210           polygonEnd: function polygonEnd() {
12211             this.stream.polygonEnd();
12212           }
12213         };
12214
12215         function fit(projection, fitBounds, object) {
12216           var clip = projection.clipExtent && projection.clipExtent();
12217           projection.scale(150).translate([0, 0]);
12218           if (clip != null) projection.clipExtent(null);
12219           d3_geoStream(object, projection.stream(boundsStream));
12220           fitBounds(boundsStream.result());
12221           if (clip != null) projection.clipExtent(clip);
12222           return projection;
12223         }
12224
12225         function fitExtent(projection, extent, object) {
12226           return fit(projection, function (b) {
12227             var w = extent[1][0] - extent[0][0],
12228                 h = extent[1][1] - extent[0][1],
12229                 k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])),
12230                 x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2,
12231                 y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2;
12232             projection.scale(150 * k).translate([x, y]);
12233           }, object);
12234         }
12235         function fitSize(projection, size, object) {
12236           return fitExtent(projection, [[0, 0], size], object);
12237         }
12238         function fitWidth(projection, width, object) {
12239           return fit(projection, function (b) {
12240             var w = +width,
12241                 k = w / (b[1][0] - b[0][0]),
12242                 x = (w - k * (b[1][0] + b[0][0])) / 2,
12243                 y = -k * b[0][1];
12244             projection.scale(150 * k).translate([x, y]);
12245           }, object);
12246         }
12247         function fitHeight(projection, height, object) {
12248           return fit(projection, function (b) {
12249             var h = +height,
12250                 k = h / (b[1][1] - b[0][1]),
12251                 x = -k * b[0][0],
12252                 y = (h - k * (b[1][1] + b[0][1])) / 2;
12253             projection.scale(150 * k).translate([x, y]);
12254           }, object);
12255         }
12256
12257         var maxDepth = 16,
12258             // maximum depth of subdivision
12259         cosMinDistance = cos(30 * radians); // cos(minimum angular distance)
12260
12261         function resample (project, delta2) {
12262           return +delta2 ? resample$1(project, delta2) : resampleNone(project);
12263         }
12264
12265         function resampleNone(project) {
12266           return transformer$1({
12267             point: function point(x, y) {
12268               x = project(x, y);
12269               this.stream.point(x[0], x[1]);
12270             }
12271           });
12272         }
12273
12274         function resample$1(project, delta2) {
12275           function resampleLineTo(x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) {
12276             var dx = x1 - x0,
12277                 dy = y1 - y0,
12278                 d2 = dx * dx + dy * dy;
12279
12280             if (d2 > 4 * delta2 && depth--) {
12281               var a = a0 + a1,
12282                   b = b0 + b1,
12283                   c = c0 + c1,
12284                   m = sqrt(a * a + b * b + c * c),
12285                   phi2 = asin(c /= m),
12286                   lambda2 = abs$2(abs$2(c) - 1) < epsilon$1 || abs$2(lambda0 - lambda1) < epsilon$1 ? (lambda0 + lambda1) / 2 : atan2(b, a),
12287                   p = project(lambda2, phi2),
12288                   x2 = p[0],
12289                   y2 = p[1],
12290                   dx2 = x2 - x0,
12291                   dy2 = y2 - y0,
12292                   dz = dy * dx2 - dx * dy2;
12293
12294               if (dz * dz / d2 > delta2 // perpendicular projected distance
12295               || abs$2((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end
12296               || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) {
12297                 // angular distance
12298                 resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream);
12299                 stream.point(x2, y2);
12300                 resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream);
12301               }
12302             }
12303           }
12304
12305           return function (stream) {
12306             var lambda00, x00, y00, a00, b00, c00, // first point
12307             lambda0, x0, y0, a0, b0, c0; // previous point
12308
12309             var resampleStream = {
12310               point: point,
12311               lineStart: lineStart,
12312               lineEnd: lineEnd,
12313               polygonStart: function polygonStart() {
12314                 stream.polygonStart();
12315                 resampleStream.lineStart = ringStart;
12316               },
12317               polygonEnd: function polygonEnd() {
12318                 stream.polygonEnd();
12319                 resampleStream.lineStart = lineStart;
12320               }
12321             };
12322
12323             function point(x, y) {
12324               x = project(x, y);
12325               stream.point(x[0], x[1]);
12326             }
12327
12328             function lineStart() {
12329               x0 = NaN;
12330               resampleStream.point = linePoint;
12331               stream.lineStart();
12332             }
12333
12334             function linePoint(lambda, phi) {
12335               var c = cartesian([lambda, phi]),
12336                   p = project(lambda, phi);
12337               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);
12338               stream.point(x0, y0);
12339             }
12340
12341             function lineEnd() {
12342               resampleStream.point = point;
12343               stream.lineEnd();
12344             }
12345
12346             function ringStart() {
12347               lineStart();
12348               resampleStream.point = ringPoint;
12349               resampleStream.lineEnd = ringEnd;
12350             }
12351
12352             function ringPoint(lambda, phi) {
12353               linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
12354               resampleStream.point = linePoint;
12355             }
12356
12357             function ringEnd() {
12358               resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream);
12359               resampleStream.lineEnd = lineEnd;
12360               lineEnd();
12361             }
12362
12363             return resampleStream;
12364           };
12365         }
12366
12367         var transformRadians = transformer$1({
12368           point: function point(x, y) {
12369             this.stream.point(x * radians, y * radians);
12370           }
12371         });
12372
12373         function transformRotate(rotate) {
12374           return transformer$1({
12375             point: function point(x, y) {
12376               var r = rotate(x, y);
12377               return this.stream.point(r[0], r[1]);
12378             }
12379           });
12380         }
12381
12382         function scaleTranslate(k, dx, dy, sx, sy) {
12383           function transform(x, y) {
12384             x *= sx;
12385             y *= sy;
12386             return [dx + k * x, dy - k * y];
12387           }
12388
12389           transform.invert = function (x, y) {
12390             return [(x - dx) / k * sx, (dy - y) / k * sy];
12391           };
12392
12393           return transform;
12394         }
12395
12396         function scaleTranslateRotate(k, dx, dy, sx, sy, alpha) {
12397           if (!alpha) return scaleTranslate(k, dx, dy, sx, sy);
12398           var cosAlpha = cos(alpha),
12399               sinAlpha = sin(alpha),
12400               a = cosAlpha * k,
12401               b = sinAlpha * k,
12402               ai = cosAlpha / k,
12403               bi = sinAlpha / k,
12404               ci = (sinAlpha * dy - cosAlpha * dx) / k,
12405               fi = (sinAlpha * dx + cosAlpha * dy) / k;
12406
12407           function transform(x, y) {
12408             x *= sx;
12409             y *= sy;
12410             return [a * x - b * y + dx, dy - b * x - a * y];
12411           }
12412
12413           transform.invert = function (x, y) {
12414             return [sx * (ai * x - bi * y + ci), sy * (fi - bi * x - ai * y)];
12415           };
12416
12417           return transform;
12418         }
12419
12420         function projection(project) {
12421           return projectionMutator(function () {
12422             return project;
12423           })();
12424         }
12425         function projectionMutator(projectAt) {
12426           var project,
12427               k = 150,
12428               // scale
12429           x = 480,
12430               y = 250,
12431               // translate
12432           lambda = 0,
12433               phi = 0,
12434               // center
12435           deltaLambda = 0,
12436               deltaPhi = 0,
12437               deltaGamma = 0,
12438               rotate,
12439               // pre-rotate
12440           alpha = 0,
12441               // post-rotate angle
12442           sx = 1,
12443               // reflectX
12444           sy = 1,
12445               // reflectX
12446           theta = null,
12447               preclip = clipAntimeridian,
12448               // pre-clip angle
12449           x0 = null,
12450               y0,
12451               x1,
12452               y1,
12453               postclip = identity$4,
12454               // post-clip extent
12455           delta2 = 0.5,
12456               // precision
12457           projectResample,
12458               projectTransform,
12459               projectRotateTransform,
12460               cache,
12461               cacheStream;
12462
12463           function projection(point) {
12464             return projectRotateTransform(point[0] * radians, point[1] * radians);
12465           }
12466
12467           function invert(point) {
12468             point = projectRotateTransform.invert(point[0], point[1]);
12469             return point && [point[0] * degrees$1, point[1] * degrees$1];
12470           }
12471
12472           projection.stream = function (stream) {
12473             return cache && cacheStream === stream ? cache : cache = transformRadians(transformRotate(rotate)(preclip(projectResample(postclip(cacheStream = stream)))));
12474           };
12475
12476           projection.preclip = function (_) {
12477             return arguments.length ? (preclip = _, theta = undefined, reset()) : preclip;
12478           };
12479
12480           projection.postclip = function (_) {
12481             return arguments.length ? (postclip = _, x0 = y0 = x1 = y1 = null, reset()) : postclip;
12482           };
12483
12484           projection.clipAngle = function (_) {
12485             return arguments.length ? (preclip = +_ ? clipCircle(theta = _ * radians) : (theta = null, clipAntimeridian), reset()) : theta * degrees$1;
12486           };
12487
12488           projection.clipExtent = function (_) {
12489             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]];
12490           };
12491
12492           projection.scale = function (_) {
12493             return arguments.length ? (k = +_, recenter()) : k;
12494           };
12495
12496           projection.translate = function (_) {
12497             return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y];
12498           };
12499
12500           projection.center = function (_) {
12501             return arguments.length ? (lambda = _[0] % 360 * radians, phi = _[1] % 360 * radians, recenter()) : [lambda * degrees$1, phi * degrees$1];
12502           };
12503
12504           projection.rotate = function (_) {
12505             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];
12506           };
12507
12508           projection.angle = function (_) {
12509             return arguments.length ? (alpha = _ % 360 * radians, recenter()) : alpha * degrees$1;
12510           };
12511
12512           projection.reflectX = function (_) {
12513             return arguments.length ? (sx = _ ? -1 : 1, recenter()) : sx < 0;
12514           };
12515
12516           projection.reflectY = function (_) {
12517             return arguments.length ? (sy = _ ? -1 : 1, recenter()) : sy < 0;
12518           };
12519
12520           projection.precision = function (_) {
12521             return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt(delta2);
12522           };
12523
12524           projection.fitExtent = function (extent, object) {
12525             return fitExtent(projection, extent, object);
12526           };
12527
12528           projection.fitSize = function (size, object) {
12529             return fitSize(projection, size, object);
12530           };
12531
12532           projection.fitWidth = function (width, object) {
12533             return fitWidth(projection, width, object);
12534           };
12535
12536           projection.fitHeight = function (height, object) {
12537             return fitHeight(projection, height, object);
12538           };
12539
12540           function recenter() {
12541             var center = scaleTranslateRotate(k, 0, 0, sx, sy, alpha).apply(null, project(lambda, phi)),
12542                 transform = scaleTranslateRotate(k, x - center[0], y - center[1], sx, sy, alpha);
12543             rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma);
12544             projectTransform = compose(project, transform);
12545             projectRotateTransform = compose(rotate, projectTransform);
12546             projectResample = resample(projectTransform, delta2);
12547             return reset();
12548           }
12549
12550           function reset() {
12551             cache = cacheStream = null;
12552             return projection;
12553           }
12554
12555           return function () {
12556             project = projectAt.apply(this, arguments);
12557             projection.invert = project.invert && invert;
12558             return recenter();
12559           };
12560         }
12561
12562         function mercatorRaw(lambda, phi) {
12563           return [lambda, log$1(tan((halfPi + phi) / 2))];
12564         }
12565
12566         mercatorRaw.invert = function (x, y) {
12567           return [x, 2 * atan(exp$2(y)) - halfPi];
12568         };
12569
12570         function mercator () {
12571           return mercatorProjection(mercatorRaw).scale(961 / tau);
12572         }
12573         function mercatorProjection(project) {
12574           var m = projection(project),
12575               center = m.center,
12576               scale = m.scale,
12577               translate = m.translate,
12578               clipExtent = m.clipExtent,
12579               x0 = null,
12580               y0,
12581               x1,
12582               y1; // clip extent
12583
12584           m.scale = function (_) {
12585             return arguments.length ? (scale(_), reclip()) : scale();
12586           };
12587
12588           m.translate = function (_) {
12589             return arguments.length ? (translate(_), reclip()) : translate();
12590           };
12591
12592           m.center = function (_) {
12593             return arguments.length ? (center(_), reclip()) : center();
12594           };
12595
12596           m.clipExtent = function (_) {
12597             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]];
12598           };
12599
12600           function reclip() {
12601             var k = pi * scale(),
12602                 t = m(rotation(m.rotate()).invert([0, 0]));
12603             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)]]);
12604           }
12605
12606           return reclip();
12607         }
12608
12609         function d3_geoIdentity () {
12610           var k = 1,
12611               tx = 0,
12612               ty = 0,
12613               sx = 1,
12614               sy = 1,
12615               // scale, translate and reflect
12616           alpha = 0,
12617               ca,
12618               sa,
12619               // angle
12620           x0 = null,
12621               y0,
12622               x1,
12623               y1,
12624               // clip extent
12625           kx = 1,
12626               ky = 1,
12627               transform = transformer$1({
12628             point: function point(x, y) {
12629               var p = projection([x, y]);
12630               this.stream.point(p[0], p[1]);
12631             }
12632           }),
12633               postclip = identity$4,
12634               cache,
12635               cacheStream;
12636
12637           function reset() {
12638             kx = k * sx;
12639             ky = k * sy;
12640             cache = cacheStream = null;
12641             return projection;
12642           }
12643
12644           function projection(p) {
12645             var x = p[0] * kx,
12646                 y = p[1] * ky;
12647
12648             if (alpha) {
12649               var t = y * ca - x * sa;
12650               x = x * ca + y * sa;
12651               y = t;
12652             }
12653
12654             return [x + tx, y + ty];
12655           }
12656
12657           projection.invert = function (p) {
12658             var x = p[0] - tx,
12659                 y = p[1] - ty;
12660
12661             if (alpha) {
12662               var t = y * ca + x * sa;
12663               x = x * ca - y * sa;
12664               y = t;
12665             }
12666
12667             return [x / kx, y / ky];
12668           };
12669
12670           projection.stream = function (stream) {
12671             return cache && cacheStream === stream ? cache : cache = transform(postclip(cacheStream = stream));
12672           };
12673
12674           projection.postclip = function (_) {
12675             return arguments.length ? (postclip = _, x0 = y0 = x1 = y1 = null, reset()) : postclip;
12676           };
12677
12678           projection.clipExtent = function (_) {
12679             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]];
12680           };
12681
12682           projection.scale = function (_) {
12683             return arguments.length ? (k = +_, reset()) : k;
12684           };
12685
12686           projection.translate = function (_) {
12687             return arguments.length ? (tx = +_[0], ty = +_[1], reset()) : [tx, ty];
12688           };
12689
12690           projection.angle = function (_) {
12691             return arguments.length ? (alpha = _ % 360 * radians, sa = sin(alpha), ca = cos(alpha), reset()) : alpha * degrees$1;
12692           };
12693
12694           projection.reflectX = function (_) {
12695             return arguments.length ? (sx = _ ? -1 : 1, reset()) : sx < 0;
12696           };
12697
12698           projection.reflectY = function (_) {
12699             return arguments.length ? (sy = _ ? -1 : 1, reset()) : sy < 0;
12700           };
12701
12702           projection.fitExtent = function (extent, object) {
12703             return fitExtent(projection, extent, object);
12704           };
12705
12706           projection.fitSize = function (size, object) {
12707             return fitSize(projection, size, object);
12708           };
12709
12710           projection.fitWidth = function (width, object) {
12711             return fitWidth(projection, width, object);
12712           };
12713
12714           projection.fitHeight = function (height, object) {
12715             return fitHeight(projection, height, object);
12716           };
12717
12718           return projection;
12719         }
12720
12721         // constants
12722         var TAU = 2 * Math.PI;
12723         var EQUATORIAL_RADIUS = 6356752.314245179;
12724         var POLAR_RADIUS = 6378137.0;
12725         function geoLatToMeters(dLat) {
12726           return dLat * (TAU * POLAR_RADIUS / 360);
12727         }
12728         function geoLonToMeters(dLon, atLat) {
12729           return Math.abs(atLat) >= 90 ? 0 : dLon * (TAU * EQUATORIAL_RADIUS / 360) * Math.abs(Math.cos(atLat * (Math.PI / 180)));
12730         }
12731         function geoMetersToLat(m) {
12732           return m / (TAU * POLAR_RADIUS / 360);
12733         }
12734         function geoMetersToLon(m, atLat) {
12735           return Math.abs(atLat) >= 90 ? 0 : m / (TAU * EQUATORIAL_RADIUS / 360) / Math.abs(Math.cos(atLat * (Math.PI / 180)));
12736         }
12737         function geoMetersToOffset(meters, tileSize) {
12738           tileSize = tileSize || 256;
12739           return [meters[0] * tileSize / (TAU * EQUATORIAL_RADIUS), -meters[1] * tileSize / (TAU * POLAR_RADIUS)];
12740         }
12741         function geoOffsetToMeters(offset, tileSize) {
12742           tileSize = tileSize || 256;
12743           return [offset[0] * TAU * EQUATORIAL_RADIUS / tileSize, -offset[1] * TAU * POLAR_RADIUS / tileSize];
12744         } // Equirectangular approximation of spherical distances on Earth
12745
12746         function geoSphericalDistance(a, b) {
12747           var x = geoLonToMeters(a[0] - b[0], (a[1] + b[1]) / 2);
12748           var y = geoLatToMeters(a[1] - b[1]);
12749           return Math.sqrt(x * x + y * y);
12750         } // scale to zoom
12751
12752         function geoScaleToZoom(k, tileSize) {
12753           tileSize = tileSize || 256;
12754           var log2ts = Math.log(tileSize) * Math.LOG2E;
12755           return Math.log(k * TAU) / Math.LN2 - log2ts;
12756         } // zoom to scale
12757
12758         function geoZoomToScale(z, tileSize) {
12759           tileSize = tileSize || 256;
12760           return tileSize * Math.pow(2, z) / TAU;
12761         } // returns info about the node from `nodes` closest to the given `point`
12762
12763         function geoSphericalClosestNode(nodes, point) {
12764           var minDistance = Infinity,
12765               distance;
12766           var indexOfMin;
12767
12768           for (var i in nodes) {
12769             distance = geoSphericalDistance(nodes[i].loc, point);
12770
12771             if (distance < minDistance) {
12772               minDistance = distance;
12773               indexOfMin = i;
12774             }
12775           }
12776
12777           if (indexOfMin !== undefined) {
12778             return {
12779               index: indexOfMin,
12780               distance: minDistance,
12781               node: nodes[indexOfMin]
12782             };
12783           } else {
12784             return null;
12785           }
12786         }
12787
12788         function geoExtent(min, max) {
12789           if (!(this instanceof geoExtent)) {
12790             return new geoExtent(min, max);
12791           } else if (min instanceof geoExtent) {
12792             return min;
12793           } else if (min && min.length === 2 && min[0].length === 2 && min[1].length === 2) {
12794             this[0] = min[0];
12795             this[1] = min[1];
12796           } else {
12797             this[0] = min || [Infinity, Infinity];
12798             this[1] = max || min || [-Infinity, -Infinity];
12799           }
12800         }
12801         geoExtent.prototype = new Array(2);
12802         Object.assign(geoExtent.prototype, {
12803           equals: function equals(obj) {
12804             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];
12805           },
12806           extend: function extend(obj) {
12807             if (!(obj instanceof geoExtent)) obj = new geoExtent(obj);
12808             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])]);
12809           },
12810           _extend: function _extend(extent) {
12811             this[0][0] = Math.min(extent[0][0], this[0][0]);
12812             this[0][1] = Math.min(extent[0][1], this[0][1]);
12813             this[1][0] = Math.max(extent[1][0], this[1][0]);
12814             this[1][1] = Math.max(extent[1][1], this[1][1]);
12815           },
12816           area: function area() {
12817             return Math.abs((this[1][0] - this[0][0]) * (this[1][1] - this[0][1]));
12818           },
12819           center: function center() {
12820             return [(this[0][0] + this[1][0]) / 2, (this[0][1] + this[1][1]) / 2];
12821           },
12822           rectangle: function rectangle() {
12823             return [this[0][0], this[0][1], this[1][0], this[1][1]];
12824           },
12825           bbox: function bbox() {
12826             return {
12827               minX: this[0][0],
12828               minY: this[0][1],
12829               maxX: this[1][0],
12830               maxY: this[1][1]
12831             };
12832           },
12833           polygon: function polygon() {
12834             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]]];
12835           },
12836           contains: function contains(obj) {
12837             if (!(obj instanceof geoExtent)) obj = new geoExtent(obj);
12838             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];
12839           },
12840           intersects: function intersects(obj) {
12841             if (!(obj instanceof geoExtent)) obj = new geoExtent(obj);
12842             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];
12843           },
12844           intersection: function intersection(obj) {
12845             if (!this.intersects(obj)) return new geoExtent();
12846             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])]);
12847           },
12848           percentContainedIn: function percentContainedIn(obj) {
12849             if (!(obj instanceof geoExtent)) obj = new geoExtent(obj);
12850             var a1 = this.intersection(obj).area();
12851             var a2 = this.area();
12852
12853             if (a1 === Infinity || a2 === Infinity) {
12854               return 0;
12855             } else if (a1 === 0 || a2 === 0) {
12856               if (obj.contains(this)) {
12857                 return 1;
12858               }
12859
12860               return 0;
12861             } else {
12862               return a1 / a2;
12863             }
12864           },
12865           padByMeters: function padByMeters(meters) {
12866             var dLat = geoMetersToLat(meters);
12867             var dLon = geoMetersToLon(meters, this.center()[1]);
12868             return geoExtent([this[0][0] - dLon, this[0][1] - dLat], [this[1][0] + dLon, this[1][1] + dLat]);
12869           },
12870           toParam: function toParam() {
12871             return this.rectangle().join(',');
12872           }
12873         });
12874
12875         var $$w = _export;
12876         var $every = arrayIteration.every;
12877         var arrayMethodIsStrict$2 = arrayMethodIsStrict$9;
12878
12879         var STRICT_METHOD$2 = arrayMethodIsStrict$2('every');
12880
12881         // `Array.prototype.every` method
12882         // https://tc39.es/ecma262/#sec-array.prototype.every
12883         $$w({ target: 'Array', proto: true, forced: !STRICT_METHOD$2 }, {
12884           every: function every(callbackfn /* , thisArg */) {
12885             return $every(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
12886           }
12887         });
12888
12889         var $$v = _export;
12890         var $reduce = arrayReduce.left;
12891         var arrayMethodIsStrict$1 = arrayMethodIsStrict$9;
12892         var CHROME_VERSION$1 = engineV8Version;
12893         var IS_NODE$1 = engineIsNode;
12894
12895         var STRICT_METHOD$1 = arrayMethodIsStrict$1('reduce');
12896         // Chrome 80-82 has a critical bug
12897         // https://bugs.chromium.org/p/chromium/issues/detail?id=1049982
12898         var CHROME_BUG$1 = !IS_NODE$1 && CHROME_VERSION$1 > 79 && CHROME_VERSION$1 < 83;
12899
12900         // `Array.prototype.reduce` method
12901         // https://tc39.es/ecma262/#sec-array.prototype.reduce
12902         $$v({ target: 'Array', proto: true, forced: !STRICT_METHOD$1 || CHROME_BUG$1 }, {
12903           reduce: function reduce(callbackfn /* , initialValue */) {
12904             var length = arguments.length;
12905             return $reduce(this, callbackfn, length, length > 1 ? arguments[1] : undefined);
12906           }
12907         });
12908
12909         function d3_polygonArea (polygon) {
12910           var i = -1,
12911               n = polygon.length,
12912               a,
12913               b = polygon[n - 1],
12914               area = 0;
12915
12916           while (++i < n) {
12917             a = b;
12918             b = polygon[i];
12919             area += a[1] * b[0] - a[0] * b[1];
12920           }
12921
12922           return area / 2;
12923         }
12924
12925         function d3_polygonCentroid (polygon) {
12926           var i = -1,
12927               n = polygon.length,
12928               x = 0,
12929               y = 0,
12930               a,
12931               b = polygon[n - 1],
12932               c,
12933               k = 0;
12934
12935           while (++i < n) {
12936             a = b;
12937             b = polygon[i];
12938             k += c = a[0] * b[1] - b[0] * a[1];
12939             x += (a[0] + b[0]) * c;
12940             y += (a[1] + b[1]) * c;
12941           }
12942
12943           return k *= 3, [x / k, y / k];
12944         }
12945
12946         // Returns the 2D cross product of AB and AC vectors, i.e., the z-component of
12947         // the 3D cross product in a quadrant I Cartesian coordinate system (+x is
12948         // right, +y is up). Returns a positive value if ABC is counter-clockwise,
12949         // negative if clockwise, and zero if the points are collinear.
12950         function cross (a, b, c) {
12951           return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
12952         }
12953
12954         function lexicographicOrder(a, b) {
12955           return a[0] - b[0] || a[1] - b[1];
12956         } // Computes the upper convex hull per the monotone chain algorithm.
12957         // Assumes points.length >= 3, is sorted by x, unique in y.
12958         // Returns an array of indices into points in left-to-right order.
12959
12960
12961         function computeUpperHullIndexes(points) {
12962           var n = points.length,
12963               indexes = [0, 1];
12964           var size = 2,
12965               i;
12966
12967           for (i = 2; i < n; ++i) {
12968             while (size > 1 && cross(points[indexes[size - 2]], points[indexes[size - 1]], points[i]) <= 0) {
12969               --size;
12970             }
12971
12972             indexes[size++] = i;
12973           }
12974
12975           return indexes.slice(0, size); // remove popped points
12976         }
12977
12978         function d3_polygonHull (points) {
12979           if ((n = points.length) < 3) return null;
12980           var i,
12981               n,
12982               sortedPoints = new Array(n),
12983               flippedPoints = new Array(n);
12984
12985           for (i = 0; i < n; ++i) {
12986             sortedPoints[i] = [+points[i][0], +points[i][1], i];
12987           }
12988
12989           sortedPoints.sort(lexicographicOrder);
12990
12991           for (i = 0; i < n; ++i) {
12992             flippedPoints[i] = [sortedPoints[i][0], -sortedPoints[i][1]];
12993           }
12994
12995           var upperIndexes = computeUpperHullIndexes(sortedPoints),
12996               lowerIndexes = computeUpperHullIndexes(flippedPoints); // Construct the hull polygon, removing possible duplicate endpoints.
12997
12998           var skipLeft = lowerIndexes[0] === upperIndexes[0],
12999               skipRight = lowerIndexes[lowerIndexes.length - 1] === upperIndexes[upperIndexes.length - 1],
13000               hull = []; // Add upper hull in right-to-l order.
13001           // Then add lower hull in left-to-right order.
13002
13003           for (i = upperIndexes.length - 1; i >= 0; --i) {
13004             hull.push(points[sortedPoints[upperIndexes[i]][2]]);
13005           }
13006
13007           for (i = +skipLeft; i < lowerIndexes.length - skipRight; ++i) {
13008             hull.push(points[sortedPoints[lowerIndexes[i]][2]]);
13009           }
13010
13011           return hull;
13012         }
13013
13014         // vector equals
13015         function geoVecEqual(a, b, epsilon) {
13016           if (epsilon) {
13017             return Math.abs(a[0] - b[0]) <= epsilon && Math.abs(a[1] - b[1]) <= epsilon;
13018           } else {
13019             return a[0] === b[0] && a[1] === b[1];
13020           }
13021         } // vector addition
13022
13023         function geoVecAdd(a, b) {
13024           return [a[0] + b[0], a[1] + b[1]];
13025         } // vector subtraction
13026
13027         function geoVecSubtract(a, b) {
13028           return [a[0] - b[0], a[1] - b[1]];
13029         } // vector scaling
13030
13031         function geoVecScale(a, mag) {
13032           return [a[0] * mag, a[1] * mag];
13033         } // vector rounding (was: geoRoundCoordinates)
13034
13035         function geoVecFloor(a) {
13036           return [Math.floor(a[0]), Math.floor(a[1])];
13037         } // linear interpolation
13038
13039         function geoVecInterp(a, b, t) {
13040           return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];
13041         } // http://jsperf.com/id-dist-optimization
13042
13043         function geoVecLength(a, b) {
13044           return Math.sqrt(geoVecLengthSquare(a, b));
13045         } // length of vector raised to the power two
13046
13047         function geoVecLengthSquare(a, b) {
13048           b = b || [0, 0];
13049           var x = a[0] - b[0];
13050           var y = a[1] - b[1];
13051           return x * x + y * y;
13052         } // get a unit vector
13053
13054         function geoVecNormalize(a) {
13055           var length = Math.sqrt(a[0] * a[0] + a[1] * a[1]);
13056
13057           if (length !== 0) {
13058             return geoVecScale(a, 1 / length);
13059           }
13060
13061           return [0, 0];
13062         } // Return the counterclockwise angle in the range (-pi, pi)
13063         // between the positive X axis and the line intersecting a and b.
13064
13065         function geoVecAngle(a, b) {
13066           return Math.atan2(b[1] - a[1], b[0] - a[0]);
13067         } // dot product
13068
13069         function geoVecDot(a, b, origin) {
13070           origin = origin || [0, 0];
13071           var p = geoVecSubtract(a, origin);
13072           var q = geoVecSubtract(b, origin);
13073           return p[0] * q[0] + p[1] * q[1];
13074         } // normalized dot product
13075
13076         function geoVecNormalizedDot(a, b, origin) {
13077           origin = origin || [0, 0];
13078           var p = geoVecNormalize(geoVecSubtract(a, origin));
13079           var q = geoVecNormalize(geoVecSubtract(b, origin));
13080           return geoVecDot(p, q);
13081         } // 2D cross product of OA and OB vectors, returns magnitude of Z vector
13082         // Returns a positive value, if OAB makes a counter-clockwise turn,
13083         // negative for clockwise turn, and zero if the points are collinear.
13084
13085         function geoVecCross(a, b, origin) {
13086           origin = origin || [0, 0];
13087           var p = geoVecSubtract(a, origin);
13088           var q = geoVecSubtract(b, origin);
13089           return p[0] * q[1] - p[1] * q[0];
13090         } // find closest orthogonal projection of point onto points array
13091
13092         function geoVecProject(a, points) {
13093           var min = Infinity;
13094           var idx;
13095           var target;
13096
13097           for (var i = 0; i < points.length - 1; i++) {
13098             var o = points[i];
13099             var s = geoVecSubtract(points[i + 1], o);
13100             var v = geoVecSubtract(a, o);
13101             var proj = geoVecDot(v, s) / geoVecDot(s, s);
13102             var p;
13103
13104             if (proj < 0) {
13105               p = o;
13106             } else if (proj > 1) {
13107               p = points[i + 1];
13108             } else {
13109               p = [o[0] + proj * s[0], o[1] + proj * s[1]];
13110             }
13111
13112             var dist = geoVecLength(p, a);
13113
13114             if (dist < min) {
13115               min = dist;
13116               idx = i + 1;
13117               target = p;
13118             }
13119           }
13120
13121           if (idx !== undefined) {
13122             return {
13123               index: idx,
13124               distance: min,
13125               target: target
13126             };
13127           } else {
13128             return null;
13129           }
13130         }
13131
13132         // between the positive X axis and the line intersecting a and b.
13133
13134         function geoAngle(a, b, projection) {
13135           return geoVecAngle(projection(a.loc), projection(b.loc));
13136         }
13137         function geoEdgeEqual(a, b) {
13138           return a[0] === b[0] && a[1] === b[1] || a[0] === b[1] && a[1] === b[0];
13139         } // Rotate all points counterclockwise around a pivot point by given angle
13140
13141         function geoRotate(points, angle, around) {
13142           return points.map(function (point) {
13143             var radial = geoVecSubtract(point, around);
13144             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]];
13145           });
13146         } // Choose the edge with the minimal distance from `point` to its orthogonal
13147         // projection onto that edge, if such a projection exists, or the distance to
13148         // the closest vertex on that edge. Returns an object with the `index` of the
13149         // chosen edge, the chosen `loc` on that edge, and the `distance` to to it.
13150
13151         function geoChooseEdge(nodes, point, projection, activeID) {
13152           var dist = geoVecLength;
13153           var points = nodes.map(function (n) {
13154             return projection(n.loc);
13155           });
13156           var ids = nodes.map(function (n) {
13157             return n.id;
13158           });
13159           var min = Infinity;
13160           var idx;
13161           var loc;
13162
13163           for (var i = 0; i < points.length - 1; i++) {
13164             if (ids[i] === activeID || ids[i + 1] === activeID) continue;
13165             var o = points[i];
13166             var s = geoVecSubtract(points[i + 1], o);
13167             var v = geoVecSubtract(point, o);
13168             var proj = geoVecDot(v, s) / geoVecDot(s, s);
13169             var p;
13170
13171             if (proj < 0) {
13172               p = o;
13173             } else if (proj > 1) {
13174               p = points[i + 1];
13175             } else {
13176               p = [o[0] + proj * s[0], o[1] + proj * s[1]];
13177             }
13178
13179             var d = dist(p, point);
13180
13181             if (d < min) {
13182               min = d;
13183               idx = i + 1;
13184               loc = projection.invert(p);
13185             }
13186           }
13187
13188           if (idx !== undefined) {
13189             return {
13190               index: idx,
13191               distance: min,
13192               loc: loc
13193             };
13194           } else {
13195             return null;
13196           }
13197         } // Test active (dragged or drawing) segments against inactive segments
13198         // This is used to test e.g. multipolygon rings that cross
13199         // `activeNodes` is the ring containing the activeID being dragged.
13200         // `inactiveNodes` is the other ring to test against
13201
13202         function geoHasLineIntersections(activeNodes, inactiveNodes, activeID) {
13203           var actives = [];
13204           var inactives = [];
13205           var j, k, n1, n2, segment; // gather active segments (only segments in activeNodes that contain the activeID)
13206
13207           for (j = 0; j < activeNodes.length - 1; j++) {
13208             n1 = activeNodes[j];
13209             n2 = activeNodes[j + 1];
13210             segment = [n1.loc, n2.loc];
13211
13212             if (n1.id === activeID || n2.id === activeID) {
13213               actives.push(segment);
13214             }
13215           } // gather inactive segments
13216
13217
13218           for (j = 0; j < inactiveNodes.length - 1; j++) {
13219             n1 = inactiveNodes[j];
13220             n2 = inactiveNodes[j + 1];
13221             segment = [n1.loc, n2.loc];
13222             inactives.push(segment);
13223           } // test
13224
13225
13226           for (j = 0; j < actives.length; j++) {
13227             for (k = 0; k < inactives.length; k++) {
13228               var p = actives[j];
13229               var q = inactives[k];
13230               var hit = geoLineIntersection(p, q);
13231
13232               if (hit) {
13233                 return true;
13234               }
13235             }
13236           }
13237
13238           return false;
13239         } // Test active (dragged or drawing) segments against inactive segments
13240         // This is used to test whether a way intersects with itself.
13241
13242         function geoHasSelfIntersections(nodes, activeID) {
13243           var actives = [];
13244           var inactives = [];
13245           var j, k; // group active and passive segments along the nodes
13246
13247           for (j = 0; j < nodes.length - 1; j++) {
13248             var n1 = nodes[j];
13249             var n2 = nodes[j + 1];
13250             var segment = [n1.loc, n2.loc];
13251
13252             if (n1.id === activeID || n2.id === activeID) {
13253               actives.push(segment);
13254             } else {
13255               inactives.push(segment);
13256             }
13257           } // test
13258
13259
13260           for (j = 0; j < actives.length; j++) {
13261             for (k = 0; k < inactives.length; k++) {
13262               var p = actives[j];
13263               var q = inactives[k]; // skip if segments share an endpoint
13264
13265               if (geoVecEqual(p[1], q[0]) || geoVecEqual(p[0], q[1]) || geoVecEqual(p[0], q[0]) || geoVecEqual(p[1], q[1])) {
13266                 continue;
13267               }
13268
13269               var hit = geoLineIntersection(p, q);
13270
13271               if (hit) {
13272                 var epsilon = 1e-8; // skip if the hit is at the segment's endpoint
13273
13274                 if (geoVecEqual(p[1], hit, epsilon) || geoVecEqual(p[0], hit, epsilon) || geoVecEqual(q[1], hit, epsilon) || geoVecEqual(q[0], hit, epsilon)) {
13275                   continue;
13276                 } else {
13277                   return true;
13278                 }
13279               }
13280             }
13281           }
13282
13283           return false;
13284         } // Return the intersection point of 2 line segments.
13285         // From https://github.com/pgkelley4/line-segments-intersect
13286         // This uses the vector cross product approach described below:
13287         //  http://stackoverflow.com/a/565282/786339
13288
13289         function geoLineIntersection(a, b) {
13290           var p = [a[0][0], a[0][1]];
13291           var p2 = [a[1][0], a[1][1]];
13292           var q = [b[0][0], b[0][1]];
13293           var q2 = [b[1][0], b[1][1]];
13294           var r = geoVecSubtract(p2, p);
13295           var s = geoVecSubtract(q2, q);
13296           var uNumerator = geoVecCross(geoVecSubtract(q, p), r);
13297           var denominator = geoVecCross(r, s);
13298
13299           if (uNumerator && denominator) {
13300             var u = uNumerator / denominator;
13301             var t = geoVecCross(geoVecSubtract(q, p), s) / denominator;
13302
13303             if (t >= 0 && t <= 1 && u >= 0 && u <= 1) {
13304               return geoVecInterp(p, p2, t);
13305             }
13306           }
13307
13308           return null;
13309         }
13310         function geoPathIntersections(path1, path2) {
13311           var intersections = [];
13312
13313           for (var i = 0; i < path1.length - 1; i++) {
13314             for (var j = 0; j < path2.length - 1; j++) {
13315               var a = [path1[i], path1[i + 1]];
13316               var b = [path2[j], path2[j + 1]];
13317               var hit = geoLineIntersection(a, b);
13318
13319               if (hit) {
13320                 intersections.push(hit);
13321               }
13322             }
13323           }
13324
13325           return intersections;
13326         }
13327         function geoPathHasIntersections(path1, path2) {
13328           for (var i = 0; i < path1.length - 1; i++) {
13329             for (var j = 0; j < path2.length - 1; j++) {
13330               var a = [path1[i], path1[i + 1]];
13331               var b = [path2[j], path2[j + 1]];
13332               var hit = geoLineIntersection(a, b);
13333
13334               if (hit) {
13335                 return true;
13336               }
13337             }
13338           }
13339
13340           return false;
13341         } // Return whether point is contained in polygon.
13342         //
13343         // `point` should be a 2-item array of coordinates.
13344         // `polygon` should be an array of 2-item arrays of coordinates.
13345         //
13346         // From https://github.com/substack/point-in-polygon.
13347         // ray-casting algorithm based on
13348         // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
13349         //
13350
13351         function geoPointInPolygon(point, polygon) {
13352           var x = point[0];
13353           var y = point[1];
13354           var inside = false;
13355
13356           for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
13357             var xi = polygon[i][0];
13358             var yi = polygon[i][1];
13359             var xj = polygon[j][0];
13360             var yj = polygon[j][1];
13361             var intersect = yi > y !== yj > y && x < (xj - xi) * (y - yi) / (yj - yi) + xi;
13362             if (intersect) inside = !inside;
13363           }
13364
13365           return inside;
13366         }
13367         function geoPolygonContainsPolygon(outer, inner) {
13368           return inner.every(function (point) {
13369             return geoPointInPolygon(point, outer);
13370           });
13371         }
13372         function geoPolygonIntersectsPolygon(outer, inner, checkSegments) {
13373           function testPoints(outer, inner) {
13374             return inner.some(function (point) {
13375               return geoPointInPolygon(point, outer);
13376             });
13377           }
13378
13379           return testPoints(outer, inner) || !!checkSegments && geoPathHasIntersections(outer, inner);
13380         } // http://gis.stackexchange.com/questions/22895/finding-minimum-area-rectangle-for-given-points
13381         // http://gis.stackexchange.com/questions/3739/generalisation-strategies-for-building-outlines/3756#3756
13382
13383         function geoGetSmallestSurroundingRectangle(points) {
13384           var hull = d3_polygonHull(points);
13385           var centroid = d3_polygonCentroid(hull);
13386           var minArea = Infinity;
13387           var ssrExtent = [];
13388           var ssrAngle = 0;
13389           var c1 = hull[0];
13390
13391           for (var i = 0; i <= hull.length - 1; i++) {
13392             var c2 = i === hull.length - 1 ? hull[0] : hull[i + 1];
13393             var angle = Math.atan2(c2[1] - c1[1], c2[0] - c1[0]);
13394             var poly = geoRotate(hull, -angle, centroid);
13395             var extent = poly.reduce(function (extent, point) {
13396               return extent.extend(geoExtent(point));
13397             }, geoExtent());
13398             var area = extent.area();
13399
13400             if (area < minArea) {
13401               minArea = area;
13402               ssrExtent = extent;
13403               ssrAngle = angle;
13404             }
13405
13406             c1 = c2;
13407           }
13408
13409           return {
13410             poly: geoRotate(ssrExtent.polygon(), ssrAngle, centroid),
13411             angle: ssrAngle
13412           };
13413         }
13414         function geoPathLength(path) {
13415           var length = 0;
13416
13417           for (var i = 0; i < path.length - 1; i++) {
13418             length += geoVecLength(path[i], path[i + 1]);
13419           }
13420
13421           return length;
13422         } // If the given point is at the edge of the padded viewport,
13423         // return a vector that will nudge the viewport in that direction
13424
13425         function geoViewportEdge(point, dimensions) {
13426           var pad = [80, 20, 50, 20]; // top, right, bottom, left
13427
13428           var x = 0;
13429           var y = 0;
13430
13431           if (point[0] > dimensions[0] - pad[1]) {
13432             x = -10;
13433           }
13434
13435           if (point[0] < pad[3]) {
13436             x = 10;
13437           }
13438
13439           if (point[1] > dimensions[1] - pad[2]) {
13440             y = -10;
13441           }
13442
13443           if (point[1] < pad[0]) {
13444             y = 10;
13445           }
13446
13447           if (x || y) {
13448             return [x, y];
13449           } else {
13450             return null;
13451           }
13452         }
13453
13454         var noop = {
13455           value: function value() {}
13456         };
13457
13458         function dispatch$8() {
13459           for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) {
13460             if (!(t = arguments[i] + "") || t in _ || /[\s.]/.test(t)) throw new Error("illegal type: " + t);
13461             _[t] = [];
13462           }
13463
13464           return new Dispatch(_);
13465         }
13466
13467         function Dispatch(_) {
13468           this._ = _;
13469         }
13470
13471         function parseTypenames$1(typenames, types) {
13472           return typenames.trim().split(/^|\s+/).map(function (t) {
13473             var name = "",
13474                 i = t.indexOf(".");
13475             if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
13476             if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t);
13477             return {
13478               type: t,
13479               name: name
13480             };
13481           });
13482         }
13483
13484         Dispatch.prototype = dispatch$8.prototype = {
13485           constructor: Dispatch,
13486           on: function on(typename, callback) {
13487             var _ = this._,
13488                 T = parseTypenames$1(typename + "", _),
13489                 t,
13490                 i = -1,
13491                 n = T.length; // If no callback was specified, return the callback of the given type and name.
13492
13493             if (arguments.length < 2) {
13494               while (++i < n) {
13495                 if ((t = (typename = T[i]).type) && (t = get$2(_[t], typename.name))) return t;
13496               }
13497
13498               return;
13499             } // If a type was specified, set the callback for the given type and name.
13500             // Otherwise, if a null callback was specified, remove callbacks of the given name.
13501
13502
13503             if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback);
13504
13505             while (++i < n) {
13506               if (t = (typename = T[i]).type) _[t] = set$1(_[t], typename.name, callback);else if (callback == null) for (t in _) {
13507                 _[t] = set$1(_[t], typename.name, null);
13508               }
13509             }
13510
13511             return this;
13512           },
13513           copy: function copy() {
13514             var copy = {},
13515                 _ = this._;
13516
13517             for (var t in _) {
13518               copy[t] = _[t].slice();
13519             }
13520
13521             return new Dispatch(copy);
13522           },
13523           call: function call(type, that) {
13524             if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) {
13525               args[i] = arguments[i + 2];
13526             }
13527             if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
13528
13529             for (t = this._[type], i = 0, n = t.length; i < n; ++i) {
13530               t[i].value.apply(that, args);
13531             }
13532           },
13533           apply: function apply(type, that, args) {
13534             if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
13535
13536             for (var t = this._[type], i = 0, n = t.length; i < n; ++i) {
13537               t[i].value.apply(that, args);
13538             }
13539           }
13540         };
13541
13542         function get$2(type, name) {
13543           for (var i = 0, n = type.length, c; i < n; ++i) {
13544             if ((c = type[i]).name === name) {
13545               return c.value;
13546             }
13547           }
13548         }
13549
13550         function set$1(type, name, callback) {
13551           for (var i = 0, n = type.length; i < n; ++i) {
13552             if (type[i].name === name) {
13553               type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1));
13554               break;
13555             }
13556           }
13557
13558           if (callback != null) type.push({
13559             name: name,
13560             value: callback
13561           });
13562           return type;
13563         }
13564
13565         var xhtml = "http://www.w3.org/1999/xhtml";
13566         var namespaces = {
13567           svg: "http://www.w3.org/2000/svg",
13568           xhtml: xhtml,
13569           xlink: "http://www.w3.org/1999/xlink",
13570           xml: "http://www.w3.org/XML/1998/namespace",
13571           xmlns: "http://www.w3.org/2000/xmlns/"
13572         };
13573
13574         function namespace (name) {
13575           var prefix = name += "",
13576               i = prefix.indexOf(":");
13577           if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1);
13578           return namespaces.hasOwnProperty(prefix) ? {
13579             space: namespaces[prefix],
13580             local: name
13581           } : name; // eslint-disable-line no-prototype-builtins
13582         }
13583
13584         function creatorInherit(name) {
13585           return function () {
13586             var document = this.ownerDocument,
13587                 uri = this.namespaceURI;
13588             return uri === xhtml && document.documentElement.namespaceURI === xhtml ? document.createElement(name) : document.createElementNS(uri, name);
13589           };
13590         }
13591
13592         function creatorFixed(fullname) {
13593           return function () {
13594             return this.ownerDocument.createElementNS(fullname.space, fullname.local);
13595           };
13596         }
13597
13598         function creator (name) {
13599           var fullname = namespace(name);
13600           return (fullname.local ? creatorFixed : creatorInherit)(fullname);
13601         }
13602
13603         function none() {}
13604
13605         function selector (selector) {
13606           return selector == null ? none : function () {
13607             return this.querySelector(selector);
13608           };
13609         }
13610
13611         function selection_select (select) {
13612           if (typeof select !== "function") select = selector(select);
13613
13614           for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
13615             for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
13616               if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
13617                 if ("__data__" in node) subnode.__data__ = node.__data__;
13618                 subgroup[i] = subnode;
13619               }
13620             }
13621           }
13622
13623           return new Selection$1(subgroups, this._parents);
13624         }
13625
13626         function array (x) {
13627           return _typeof(x) === "object" && "length" in x ? x // Array, TypedArray, NodeList, array-like
13628           : Array.from(x); // Map, Set, iterable, string, or anything else
13629         }
13630
13631         function empty() {
13632           return [];
13633         }
13634
13635         function selectorAll (selector) {
13636           return selector == null ? empty : function () {
13637             return this.querySelectorAll(selector);
13638           };
13639         }
13640
13641         function arrayAll(select) {
13642           return function () {
13643             var group = select.apply(this, arguments);
13644             return group == null ? [] : array(group);
13645           };
13646         }
13647
13648         function selection_selectAll (select) {
13649           if (typeof select === "function") select = arrayAll(select);else select = selectorAll(select);
13650
13651           for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
13652             for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
13653               if (node = group[i]) {
13654                 subgroups.push(select.call(node, node.__data__, i, group));
13655                 parents.push(node);
13656               }
13657             }
13658           }
13659
13660           return new Selection$1(subgroups, parents);
13661         }
13662
13663         var $$u = _export;
13664         var $find = arrayIteration.find;
13665         var addToUnscopables$3 = addToUnscopables$6;
13666
13667         var FIND = 'find';
13668         var SKIPS_HOLES$1 = true;
13669
13670         // Shouldn't skip holes
13671         if (FIND in []) Array(1)[FIND](function () { SKIPS_HOLES$1 = false; });
13672
13673         // `Array.prototype.find` method
13674         // https://tc39.es/ecma262/#sec-array.prototype.find
13675         $$u({ target: 'Array', proto: true, forced: SKIPS_HOLES$1 }, {
13676           find: function find(callbackfn /* , that = undefined */) {
13677             return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
13678           }
13679         });
13680
13681         // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
13682         addToUnscopables$3(FIND);
13683
13684         function matcher (selector) {
13685           return function () {
13686             return this.matches(selector);
13687           };
13688         }
13689         function childMatcher(selector) {
13690           return function (node) {
13691             return node.matches(selector);
13692           };
13693         }
13694
13695         var find = Array.prototype.find;
13696
13697         function childFind(match) {
13698           return function () {
13699             return find.call(this.children, match);
13700           };
13701         }
13702
13703         function childFirst() {
13704           return this.firstElementChild;
13705         }
13706
13707         function selection_selectChild (match) {
13708           return this.select(match == null ? childFirst : childFind(typeof match === "function" ? match : childMatcher(match)));
13709         }
13710
13711         var filter = Array.prototype.filter;
13712
13713         function children() {
13714           return this.children;
13715         }
13716
13717         function childrenFilter(match) {
13718           return function () {
13719             return filter.call(this.children, match);
13720           };
13721         }
13722
13723         function selection_selectChildren (match) {
13724           return this.selectAll(match == null ? children : childrenFilter(typeof match === "function" ? match : childMatcher(match)));
13725         }
13726
13727         function selection_filter (match) {
13728           if (typeof match !== "function") match = matcher(match);
13729
13730           for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
13731             for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
13732               if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
13733                 subgroup.push(node);
13734               }
13735             }
13736           }
13737
13738           return new Selection$1(subgroups, this._parents);
13739         }
13740
13741         function sparse (update) {
13742           return new Array(update.length);
13743         }
13744
13745         function selection_enter () {
13746           return new Selection$1(this._enter || this._groups.map(sparse), this._parents);
13747         }
13748         function EnterNode(parent, datum) {
13749           this.ownerDocument = parent.ownerDocument;
13750           this.namespaceURI = parent.namespaceURI;
13751           this._next = null;
13752           this._parent = parent;
13753           this.__data__ = datum;
13754         }
13755         EnterNode.prototype = {
13756           constructor: EnterNode,
13757           appendChild: function appendChild(child) {
13758             return this._parent.insertBefore(child, this._next);
13759           },
13760           insertBefore: function insertBefore(child, next) {
13761             return this._parent.insertBefore(child, next);
13762           },
13763           querySelector: function querySelector(selector) {
13764             return this._parent.querySelector(selector);
13765           },
13766           querySelectorAll: function querySelectorAll(selector) {
13767             return this._parent.querySelectorAll(selector);
13768           }
13769         };
13770
13771         function constant$3 (x) {
13772           return function () {
13773             return x;
13774           };
13775         }
13776
13777         function bindIndex(parent, group, enter, update, exit, data) {
13778           var i = 0,
13779               node,
13780               groupLength = group.length,
13781               dataLength = data.length; // Put any non-null nodes that fit into update.
13782           // Put any null nodes into enter.
13783           // Put any remaining data into enter.
13784
13785           for (; i < dataLength; ++i) {
13786             if (node = group[i]) {
13787               node.__data__ = data[i];
13788               update[i] = node;
13789             } else {
13790               enter[i] = new EnterNode(parent, data[i]);
13791             }
13792           } // Put any non-null nodes that don’t fit into exit.
13793
13794
13795           for (; i < groupLength; ++i) {
13796             if (node = group[i]) {
13797               exit[i] = node;
13798             }
13799           }
13800         }
13801
13802         function bindKey(parent, group, enter, update, exit, data, key) {
13803           var i,
13804               node,
13805               nodeByKeyValue = new Map(),
13806               groupLength = group.length,
13807               dataLength = data.length,
13808               keyValues = new Array(groupLength),
13809               keyValue; // Compute the key for each node.
13810           // If multiple nodes have the same key, the duplicates are added to exit.
13811
13812           for (i = 0; i < groupLength; ++i) {
13813             if (node = group[i]) {
13814               keyValues[i] = keyValue = key.call(node, node.__data__, i, group) + "";
13815
13816               if (nodeByKeyValue.has(keyValue)) {
13817                 exit[i] = node;
13818               } else {
13819                 nodeByKeyValue.set(keyValue, node);
13820               }
13821             }
13822           } // Compute the key for each datum.
13823           // If there a node associated with this key, join and add it to update.
13824           // If there is not (or the key is a duplicate), add it to enter.
13825
13826
13827           for (i = 0; i < dataLength; ++i) {
13828             keyValue = key.call(parent, data[i], i, data) + "";
13829
13830             if (node = nodeByKeyValue.get(keyValue)) {
13831               update[i] = node;
13832               node.__data__ = data[i];
13833               nodeByKeyValue["delete"](keyValue);
13834             } else {
13835               enter[i] = new EnterNode(parent, data[i]);
13836             }
13837           } // Add any remaining nodes that were not bound to data to exit.
13838
13839
13840           for (i = 0; i < groupLength; ++i) {
13841             if ((node = group[i]) && nodeByKeyValue.get(keyValues[i]) === node) {
13842               exit[i] = node;
13843             }
13844           }
13845         }
13846
13847         function datum(node) {
13848           return node.__data__;
13849         }
13850
13851         function selection_data (value, key) {
13852           if (!arguments.length) return Array.from(this, datum);
13853           var bind = key ? bindKey : bindIndex,
13854               parents = this._parents,
13855               groups = this._groups;
13856           if (typeof value !== "function") value = constant$3(value);
13857
13858           for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) {
13859             var parent = parents[j],
13860                 group = groups[j],
13861                 groupLength = group.length,
13862                 data = array(value.call(parent, parent && parent.__data__, j, parents)),
13863                 dataLength = data.length,
13864                 enterGroup = enter[j] = new Array(dataLength),
13865                 updateGroup = update[j] = new Array(dataLength),
13866                 exitGroup = exit[j] = new Array(groupLength);
13867             bind(parent, group, enterGroup, updateGroup, exitGroup, data, key); // Now connect the enter nodes to their following update node, such that
13868             // appendChild can insert the materialized enter node before this node,
13869             // rather than at the end of the parent node.
13870
13871             for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) {
13872               if (previous = enterGroup[i0]) {
13873                 if (i0 >= i1) i1 = i0 + 1;
13874
13875                 while (!(next = updateGroup[i1]) && ++i1 < dataLength) {
13876                 }
13877
13878                 previous._next = next || null;
13879               }
13880             }
13881           }
13882
13883           update = new Selection$1(update, parents);
13884           update._enter = enter;
13885           update._exit = exit;
13886           return update;
13887         }
13888
13889         function selection_exit () {
13890           return new Selection$1(this._exit || this._groups.map(sparse), this._parents);
13891         }
13892
13893         function selection_join (onenter, onupdate, onexit) {
13894           var enter = this.enter(),
13895               update = this,
13896               exit = this.exit();
13897           enter = typeof onenter === "function" ? onenter(enter) : enter.append(onenter + "");
13898           if (onupdate != null) update = onupdate(update);
13899           if (onexit == null) exit.remove();else onexit(exit);
13900           return enter && update ? enter.merge(update).order() : update;
13901         }
13902
13903         function selection_merge (selection) {
13904           if (!(selection instanceof Selection$1)) throw new Error("invalid merge");
13905
13906           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) {
13907             for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
13908               if (node = group0[i] || group1[i]) {
13909                 merge[i] = node;
13910               }
13911             }
13912           }
13913
13914           for (; j < m0; ++j) {
13915             merges[j] = groups0[j];
13916           }
13917
13918           return new Selection$1(merges, this._parents);
13919         }
13920
13921         function selection_order () {
13922           for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) {
13923             for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) {
13924               if (node = group[i]) {
13925                 if (next && node.compareDocumentPosition(next) ^ 4) next.parentNode.insertBefore(node, next);
13926                 next = node;
13927               }
13928             }
13929           }
13930
13931           return this;
13932         }
13933
13934         function selection_sort (compare) {
13935           if (!compare) compare = ascending;
13936
13937           function compareNode(a, b) {
13938             return a && b ? compare(a.__data__, b.__data__) : !a - !b;
13939           }
13940
13941           for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) {
13942             for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) {
13943               if (node = group[i]) {
13944                 sortgroup[i] = node;
13945               }
13946             }
13947
13948             sortgroup.sort(compareNode);
13949           }
13950
13951           return new Selection$1(sortgroups, this._parents).order();
13952         }
13953
13954         function ascending(a, b) {
13955           return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
13956         }
13957
13958         function selection_call () {
13959           var callback = arguments[0];
13960           arguments[0] = this;
13961           callback.apply(null, arguments);
13962           return this;
13963         }
13964
13965         function selection_nodes () {
13966           return Array.from(this);
13967         }
13968
13969         function selection_node () {
13970           for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
13971             for (var group = groups[j], i = 0, n = group.length; i < n; ++i) {
13972               var node = group[i];
13973               if (node) return node;
13974             }
13975           }
13976
13977           return null;
13978         }
13979
13980         function selection_size () {
13981           var size = 0;
13982
13983           var _iterator = _createForOfIteratorHelper(this),
13984               _step;
13985
13986           try {
13987             for (_iterator.s(); !(_step = _iterator.n()).done;) {
13988               var node = _step.value;
13989               ++size;
13990             } // eslint-disable-line no-unused-vars
13991
13992           } catch (err) {
13993             _iterator.e(err);
13994           } finally {
13995             _iterator.f();
13996           }
13997
13998           return size;
13999         }
14000
14001         function selection_empty () {
14002           return !this.node();
14003         }
14004
14005         function selection_each (callback) {
14006           for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
14007             for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) {
14008               if (node = group[i]) callback.call(node, node.__data__, i, group);
14009             }
14010           }
14011
14012           return this;
14013         }
14014
14015         function attrRemove$1(name) {
14016           return function () {
14017             this.removeAttribute(name);
14018           };
14019         }
14020
14021         function attrRemoveNS$1(fullname) {
14022           return function () {
14023             this.removeAttributeNS(fullname.space, fullname.local);
14024           };
14025         }
14026
14027         function attrConstant$1(name, value) {
14028           return function () {
14029             this.setAttribute(name, value);
14030           };
14031         }
14032
14033         function attrConstantNS$1(fullname, value) {
14034           return function () {
14035             this.setAttributeNS(fullname.space, fullname.local, value);
14036           };
14037         }
14038
14039         function attrFunction$1(name, value) {
14040           return function () {
14041             var v = value.apply(this, arguments);
14042             if (v == null) this.removeAttribute(name);else this.setAttribute(name, v);
14043           };
14044         }
14045
14046         function attrFunctionNS$1(fullname, value) {
14047           return function () {
14048             var v = value.apply(this, arguments);
14049             if (v == null) this.removeAttributeNS(fullname.space, fullname.local);else this.setAttributeNS(fullname.space, fullname.local, v);
14050           };
14051         }
14052
14053         function selection_attr (name, value) {
14054           var fullname = namespace(name);
14055
14056           if (arguments.length < 2) {
14057             var node = this.node();
14058             return fullname.local ? node.getAttributeNS(fullname.space, fullname.local) : node.getAttribute(fullname);
14059           }
14060
14061           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));
14062         }
14063
14064         function defaultView (node) {
14065           return node.ownerDocument && node.ownerDocument.defaultView // node is a Node
14066           || node.document && node // node is a Window
14067           || node.defaultView; // node is a Document
14068         }
14069
14070         function styleRemove$1(name) {
14071           return function () {
14072             this.style.removeProperty(name);
14073           };
14074         }
14075
14076         function styleConstant$1(name, value, priority) {
14077           return function () {
14078             this.style.setProperty(name, value, priority);
14079           };
14080         }
14081
14082         function styleFunction$1(name, value, priority) {
14083           return function () {
14084             var v = value.apply(this, arguments);
14085             if (v == null) this.style.removeProperty(name);else this.style.setProperty(name, v, priority);
14086           };
14087         }
14088
14089         function selection_style (name, value, priority) {
14090           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);
14091         }
14092         function styleValue(node, name) {
14093           return node.style.getPropertyValue(name) || defaultView(node).getComputedStyle(node, null).getPropertyValue(name);
14094         }
14095
14096         function propertyRemove(name) {
14097           return function () {
14098             delete this[name];
14099           };
14100         }
14101
14102         function propertyConstant(name, value) {
14103           return function () {
14104             this[name] = value;
14105           };
14106         }
14107
14108         function propertyFunction(name, value) {
14109           return function () {
14110             var v = value.apply(this, arguments);
14111             if (v == null) delete this[name];else this[name] = v;
14112           };
14113         }
14114
14115         function selection_property (name, value) {
14116           return arguments.length > 1 ? this.each((value == null ? propertyRemove : typeof value === "function" ? propertyFunction : propertyConstant)(name, value)) : this.node()[name];
14117         }
14118
14119         function classArray(string) {
14120           return string.trim().split(/^|\s+/);
14121         }
14122
14123         function classList(node) {
14124           return node.classList || new ClassList(node);
14125         }
14126
14127         function ClassList(node) {
14128           this._node = node;
14129           this._names = classArray(node.getAttribute("class") || "");
14130         }
14131
14132         ClassList.prototype = {
14133           add: function add(name) {
14134             var i = this._names.indexOf(name);
14135
14136             if (i < 0) {
14137               this._names.push(name);
14138
14139               this._node.setAttribute("class", this._names.join(" "));
14140             }
14141           },
14142           remove: function remove(name) {
14143             var i = this._names.indexOf(name);
14144
14145             if (i >= 0) {
14146               this._names.splice(i, 1);
14147
14148               this._node.setAttribute("class", this._names.join(" "));
14149             }
14150           },
14151           contains: function contains(name) {
14152             return this._names.indexOf(name) >= 0;
14153           }
14154         };
14155
14156         function classedAdd(node, names) {
14157           var list = classList(node),
14158               i = -1,
14159               n = names.length;
14160
14161           while (++i < n) {
14162             list.add(names[i]);
14163           }
14164         }
14165
14166         function classedRemove(node, names) {
14167           var list = classList(node),
14168               i = -1,
14169               n = names.length;
14170
14171           while (++i < n) {
14172             list.remove(names[i]);
14173           }
14174         }
14175
14176         function classedTrue(names) {
14177           return function () {
14178             classedAdd(this, names);
14179           };
14180         }
14181
14182         function classedFalse(names) {
14183           return function () {
14184             classedRemove(this, names);
14185           };
14186         }
14187
14188         function classedFunction(names, value) {
14189           return function () {
14190             (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names);
14191           };
14192         }
14193
14194         function selection_classed (name, value) {
14195           var names = classArray(name + "");
14196
14197           if (arguments.length < 2) {
14198             var list = classList(this.node()),
14199                 i = -1,
14200                 n = names.length;
14201
14202             while (++i < n) {
14203               if (!list.contains(names[i])) return false;
14204             }
14205
14206             return true;
14207           }
14208
14209           return this.each((typeof value === "function" ? classedFunction : value ? classedTrue : classedFalse)(names, value));
14210         }
14211
14212         function textRemove() {
14213           this.textContent = "";
14214         }
14215
14216         function textConstant$1(value) {
14217           return function () {
14218             this.textContent = value;
14219           };
14220         }
14221
14222         function textFunction$1(value) {
14223           return function () {
14224             var v = value.apply(this, arguments);
14225             this.textContent = v == null ? "" : v;
14226           };
14227         }
14228
14229         function selection_text (value) {
14230           return arguments.length ? this.each(value == null ? textRemove : (typeof value === "function" ? textFunction$1 : textConstant$1)(value)) : this.node().textContent;
14231         }
14232
14233         function htmlRemove() {
14234           this.innerHTML = "";
14235         }
14236
14237         function htmlConstant(value) {
14238           return function () {
14239             this.innerHTML = value;
14240           };
14241         }
14242
14243         function htmlFunction(value) {
14244           return function () {
14245             var v = value.apply(this, arguments);
14246             this.innerHTML = v == null ? "" : v;
14247           };
14248         }
14249
14250         function selection_html (value) {
14251           return arguments.length ? this.each(value == null ? htmlRemove : (typeof value === "function" ? htmlFunction : htmlConstant)(value)) : this.node().innerHTML;
14252         }
14253
14254         function raise() {
14255           if (this.nextSibling) this.parentNode.appendChild(this);
14256         }
14257
14258         function selection_raise () {
14259           return this.each(raise);
14260         }
14261
14262         function lower() {
14263           if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild);
14264         }
14265
14266         function selection_lower () {
14267           return this.each(lower);
14268         }
14269
14270         function selection_append (name) {
14271           var create = typeof name === "function" ? name : creator(name);
14272           return this.select(function () {
14273             return this.appendChild(create.apply(this, arguments));
14274           });
14275         }
14276
14277         function constantNull() {
14278           return null;
14279         }
14280
14281         function selection_insert (name, before) {
14282           var create = typeof name === "function" ? name : creator(name),
14283               select = before == null ? constantNull : typeof before === "function" ? before : selector(before);
14284           return this.select(function () {
14285             return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null);
14286           });
14287         }
14288
14289         function remove$7() {
14290           var parent = this.parentNode;
14291           if (parent) parent.removeChild(this);
14292         }
14293
14294         function selection_remove () {
14295           return this.each(remove$7);
14296         }
14297
14298         function selection_cloneShallow() {
14299           var clone = this.cloneNode(false),
14300               parent = this.parentNode;
14301           return parent ? parent.insertBefore(clone, this.nextSibling) : clone;
14302         }
14303
14304         function selection_cloneDeep() {
14305           var clone = this.cloneNode(true),
14306               parent = this.parentNode;
14307           return parent ? parent.insertBefore(clone, this.nextSibling) : clone;
14308         }
14309
14310         function selection_clone (deep) {
14311           return this.select(deep ? selection_cloneDeep : selection_cloneShallow);
14312         }
14313
14314         function selection_datum (value) {
14315           return arguments.length ? this.property("__data__", value) : this.node().__data__;
14316         }
14317
14318         function contextListener(listener) {
14319           return function (event) {
14320             listener.call(this, event, this.__data__);
14321           };
14322         }
14323
14324         function parseTypenames(typenames) {
14325           return typenames.trim().split(/^|\s+/).map(function (t) {
14326             var name = "",
14327                 i = t.indexOf(".");
14328             if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
14329             return {
14330               type: t,
14331               name: name
14332             };
14333           });
14334         }
14335
14336         function onRemove(typename) {
14337           return function () {
14338             var on = this.__on;
14339             if (!on) return;
14340
14341             for (var j = 0, i = -1, m = on.length, o; j < m; ++j) {
14342               if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) {
14343                 this.removeEventListener(o.type, o.listener, o.options);
14344               } else {
14345                 on[++i] = o;
14346               }
14347             }
14348
14349             if (++i) on.length = i;else delete this.__on;
14350           };
14351         }
14352
14353         function onAdd(typename, value, options) {
14354           return function () {
14355             var on = this.__on,
14356                 o,
14357                 listener = contextListener(value);
14358             if (on) for (var j = 0, m = on.length; j < m; ++j) {
14359               if ((o = on[j]).type === typename.type && o.name === typename.name) {
14360                 this.removeEventListener(o.type, o.listener, o.options);
14361                 this.addEventListener(o.type, o.listener = listener, o.options = options);
14362                 o.value = value;
14363                 return;
14364               }
14365             }
14366             this.addEventListener(typename.type, listener, options);
14367             o = {
14368               type: typename.type,
14369               name: typename.name,
14370               value: value,
14371               listener: listener,
14372               options: options
14373             };
14374             if (!on) this.__on = [o];else on.push(o);
14375           };
14376         }
14377
14378         function selection_on (typename, value, options) {
14379           var typenames = parseTypenames(typename + ""),
14380               i,
14381               n = typenames.length,
14382               t;
14383
14384           if (arguments.length < 2) {
14385             var on = this.node().__on;
14386
14387             if (on) for (var j = 0, m = on.length, o; j < m; ++j) {
14388               for (i = 0, o = on[j]; i < n; ++i) {
14389                 if ((t = typenames[i]).type === o.type && t.name === o.name) {
14390                   return o.value;
14391                 }
14392               }
14393             }
14394             return;
14395           }
14396
14397           on = value ? onAdd : onRemove;
14398
14399           for (i = 0; i < n; ++i) {
14400             this.each(on(typenames[i], value, options));
14401           }
14402
14403           return this;
14404         }
14405
14406         function dispatchEvent(node, type, params) {
14407           var window = defaultView(node),
14408               event = window.CustomEvent;
14409
14410           if (typeof event === "function") {
14411             event = new event(type, params);
14412           } else {
14413             event = window.document.createEvent("Event");
14414             if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail;else event.initEvent(type, false, false);
14415           }
14416
14417           node.dispatchEvent(event);
14418         }
14419
14420         function dispatchConstant(type, params) {
14421           return function () {
14422             return dispatchEvent(this, type, params);
14423           };
14424         }
14425
14426         function dispatchFunction(type, params) {
14427           return function () {
14428             return dispatchEvent(this, type, params.apply(this, arguments));
14429           };
14430         }
14431
14432         function selection_dispatch (type, params) {
14433           return this.each((typeof params === "function" ? dispatchFunction : dispatchConstant)(type, params));
14434         }
14435
14436         var _marked$1 = /*#__PURE__*/regeneratorRuntime.mark(_callee);
14437
14438         function _callee() {
14439           var groups, j, m, group, i, n, node;
14440           return regeneratorRuntime.wrap(function _callee$(_context) {
14441             while (1) {
14442               switch (_context.prev = _context.next) {
14443                 case 0:
14444                   groups = this._groups, j = 0, m = groups.length;
14445
14446                 case 1:
14447                   if (!(j < m)) {
14448                     _context.next = 13;
14449                     break;
14450                   }
14451
14452                   group = groups[j], i = 0, n = group.length;
14453
14454                 case 3:
14455                   if (!(i < n)) {
14456                     _context.next = 10;
14457                     break;
14458                   }
14459
14460                   if (!(node = group[i])) {
14461                     _context.next = 7;
14462                     break;
14463                   }
14464
14465                   _context.next = 7;
14466                   return node;
14467
14468                 case 7:
14469                   ++i;
14470                   _context.next = 3;
14471                   break;
14472
14473                 case 10:
14474                   ++j;
14475                   _context.next = 1;
14476                   break;
14477
14478                 case 13:
14479                 case "end":
14480                   return _context.stop();
14481               }
14482             }
14483           }, _marked$1, this);
14484         }
14485
14486         var root$1 = [null];
14487         function Selection$1(groups, parents) {
14488           this._groups = groups;
14489           this._parents = parents;
14490         }
14491
14492         function selection() {
14493           return new Selection$1([[document.documentElement]], root$1);
14494         }
14495
14496         function selection_selection() {
14497           return this;
14498         }
14499
14500         Selection$1.prototype = selection.prototype = _defineProperty({
14501           constructor: Selection$1,
14502           select: selection_select,
14503           selectAll: selection_selectAll,
14504           selectChild: selection_selectChild,
14505           selectChildren: selection_selectChildren,
14506           filter: selection_filter,
14507           data: selection_data,
14508           enter: selection_enter,
14509           exit: selection_exit,
14510           join: selection_join,
14511           merge: selection_merge,
14512           selection: selection_selection,
14513           order: selection_order,
14514           sort: selection_sort,
14515           call: selection_call,
14516           nodes: selection_nodes,
14517           node: selection_node,
14518           size: selection_size,
14519           empty: selection_empty,
14520           each: selection_each,
14521           attr: selection_attr,
14522           style: selection_style,
14523           property: selection_property,
14524           classed: selection_classed,
14525           text: selection_text,
14526           html: selection_html,
14527           raise: selection_raise,
14528           lower: selection_lower,
14529           append: selection_append,
14530           insert: selection_insert,
14531           remove: selection_remove,
14532           clone: selection_clone,
14533           datum: selection_datum,
14534           on: selection_on,
14535           dispatch: selection_dispatch
14536         }, Symbol.iterator, _callee);
14537
14538         function select (selector) {
14539           return typeof selector === "string" ? new Selection$1([[document.querySelector(selector)]], [document.documentElement]) : new Selection$1([[selector]], root$1);
14540         }
14541
14542         function sourceEvent (event) {
14543           var sourceEvent;
14544
14545           while (sourceEvent = event.sourceEvent) {
14546             event = sourceEvent;
14547           }
14548
14549           return event;
14550         }
14551
14552         function pointer (event, node) {
14553           event = sourceEvent(event);
14554           if (node === undefined) node = event.currentTarget;
14555
14556           if (node) {
14557             var svg = node.ownerSVGElement || node;
14558
14559             if (svg.createSVGPoint) {
14560               var point = svg.createSVGPoint();
14561               point.x = event.clientX, point.y = event.clientY;
14562               point = point.matrixTransform(node.getScreenCTM().inverse());
14563               return [point.x, point.y];
14564             }
14565
14566             if (node.getBoundingClientRect) {
14567               var rect = node.getBoundingClientRect();
14568               return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop];
14569             }
14570           }
14571
14572           return [event.pageX, event.pageY];
14573         }
14574
14575         function selectAll (selector) {
14576           return typeof selector === "string" ? new Selection$1([document.querySelectorAll(selector)], [document.documentElement]) : new Selection$1([selector == null ? [] : array(selector)], root$1);
14577         }
14578
14579         function nopropagation$1(event) {
14580           event.stopImmediatePropagation();
14581         }
14582         function noevent$1 (event) {
14583           event.preventDefault();
14584           event.stopImmediatePropagation();
14585         }
14586
14587         function dragDisable (view) {
14588           var root = view.document.documentElement,
14589               selection = select(view).on("dragstart.drag", noevent$1, true);
14590
14591           if ("onselectstart" in root) {
14592             selection.on("selectstart.drag", noevent$1, true);
14593           } else {
14594             root.__noselect = root.style.MozUserSelect;
14595             root.style.MozUserSelect = "none";
14596           }
14597         }
14598         function yesdrag(view, noclick) {
14599           var root = view.document.documentElement,
14600               selection = select(view).on("dragstart.drag", null);
14601
14602           if (noclick) {
14603             selection.on("click.drag", noevent$1, true);
14604             setTimeout(function () {
14605               selection.on("click.drag", null);
14606             }, 0);
14607           }
14608
14609           if ("onselectstart" in root) {
14610             selection.on("selectstart.drag", null);
14611           } else {
14612             root.style.MozUserSelect = root.__noselect;
14613             delete root.__noselect;
14614           }
14615         }
14616
14617         var constant$2 = (function (x) {
14618           return function () {
14619             return x;
14620           };
14621         });
14622
14623         function DragEvent(type, _ref) {
14624           var sourceEvent = _ref.sourceEvent,
14625               subject = _ref.subject,
14626               target = _ref.target,
14627               identifier = _ref.identifier,
14628               active = _ref.active,
14629               x = _ref.x,
14630               y = _ref.y,
14631               dx = _ref.dx,
14632               dy = _ref.dy,
14633               dispatch = _ref.dispatch;
14634           Object.defineProperties(this, {
14635             type: {
14636               value: type,
14637               enumerable: true,
14638               configurable: true
14639             },
14640             sourceEvent: {
14641               value: sourceEvent,
14642               enumerable: true,
14643               configurable: true
14644             },
14645             subject: {
14646               value: subject,
14647               enumerable: true,
14648               configurable: true
14649             },
14650             target: {
14651               value: target,
14652               enumerable: true,
14653               configurable: true
14654             },
14655             identifier: {
14656               value: identifier,
14657               enumerable: true,
14658               configurable: true
14659             },
14660             active: {
14661               value: active,
14662               enumerable: true,
14663               configurable: true
14664             },
14665             x: {
14666               value: x,
14667               enumerable: true,
14668               configurable: true
14669             },
14670             y: {
14671               value: y,
14672               enumerable: true,
14673               configurable: true
14674             },
14675             dx: {
14676               value: dx,
14677               enumerable: true,
14678               configurable: true
14679             },
14680             dy: {
14681               value: dy,
14682               enumerable: true,
14683               configurable: true
14684             },
14685             _: {
14686               value: dispatch
14687             }
14688           });
14689         }
14690
14691         DragEvent.prototype.on = function () {
14692           var value = this._.on.apply(this._, arguments);
14693
14694           return value === this._ ? this : value;
14695         };
14696
14697         function defaultFilter$2(event) {
14698           return !event.ctrlKey && !event.button;
14699         }
14700
14701         function defaultContainer() {
14702           return this.parentNode;
14703         }
14704
14705         function defaultSubject(event, d) {
14706           return d == null ? {
14707             x: event.x,
14708             y: event.y
14709           } : d;
14710         }
14711
14712         function defaultTouchable$1() {
14713           return navigator.maxTouchPoints || "ontouchstart" in this;
14714         }
14715
14716         function d3_drag () {
14717           var filter = defaultFilter$2,
14718               container = defaultContainer,
14719               subject = defaultSubject,
14720               touchable = defaultTouchable$1,
14721               gestures = {},
14722               listeners = dispatch$8("start", "drag", "end"),
14723               active = 0,
14724               mousedownx,
14725               mousedowny,
14726               mousemoving,
14727               touchending,
14728               clickDistance2 = 0;
14729
14730           function drag(selection) {
14731             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)");
14732           }
14733
14734           function mousedowned(event, d) {
14735             if (touchending || !filter.call(this, event, d)) return;
14736             var gesture = beforestart(this, container.call(this, event, d), event, d, "mouse");
14737             if (!gesture) return;
14738             select(event.view).on("mousemove.drag", mousemoved, true).on("mouseup.drag", mouseupped, true);
14739             dragDisable(event.view);
14740             nopropagation$1(event);
14741             mousemoving = false;
14742             mousedownx = event.clientX;
14743             mousedowny = event.clientY;
14744             gesture("start", event);
14745           }
14746
14747           function mousemoved(event) {
14748             noevent$1(event);
14749
14750             if (!mousemoving) {
14751               var dx = event.clientX - mousedownx,
14752                   dy = event.clientY - mousedowny;
14753               mousemoving = dx * dx + dy * dy > clickDistance2;
14754             }
14755
14756             gestures.mouse("drag", event);
14757           }
14758
14759           function mouseupped(event) {
14760             select(event.view).on("mousemove.drag mouseup.drag", null);
14761             yesdrag(event.view, mousemoving);
14762             noevent$1(event);
14763             gestures.mouse("end", event);
14764           }
14765
14766           function touchstarted(event, d) {
14767             if (!filter.call(this, event, d)) return;
14768             var touches = event.changedTouches,
14769                 c = container.call(this, event, d),
14770                 n = touches.length,
14771                 i,
14772                 gesture;
14773
14774             for (i = 0; i < n; ++i) {
14775               if (gesture = beforestart(this, c, event, d, touches[i].identifier, touches[i])) {
14776                 nopropagation$1(event);
14777                 gesture("start", event, touches[i]);
14778               }
14779             }
14780           }
14781
14782           function touchmoved(event) {
14783             var touches = event.changedTouches,
14784                 n = touches.length,
14785                 i,
14786                 gesture;
14787
14788             for (i = 0; i < n; ++i) {
14789               if (gesture = gestures[touches[i].identifier]) {
14790                 noevent$1(event);
14791                 gesture("drag", event, touches[i]);
14792               }
14793             }
14794           }
14795
14796           function touchended(event) {
14797             var touches = event.changedTouches,
14798                 n = touches.length,
14799                 i,
14800                 gesture;
14801             if (touchending) clearTimeout(touchending);
14802             touchending = setTimeout(function () {
14803               touchending = null;
14804             }, 500); // Ghost clicks are delayed!
14805
14806             for (i = 0; i < n; ++i) {
14807               if (gesture = gestures[touches[i].identifier]) {
14808                 nopropagation$1(event);
14809                 gesture("end", event, touches[i]);
14810               }
14811             }
14812           }
14813
14814           function beforestart(that, container, event, d, identifier, touch) {
14815             var dispatch = listeners.copy(),
14816                 p = pointer(touch || event, container),
14817                 dx,
14818                 dy,
14819                 s;
14820             if ((s = subject.call(that, new DragEvent("beforestart", {
14821               sourceEvent: event,
14822               target: drag,
14823               identifier: identifier,
14824               active: active,
14825               x: p[0],
14826               y: p[1],
14827               dx: 0,
14828               dy: 0,
14829               dispatch: dispatch
14830             }), d)) == null) return;
14831             dx = s.x - p[0] || 0;
14832             dy = s.y - p[1] || 0;
14833             return function gesture(type, event, touch) {
14834               var p0 = p,
14835                   n;
14836
14837               switch (type) {
14838                 case "start":
14839                   gestures[identifier] = gesture, n = active++;
14840                   break;
14841
14842                 case "end":
14843                   delete gestures[identifier], --active;
14844                 // nobreak
14845
14846                 case "drag":
14847                   p = pointer(touch || event, container), n = active;
14848                   break;
14849               }
14850
14851               dispatch.call(type, that, new DragEvent(type, {
14852                 sourceEvent: event,
14853                 subject: s,
14854                 target: drag,
14855                 identifier: identifier,
14856                 active: n,
14857                 x: p[0] + dx,
14858                 y: p[1] + dy,
14859                 dx: p[0] - p0[0],
14860                 dy: p[1] - p0[1],
14861                 dispatch: dispatch
14862               }), d);
14863             };
14864           }
14865
14866           drag.filter = function (_) {
14867             return arguments.length ? (filter = typeof _ === "function" ? _ : constant$2(!!_), drag) : filter;
14868           };
14869
14870           drag.container = function (_) {
14871             return arguments.length ? (container = typeof _ === "function" ? _ : constant$2(_), drag) : container;
14872           };
14873
14874           drag.subject = function (_) {
14875             return arguments.length ? (subject = typeof _ === "function" ? _ : constant$2(_), drag) : subject;
14876           };
14877
14878           drag.touchable = function (_) {
14879             return arguments.length ? (touchable = typeof _ === "function" ? _ : constant$2(!!_), drag) : touchable;
14880           };
14881
14882           drag.on = function () {
14883             var value = listeners.on.apply(listeners, arguments);
14884             return value === listeners ? drag : value;
14885           };
14886
14887           drag.clickDistance = function (_) {
14888             return arguments.length ? (clickDistance2 = (_ = +_) * _, drag) : Math.sqrt(clickDistance2);
14889           };
14890
14891           return drag;
14892         }
14893
14894         var DESCRIPTORS$4 = descriptors;
14895         var global$b = global$1m;
14896         var uncurryThis$e = functionUncurryThis;
14897         var isForced$1 = isForced_1;
14898         var inheritIfRequired$1 = inheritIfRequired$4;
14899         var createNonEnumerableProperty = createNonEnumerableProperty$b;
14900         var defineProperty$1 = objectDefineProperty.f;
14901         var getOwnPropertyNames$1 = objectGetOwnPropertyNames.f;
14902         var isPrototypeOf$1 = objectIsPrototypeOf;
14903         var isRegExp$1 = isRegexp;
14904         var toString$9 = toString$k;
14905         var regExpFlags$1 = regexpFlags$1;
14906         var stickyHelpers = regexpStickyHelpers;
14907         var redefine$3 = redefine$h.exports;
14908         var fails$a = fails$S;
14909         var hasOwn$2 = hasOwnProperty_1;
14910         var enforceInternalState = internalState.enforce;
14911         var setSpecies = setSpecies$5;
14912         var wellKnownSymbol$1 = wellKnownSymbol$t;
14913         var UNSUPPORTED_DOT_ALL = regexpUnsupportedDotAll;
14914         var UNSUPPORTED_NCG = regexpUnsupportedNcg;
14915
14916         var MATCH$1 = wellKnownSymbol$1('match');
14917         var NativeRegExp = global$b.RegExp;
14918         var RegExpPrototype$1 = NativeRegExp.prototype;
14919         var SyntaxError$1 = global$b.SyntaxError;
14920         var getFlags = uncurryThis$e(regExpFlags$1);
14921         var exec$2 = uncurryThis$e(RegExpPrototype$1.exec);
14922         var charAt$1 = uncurryThis$e(''.charAt);
14923         var replace$3 = uncurryThis$e(''.replace);
14924         var stringIndexOf$1 = uncurryThis$e(''.indexOf);
14925         var stringSlice$4 = uncurryThis$e(''.slice);
14926         // TODO: Use only propper RegExpIdentifierName
14927         var IS_NCG = /^\?<[^\s\d!#%&*+<=>@^][^\s!#%&*+<=>@^]*>/;
14928         var re1 = /a/g;
14929         var re2 = /a/g;
14930
14931         // "new" should create a new object, old webkit bug
14932         var CORRECT_NEW = new NativeRegExp(re1) !== re1;
14933
14934         var UNSUPPORTED_Y = stickyHelpers.UNSUPPORTED_Y;
14935
14936         var BASE_FORCED = DESCRIPTORS$4 &&
14937           (!CORRECT_NEW || UNSUPPORTED_Y || UNSUPPORTED_DOT_ALL || UNSUPPORTED_NCG || fails$a(function () {
14938             re2[MATCH$1] = false;
14939             // RegExp constructor can alter flags and IsRegExp works correct with @@match
14940             return NativeRegExp(re1) != re1 || NativeRegExp(re2) == re2 || NativeRegExp(re1, 'i') != '/a/i';
14941           }));
14942
14943         var handleDotAll = function (string) {
14944           var length = string.length;
14945           var index = 0;
14946           var result = '';
14947           var brackets = false;
14948           var chr;
14949           for (; index <= length; index++) {
14950             chr = charAt$1(string, index);
14951             if (chr === '\\') {
14952               result += chr + charAt$1(string, ++index);
14953               continue;
14954             }
14955             if (!brackets && chr === '.') {
14956               result += '[\\s\\S]';
14957             } else {
14958               if (chr === '[') {
14959                 brackets = true;
14960               } else if (chr === ']') {
14961                 brackets = false;
14962               } result += chr;
14963             }
14964           } return result;
14965         };
14966
14967         var handleNCG = function (string) {
14968           var length = string.length;
14969           var index = 0;
14970           var result = '';
14971           var named = [];
14972           var names = {};
14973           var brackets = false;
14974           var ncg = false;
14975           var groupid = 0;
14976           var groupname = '';
14977           var chr;
14978           for (; index <= length; index++) {
14979             chr = charAt$1(string, index);
14980             if (chr === '\\') {
14981               chr = chr + charAt$1(string, ++index);
14982             } else if (chr === ']') {
14983               brackets = false;
14984             } else if (!brackets) switch (true) {
14985               case chr === '[':
14986                 brackets = true;
14987                 break;
14988               case chr === '(':
14989                 if (exec$2(IS_NCG, stringSlice$4(string, index + 1))) {
14990                   index += 2;
14991                   ncg = true;
14992                 }
14993                 result += chr;
14994                 groupid++;
14995                 continue;
14996               case chr === '>' && ncg:
14997                 if (groupname === '' || hasOwn$2(names, groupname)) {
14998                   throw new SyntaxError$1('Invalid capture group name');
14999                 }
15000                 names[groupname] = true;
15001                 named[named.length] = [groupname, groupid];
15002                 ncg = false;
15003                 groupname = '';
15004                 continue;
15005             }
15006             if (ncg) groupname += chr;
15007             else result += chr;
15008           } return [result, named];
15009         };
15010
15011         // `RegExp` constructor
15012         // https://tc39.es/ecma262/#sec-regexp-constructor
15013         if (isForced$1('RegExp', BASE_FORCED)) {
15014           var RegExpWrapper = function RegExp(pattern, flags) {
15015             var thisIsRegExp = isPrototypeOf$1(RegExpPrototype$1, this);
15016             var patternIsRegExp = isRegExp$1(pattern);
15017             var flagsAreUndefined = flags === undefined;
15018             var groups = [];
15019             var rawPattern = pattern;
15020             var rawFlags, dotAll, sticky, handled, result, state;
15021
15022             if (!thisIsRegExp && patternIsRegExp && flagsAreUndefined && pattern.constructor === RegExpWrapper) {
15023               return pattern;
15024             }
15025
15026             if (patternIsRegExp || isPrototypeOf$1(RegExpPrototype$1, pattern)) {
15027               pattern = pattern.source;
15028               if (flagsAreUndefined) flags = 'flags' in rawPattern ? rawPattern.flags : getFlags(rawPattern);
15029             }
15030
15031             pattern = pattern === undefined ? '' : toString$9(pattern);
15032             flags = flags === undefined ? '' : toString$9(flags);
15033             rawPattern = pattern;
15034
15035             if (UNSUPPORTED_DOT_ALL && 'dotAll' in re1) {
15036               dotAll = !!flags && stringIndexOf$1(flags, 's') > -1;
15037               if (dotAll) flags = replace$3(flags, /s/g, '');
15038             }
15039
15040             rawFlags = flags;
15041
15042             if (UNSUPPORTED_Y && 'sticky' in re1) {
15043               sticky = !!flags && stringIndexOf$1(flags, 'y') > -1;
15044               if (sticky) flags = replace$3(flags, /y/g, '');
15045             }
15046
15047             if (UNSUPPORTED_NCG) {
15048               handled = handleNCG(pattern);
15049               pattern = handled[0];
15050               groups = handled[1];
15051             }
15052
15053             result = inheritIfRequired$1(NativeRegExp(pattern, flags), thisIsRegExp ? this : RegExpPrototype$1, RegExpWrapper);
15054
15055             if (dotAll || sticky || groups.length) {
15056               state = enforceInternalState(result);
15057               if (dotAll) {
15058                 state.dotAll = true;
15059                 state.raw = RegExpWrapper(handleDotAll(pattern), rawFlags);
15060               }
15061               if (sticky) state.sticky = true;
15062               if (groups.length) state.groups = groups;
15063             }
15064
15065             if (pattern !== rawPattern) try {
15066               // fails in old engines, but we have no alternatives for unsupported regex syntax
15067               createNonEnumerableProperty(result, 'source', rawPattern === '' ? '(?:)' : rawPattern);
15068             } catch (error) { /* empty */ }
15069
15070             return result;
15071           };
15072
15073           var proxy = function (key) {
15074             key in RegExpWrapper || defineProperty$1(RegExpWrapper, key, {
15075               configurable: true,
15076               get: function () { return NativeRegExp[key]; },
15077               set: function (it) { NativeRegExp[key] = it; }
15078             });
15079           };
15080
15081           for (var keys$1 = getOwnPropertyNames$1(NativeRegExp), index$1 = 0; keys$1.length > index$1;) {
15082             proxy(keys$1[index$1++]);
15083           }
15084
15085           RegExpPrototype$1.constructor = RegExpWrapper;
15086           RegExpWrapper.prototype = RegExpPrototype$1;
15087           redefine$3(global$b, 'RegExp', RegExpWrapper);
15088         }
15089
15090         // https://tc39.es/ecma262/#sec-get-regexp-@@species
15091         setSpecies('RegExp');
15092
15093         function define (constructor, factory, prototype) {
15094           constructor.prototype = factory.prototype = prototype;
15095           prototype.constructor = constructor;
15096         }
15097         function extend$3(parent, definition) {
15098           var prototype = Object.create(parent.prototype);
15099
15100           for (var key in definition) {
15101             prototype[key] = definition[key];
15102           }
15103
15104           return prototype;
15105         }
15106
15107         function Color() {}
15108         var _darker = 0.7;
15109
15110         var _brighter = 1 / _darker;
15111         var reI = "\\s*([+-]?\\d+)\\s*",
15112             reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",
15113             reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",
15114             reHex = /^#([0-9a-f]{3,8})$/,
15115             reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"),
15116             reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"),
15117             reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"),
15118             reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"),
15119             reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"),
15120             reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$");
15121         var named = {
15122           aliceblue: 0xf0f8ff,
15123           antiquewhite: 0xfaebd7,
15124           aqua: 0x00ffff,
15125           aquamarine: 0x7fffd4,
15126           azure: 0xf0ffff,
15127           beige: 0xf5f5dc,
15128           bisque: 0xffe4c4,
15129           black: 0x000000,
15130           blanchedalmond: 0xffebcd,
15131           blue: 0x0000ff,
15132           blueviolet: 0x8a2be2,
15133           brown: 0xa52a2a,
15134           burlywood: 0xdeb887,
15135           cadetblue: 0x5f9ea0,
15136           chartreuse: 0x7fff00,
15137           chocolate: 0xd2691e,
15138           coral: 0xff7f50,
15139           cornflowerblue: 0x6495ed,
15140           cornsilk: 0xfff8dc,
15141           crimson: 0xdc143c,
15142           cyan: 0x00ffff,
15143           darkblue: 0x00008b,
15144           darkcyan: 0x008b8b,
15145           darkgoldenrod: 0xb8860b,
15146           darkgray: 0xa9a9a9,
15147           darkgreen: 0x006400,
15148           darkgrey: 0xa9a9a9,
15149           darkkhaki: 0xbdb76b,
15150           darkmagenta: 0x8b008b,
15151           darkolivegreen: 0x556b2f,
15152           darkorange: 0xff8c00,
15153           darkorchid: 0x9932cc,
15154           darkred: 0x8b0000,
15155           darksalmon: 0xe9967a,
15156           darkseagreen: 0x8fbc8f,
15157           darkslateblue: 0x483d8b,
15158           darkslategray: 0x2f4f4f,
15159           darkslategrey: 0x2f4f4f,
15160           darkturquoise: 0x00ced1,
15161           darkviolet: 0x9400d3,
15162           deeppink: 0xff1493,
15163           deepskyblue: 0x00bfff,
15164           dimgray: 0x696969,
15165           dimgrey: 0x696969,
15166           dodgerblue: 0x1e90ff,
15167           firebrick: 0xb22222,
15168           floralwhite: 0xfffaf0,
15169           forestgreen: 0x228b22,
15170           fuchsia: 0xff00ff,
15171           gainsboro: 0xdcdcdc,
15172           ghostwhite: 0xf8f8ff,
15173           gold: 0xffd700,
15174           goldenrod: 0xdaa520,
15175           gray: 0x808080,
15176           green: 0x008000,
15177           greenyellow: 0xadff2f,
15178           grey: 0x808080,
15179           honeydew: 0xf0fff0,
15180           hotpink: 0xff69b4,
15181           indianred: 0xcd5c5c,
15182           indigo: 0x4b0082,
15183           ivory: 0xfffff0,
15184           khaki: 0xf0e68c,
15185           lavender: 0xe6e6fa,
15186           lavenderblush: 0xfff0f5,
15187           lawngreen: 0x7cfc00,
15188           lemonchiffon: 0xfffacd,
15189           lightblue: 0xadd8e6,
15190           lightcoral: 0xf08080,
15191           lightcyan: 0xe0ffff,
15192           lightgoldenrodyellow: 0xfafad2,
15193           lightgray: 0xd3d3d3,
15194           lightgreen: 0x90ee90,
15195           lightgrey: 0xd3d3d3,
15196           lightpink: 0xffb6c1,
15197           lightsalmon: 0xffa07a,
15198           lightseagreen: 0x20b2aa,
15199           lightskyblue: 0x87cefa,
15200           lightslategray: 0x778899,
15201           lightslategrey: 0x778899,
15202           lightsteelblue: 0xb0c4de,
15203           lightyellow: 0xffffe0,
15204           lime: 0x00ff00,
15205           limegreen: 0x32cd32,
15206           linen: 0xfaf0e6,
15207           magenta: 0xff00ff,
15208           maroon: 0x800000,
15209           mediumaquamarine: 0x66cdaa,
15210           mediumblue: 0x0000cd,
15211           mediumorchid: 0xba55d3,
15212           mediumpurple: 0x9370db,
15213           mediumseagreen: 0x3cb371,
15214           mediumslateblue: 0x7b68ee,
15215           mediumspringgreen: 0x00fa9a,
15216           mediumturquoise: 0x48d1cc,
15217           mediumvioletred: 0xc71585,
15218           midnightblue: 0x191970,
15219           mintcream: 0xf5fffa,
15220           mistyrose: 0xffe4e1,
15221           moccasin: 0xffe4b5,
15222           navajowhite: 0xffdead,
15223           navy: 0x000080,
15224           oldlace: 0xfdf5e6,
15225           olive: 0x808000,
15226           olivedrab: 0x6b8e23,
15227           orange: 0xffa500,
15228           orangered: 0xff4500,
15229           orchid: 0xda70d6,
15230           palegoldenrod: 0xeee8aa,
15231           palegreen: 0x98fb98,
15232           paleturquoise: 0xafeeee,
15233           palevioletred: 0xdb7093,
15234           papayawhip: 0xffefd5,
15235           peachpuff: 0xffdab9,
15236           peru: 0xcd853f,
15237           pink: 0xffc0cb,
15238           plum: 0xdda0dd,
15239           powderblue: 0xb0e0e6,
15240           purple: 0x800080,
15241           rebeccapurple: 0x663399,
15242           red: 0xff0000,
15243           rosybrown: 0xbc8f8f,
15244           royalblue: 0x4169e1,
15245           saddlebrown: 0x8b4513,
15246           salmon: 0xfa8072,
15247           sandybrown: 0xf4a460,
15248           seagreen: 0x2e8b57,
15249           seashell: 0xfff5ee,
15250           sienna: 0xa0522d,
15251           silver: 0xc0c0c0,
15252           skyblue: 0x87ceeb,
15253           slateblue: 0x6a5acd,
15254           slategray: 0x708090,
15255           slategrey: 0x708090,
15256           snow: 0xfffafa,
15257           springgreen: 0x00ff7f,
15258           steelblue: 0x4682b4,
15259           tan: 0xd2b48c,
15260           teal: 0x008080,
15261           thistle: 0xd8bfd8,
15262           tomato: 0xff6347,
15263           turquoise: 0x40e0d0,
15264           violet: 0xee82ee,
15265           wheat: 0xf5deb3,
15266           white: 0xffffff,
15267           whitesmoke: 0xf5f5f5,
15268           yellow: 0xffff00,
15269           yellowgreen: 0x9acd32
15270         };
15271         define(Color, color, {
15272           copy: function copy(channels) {
15273             return Object.assign(new this.constructor(), this, channels);
15274           },
15275           displayable: function displayable() {
15276             return this.rgb().displayable();
15277           },
15278           hex: color_formatHex,
15279           // Deprecated! Use color.formatHex.
15280           formatHex: color_formatHex,
15281           formatHsl: color_formatHsl,
15282           formatRgb: color_formatRgb,
15283           toString: color_formatRgb
15284         });
15285
15286         function color_formatHex() {
15287           return this.rgb().formatHex();
15288         }
15289
15290         function color_formatHsl() {
15291           return hslConvert(this).formatHsl();
15292         }
15293
15294         function color_formatRgb() {
15295           return this.rgb().formatRgb();
15296         }
15297
15298         function color(format) {
15299           var m, l;
15300           format = (format + "").trim().toLowerCase();
15301           return (m = reHex.exec(format)) ? (l = m[1].length, m = parseInt(m[1], 16), l === 6 ? rgbn(m) // #ff0000
15302           : l === 3 ? new Rgb(m >> 8 & 0xf | m >> 4 & 0xf0, m >> 4 & 0xf | m & 0xf0, (m & 0xf) << 4 | m & 0xf, 1) // #f00
15303           : l === 8 ? rgba(m >> 24 & 0xff, m >> 16 & 0xff, m >> 8 & 0xff, (m & 0xff) / 0xff) // #ff000000
15304           : 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
15305           : null // invalid hex
15306           ) : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
15307           : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
15308           : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
15309           : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
15310           : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
15311           : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
15312           : named.hasOwnProperty(format) ? rgbn(named[format]) // eslint-disable-line no-prototype-builtins
15313           : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0) : null;
15314         }
15315
15316         function rgbn(n) {
15317           return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
15318         }
15319
15320         function rgba(r, g, b, a) {
15321           if (a <= 0) r = g = b = NaN;
15322           return new Rgb(r, g, b, a);
15323         }
15324
15325         function rgbConvert(o) {
15326           if (!(o instanceof Color)) o = color(o);
15327           if (!o) return new Rgb();
15328           o = o.rgb();
15329           return new Rgb(o.r, o.g, o.b, o.opacity);
15330         }
15331         function rgb(r, g, b, opacity) {
15332           return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
15333         }
15334         function Rgb(r, g, b, opacity) {
15335           this.r = +r;
15336           this.g = +g;
15337           this.b = +b;
15338           this.opacity = +opacity;
15339         }
15340         define(Rgb, rgb, extend$3(Color, {
15341           brighter: function brighter(k) {
15342             k = k == null ? _brighter : Math.pow(_brighter, k);
15343             return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
15344           },
15345           darker: function darker(k) {
15346             k = k == null ? _darker : Math.pow(_darker, k);
15347             return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
15348           },
15349           rgb: function rgb() {
15350             return this;
15351           },
15352           displayable: function displayable() {
15353             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;
15354           },
15355           hex: rgb_formatHex,
15356           // Deprecated! Use color.formatHex.
15357           formatHex: rgb_formatHex,
15358           formatRgb: rgb_formatRgb,
15359           toString: rgb_formatRgb
15360         }));
15361
15362         function rgb_formatHex() {
15363           return "#" + hex$1(this.r) + hex$1(this.g) + hex$1(this.b);
15364         }
15365
15366         function rgb_formatRgb() {
15367           var a = this.opacity;
15368           a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
15369           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 + ")");
15370         }
15371
15372         function hex$1(value) {
15373           value = Math.max(0, Math.min(255, Math.round(value) || 0));
15374           return (value < 16 ? "0" : "") + value.toString(16);
15375         }
15376
15377         function hsla(h, s, l, a) {
15378           if (a <= 0) h = s = l = NaN;else if (l <= 0 || l >= 1) h = s = NaN;else if (s <= 0) h = NaN;
15379           return new Hsl(h, s, l, a);
15380         }
15381
15382         function hslConvert(o) {
15383           if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);
15384           if (!(o instanceof Color)) o = color(o);
15385           if (!o) return new Hsl();
15386           if (o instanceof Hsl) return o;
15387           o = o.rgb();
15388           var r = o.r / 255,
15389               g = o.g / 255,
15390               b = o.b / 255,
15391               min = Math.min(r, g, b),
15392               max = Math.max(r, g, b),
15393               h = NaN,
15394               s = max - min,
15395               l = (max + min) / 2;
15396
15397           if (s) {
15398             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;
15399             s /= l < 0.5 ? max + min : 2 - max - min;
15400             h *= 60;
15401           } else {
15402             s = l > 0 && l < 1 ? 0 : h;
15403           }
15404
15405           return new Hsl(h, s, l, o.opacity);
15406         }
15407         function hsl(h, s, l, opacity) {
15408           return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);
15409         }
15410
15411         function Hsl(h, s, l, opacity) {
15412           this.h = +h;
15413           this.s = +s;
15414           this.l = +l;
15415           this.opacity = +opacity;
15416         }
15417
15418         define(Hsl, hsl, extend$3(Color, {
15419           brighter: function brighter(k) {
15420             k = k == null ? _brighter : Math.pow(_brighter, k);
15421             return new Hsl(this.h, this.s, this.l * k, this.opacity);
15422           },
15423           darker: function darker(k) {
15424             k = k == null ? _darker : Math.pow(_darker, k);
15425             return new Hsl(this.h, this.s, this.l * k, this.opacity);
15426           },
15427           rgb: function rgb() {
15428             var h = this.h % 360 + (this.h < 0) * 360,
15429                 s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
15430                 l = this.l,
15431                 m2 = l + (l < 0.5 ? l : 1 - l) * s,
15432                 m1 = 2 * l - m2;
15433             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);
15434           },
15435           displayable: function displayable() {
15436             return (0 <= this.s && this.s <= 1 || isNaN(this.s)) && 0 <= this.l && this.l <= 1 && 0 <= this.opacity && this.opacity <= 1;
15437           },
15438           formatHsl: function formatHsl() {
15439             var a = this.opacity;
15440             a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
15441             return (a === 1 ? "hsl(" : "hsla(") + (this.h || 0) + ", " + (this.s || 0) * 100 + "%, " + (this.l || 0) * 100 + "%" + (a === 1 ? ")" : ", " + a + ")");
15442           }
15443         }));
15444         /* From FvD 13.37, CSS Color Module Level 3 */
15445
15446         function hsl2rgb(h, m1, m2) {
15447           return (h < 60 ? m1 + (m2 - m1) * h / 60 : h < 180 ? m2 : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 : m1) * 255;
15448         }
15449
15450         var constant$1 = (function (x) {
15451           return function () {
15452             return x;
15453           };
15454         });
15455
15456         function linear$2(a, d) {
15457           return function (t) {
15458             return a + t * d;
15459           };
15460         }
15461
15462         function exponential(a, b, y) {
15463           return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function (t) {
15464             return Math.pow(a + t * b, y);
15465           };
15466         }
15467         function gamma(y) {
15468           return (y = +y) === 1 ? nogamma : function (a, b) {
15469             return b - a ? exponential(a, b, y) : constant$1(isNaN(a) ? b : a);
15470           };
15471         }
15472         function nogamma(a, b) {
15473           var d = b - a;
15474           return d ? linear$2(a, d) : constant$1(isNaN(a) ? b : a);
15475         }
15476
15477         var d3_interpolateRgb = (function rgbGamma(y) {
15478           var color = gamma(y);
15479
15480           function rgb$1(start, end) {
15481             var r = color((start = rgb(start)).r, (end = rgb(end)).r),
15482                 g = color(start.g, end.g),
15483                 b = color(start.b, end.b),
15484                 opacity = nogamma(start.opacity, end.opacity);
15485             return function (t) {
15486               start.r = r(t);
15487               start.g = g(t);
15488               start.b = b(t);
15489               start.opacity = opacity(t);
15490               return start + "";
15491             };
15492           }
15493
15494           rgb$1.gamma = rgbGamma;
15495           return rgb$1;
15496         })(1);
15497
15498         function numberArray (a, b) {
15499           if (!b) b = [];
15500           var n = a ? Math.min(b.length, a.length) : 0,
15501               c = b.slice(),
15502               i;
15503           return function (t) {
15504             for (i = 0; i < n; ++i) {
15505               c[i] = a[i] * (1 - t) + b[i] * t;
15506             }
15507
15508             return c;
15509           };
15510         }
15511         function isNumberArray(x) {
15512           return ArrayBuffer.isView(x) && !(x instanceof DataView);
15513         }
15514
15515         function genericArray(a, b) {
15516           var nb = b ? b.length : 0,
15517               na = a ? Math.min(nb, a.length) : 0,
15518               x = new Array(na),
15519               c = new Array(nb),
15520               i;
15521
15522           for (i = 0; i < na; ++i) {
15523             x[i] = interpolate$1(a[i], b[i]);
15524           }
15525
15526           for (; i < nb; ++i) {
15527             c[i] = b[i];
15528           }
15529
15530           return function (t) {
15531             for (i = 0; i < na; ++i) {
15532               c[i] = x[i](t);
15533             }
15534
15535             return c;
15536           };
15537         }
15538
15539         function date (a, b) {
15540           var d = new Date();
15541           return a = +a, b = +b, function (t) {
15542             return d.setTime(a * (1 - t) + b * t), d;
15543           };
15544         }
15545
15546         function d3_interpolateNumber (a, b) {
15547           return a = +a, b = +b, function (t) {
15548             return a * (1 - t) + b * t;
15549           };
15550         }
15551
15552         function object (a, b) {
15553           var i = {},
15554               c = {},
15555               k;
15556           if (a === null || _typeof(a) !== "object") a = {};
15557           if (b === null || _typeof(b) !== "object") b = {};
15558
15559           for (k in b) {
15560             if (k in a) {
15561               i[k] = interpolate$1(a[k], b[k]);
15562             } else {
15563               c[k] = b[k];
15564             }
15565           }
15566
15567           return function (t) {
15568             for (k in i) {
15569               c[k] = i[k](t);
15570             }
15571
15572             return c;
15573           };
15574         }
15575
15576         var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,
15577             reB = new RegExp(reA.source, "g");
15578
15579         function zero(b) {
15580           return function () {
15581             return b;
15582           };
15583         }
15584
15585         function one(b) {
15586           return function (t) {
15587             return b(t) + "";
15588           };
15589         }
15590
15591         function interpolateString (a, b) {
15592           var bi = reA.lastIndex = reB.lastIndex = 0,
15593               // scan index for next number in b
15594           am,
15595               // current match in a
15596           bm,
15597               // current match in b
15598           bs,
15599               // string preceding current number in b, if any
15600           i = -1,
15601               // index in s
15602           s = [],
15603               // string constants and placeholders
15604           q = []; // number interpolators
15605           // Coerce inputs to strings.
15606
15607           a = a + "", b = b + ""; // Interpolate pairs of numbers in a & b.
15608
15609           while ((am = reA.exec(a)) && (bm = reB.exec(b))) {
15610             if ((bs = bm.index) > bi) {
15611               // a string precedes the next number in b
15612               bs = b.slice(bi, bs);
15613               if (s[i]) s[i] += bs; // coalesce with previous string
15614               else s[++i] = bs;
15615             }
15616
15617             if ((am = am[0]) === (bm = bm[0])) {
15618               // numbers in a & b match
15619               if (s[i]) s[i] += bm; // coalesce with previous string
15620               else s[++i] = bm;
15621             } else {
15622               // interpolate non-matching numbers
15623               s[++i] = null;
15624               q.push({
15625                 i: i,
15626                 x: d3_interpolateNumber(am, bm)
15627               });
15628             }
15629
15630             bi = reB.lastIndex;
15631           } // Add remains of b.
15632
15633
15634           if (bi < b.length) {
15635             bs = b.slice(bi);
15636             if (s[i]) s[i] += bs; // coalesce with previous string
15637             else s[++i] = bs;
15638           } // Special optimization for only a single match.
15639           // Otherwise, interpolate each of the numbers and rejoin the string.
15640
15641
15642           return s.length < 2 ? q[0] ? one(q[0].x) : zero(b) : (b = q.length, function (t) {
15643             for (var i = 0, o; i < b; ++i) {
15644               s[(o = q[i]).i] = o.x(t);
15645             }
15646
15647             return s.join("");
15648           });
15649         }
15650
15651         function interpolate$1 (a, b) {
15652           var t = _typeof(b),
15653               c;
15654
15655           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);
15656         }
15657
15658         function interpolateRound (a, b) {
15659           return a = +a, b = +b, function (t) {
15660             return Math.round(a * (1 - t) + b * t);
15661           };
15662         }
15663
15664         var degrees = 180 / Math.PI;
15665         var identity$3 = {
15666           translateX: 0,
15667           translateY: 0,
15668           rotate: 0,
15669           skewX: 0,
15670           scaleX: 1,
15671           scaleY: 1
15672         };
15673         function decompose (a, b, c, d, e, f) {
15674           var scaleX, scaleY, skewX;
15675           if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX;
15676           if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX;
15677           if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY;
15678           if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX;
15679           return {
15680             translateX: e,
15681             translateY: f,
15682             rotate: Math.atan2(b, a) * degrees,
15683             skewX: Math.atan(skewX) * degrees,
15684             scaleX: scaleX,
15685             scaleY: scaleY
15686           };
15687         }
15688
15689         var svgNode;
15690         /* eslint-disable no-undef */
15691
15692         function parseCss(value) {
15693           var m = new (typeof DOMMatrix === "function" ? DOMMatrix : WebKitCSSMatrix)(value + "");
15694           return m.isIdentity ? identity$3 : decompose(m.a, m.b, m.c, m.d, m.e, m.f);
15695         }
15696         function parseSvg(value) {
15697           if (value == null) return identity$3;
15698           if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g");
15699           svgNode.setAttribute("transform", value);
15700           if (!(value = svgNode.transform.baseVal.consolidate())) return identity$3;
15701           value = value.matrix;
15702           return decompose(value.a, value.b, value.c, value.d, value.e, value.f);
15703         }
15704
15705         function interpolateTransform(parse, pxComma, pxParen, degParen) {
15706           function pop(s) {
15707             return s.length ? s.pop() + " " : "";
15708           }
15709
15710           function translate(xa, ya, xb, yb, s, q) {
15711             if (xa !== xb || ya !== yb) {
15712               var i = s.push("translate(", null, pxComma, null, pxParen);
15713               q.push({
15714                 i: i - 4,
15715                 x: d3_interpolateNumber(xa, xb)
15716               }, {
15717                 i: i - 2,
15718                 x: d3_interpolateNumber(ya, yb)
15719               });
15720             } else if (xb || yb) {
15721               s.push("translate(" + xb + pxComma + yb + pxParen);
15722             }
15723           }
15724
15725           function rotate(a, b, s, q) {
15726             if (a !== b) {
15727               if (a - b > 180) b += 360;else if (b - a > 180) a += 360; // shortest path
15728
15729               q.push({
15730                 i: s.push(pop(s) + "rotate(", null, degParen) - 2,
15731                 x: d3_interpolateNumber(a, b)
15732               });
15733             } else if (b) {
15734               s.push(pop(s) + "rotate(" + b + degParen);
15735             }
15736           }
15737
15738           function skewX(a, b, s, q) {
15739             if (a !== b) {
15740               q.push({
15741                 i: s.push(pop(s) + "skewX(", null, degParen) - 2,
15742                 x: d3_interpolateNumber(a, b)
15743               });
15744             } else if (b) {
15745               s.push(pop(s) + "skewX(" + b + degParen);
15746             }
15747           }
15748
15749           function scale(xa, ya, xb, yb, s, q) {
15750             if (xa !== xb || ya !== yb) {
15751               var i = s.push(pop(s) + "scale(", null, ",", null, ")");
15752               q.push({
15753                 i: i - 4,
15754                 x: d3_interpolateNumber(xa, xb)
15755               }, {
15756                 i: i - 2,
15757                 x: d3_interpolateNumber(ya, yb)
15758               });
15759             } else if (xb !== 1 || yb !== 1) {
15760               s.push(pop(s) + "scale(" + xb + "," + yb + ")");
15761             }
15762           }
15763
15764           return function (a, b) {
15765             var s = [],
15766                 // string constants and placeholders
15767             q = []; // number interpolators
15768
15769             a = parse(a), b = parse(b);
15770             translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q);
15771             rotate(a.rotate, b.rotate, s, q);
15772             skewX(a.skewX, b.skewX, s, q);
15773             scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q);
15774             a = b = null; // gc
15775
15776             return function (t) {
15777               var i = -1,
15778                   n = q.length,
15779                   o;
15780
15781               while (++i < n) {
15782                 s[(o = q[i]).i] = o.x(t);
15783               }
15784
15785               return s.join("");
15786             };
15787           };
15788         }
15789
15790         var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)");
15791         var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")");
15792
15793         var epsilon2 = 1e-12;
15794
15795         function cosh(x) {
15796           return ((x = Math.exp(x)) + 1 / x) / 2;
15797         }
15798
15799         function sinh(x) {
15800           return ((x = Math.exp(x)) - 1 / x) / 2;
15801         }
15802
15803         function tanh(x) {
15804           return ((x = Math.exp(2 * x)) - 1) / (x + 1);
15805         }
15806
15807         var interpolateZoom = (function zoomRho(rho, rho2, rho4) {
15808           // p0 = [ux0, uy0, w0]
15809           // p1 = [ux1, uy1, w1]
15810           function zoom(p0, p1) {
15811             var ux0 = p0[0],
15812                 uy0 = p0[1],
15813                 w0 = p0[2],
15814                 ux1 = p1[0],
15815                 uy1 = p1[1],
15816                 w1 = p1[2],
15817                 dx = ux1 - ux0,
15818                 dy = uy1 - uy0,
15819                 d2 = dx * dx + dy * dy,
15820                 i,
15821                 S; // Special case for u0 ≅ u1.
15822
15823             if (d2 < epsilon2) {
15824               S = Math.log(w1 / w0) / rho;
15825
15826               i = function i(t) {
15827                 return [ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(rho * t * S)];
15828               };
15829             } // General case.
15830             else {
15831               var d1 = Math.sqrt(d2),
15832                   b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1),
15833                   b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1),
15834                   r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0),
15835                   r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1);
15836               S = (r1 - r0) / rho;
15837
15838               i = function i(t) {
15839                 var s = t * S,
15840                     coshr0 = cosh(r0),
15841                     u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0));
15842                 return [ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / cosh(rho * s + r0)];
15843               };
15844             }
15845
15846             i.duration = S * 1000 * rho / Math.SQRT2;
15847             return i;
15848           }
15849
15850           zoom.rho = function (_) {
15851             var _1 = Math.max(1e-3, +_),
15852                 _2 = _1 * _1,
15853                 _4 = _2 * _2;
15854
15855             return zoomRho(_1, _2, _4);
15856           };
15857
15858           return zoom;
15859         })(Math.SQRT2, 2, 4);
15860
15861         function d3_quantize (interpolator, n) {
15862           var samples = new Array(n);
15863
15864           for (var i = 0; i < n; ++i) {
15865             samples[i] = interpolator(i / (n - 1));
15866           }
15867
15868           return samples;
15869         }
15870
15871         var $$t = _export;
15872         var bind$4 = functionBind;
15873
15874         // `Function.prototype.bind` method
15875         // https://tc39.es/ecma262/#sec-function.prototype.bind
15876         $$t({ target: 'Function', proto: true }, {
15877           bind: bind$4
15878         });
15879
15880         var frame = 0,
15881             // is an animation frame pending?
15882         timeout = 0,
15883             // is a timeout pending?
15884         interval = 0,
15885             // are any timers active?
15886         pokeDelay = 1000,
15887             // how frequently we check for clock skew
15888         taskHead,
15889             taskTail,
15890             clockLast = 0,
15891             clockNow = 0,
15892             clockSkew = 0,
15893             clock = (typeof performance === "undefined" ? "undefined" : _typeof(performance)) === "object" && performance.now ? performance : Date,
15894             setFrame = (typeof window === "undefined" ? "undefined" : _typeof(window)) === "object" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function (f) {
15895           setTimeout(f, 17);
15896         };
15897         function now$1() {
15898           return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew);
15899         }
15900
15901         function clearNow() {
15902           clockNow = 0;
15903         }
15904
15905         function Timer() {
15906           this._call = this._time = this._next = null;
15907         }
15908         Timer.prototype = timer.prototype = {
15909           constructor: Timer,
15910           restart: function restart(callback, delay, time) {
15911             if (typeof callback !== "function") throw new TypeError("callback is not a function");
15912             time = (time == null ? now$1() : +time) + (delay == null ? 0 : +delay);
15913
15914             if (!this._next && taskTail !== this) {
15915               if (taskTail) taskTail._next = this;else taskHead = this;
15916               taskTail = this;
15917             }
15918
15919             this._call = callback;
15920             this._time = time;
15921             sleep();
15922           },
15923           stop: function stop() {
15924             if (this._call) {
15925               this._call = null;
15926               this._time = Infinity;
15927               sleep();
15928             }
15929           }
15930         };
15931         function timer(callback, delay, time) {
15932           var t = new Timer();
15933           t.restart(callback, delay, time);
15934           return t;
15935         }
15936         function timerFlush() {
15937           now$1(); // Get the current time, if not already set.
15938
15939           ++frame; // Pretend we’ve set an alarm, if we haven’t already.
15940
15941           var t = taskHead,
15942               e;
15943
15944           while (t) {
15945             if ((e = clockNow - t._time) >= 0) t._call.call(null, e);
15946             t = t._next;
15947           }
15948
15949           --frame;
15950         }
15951
15952         function wake() {
15953           clockNow = (clockLast = clock.now()) + clockSkew;
15954           frame = timeout = 0;
15955
15956           try {
15957             timerFlush();
15958           } finally {
15959             frame = 0;
15960             nap();
15961             clockNow = 0;
15962           }
15963         }
15964
15965         function poke() {
15966           var now = clock.now(),
15967               delay = now - clockLast;
15968           if (delay > pokeDelay) clockSkew -= delay, clockLast = now;
15969         }
15970
15971         function nap() {
15972           var t0,
15973               t1 = taskHead,
15974               t2,
15975               time = Infinity;
15976
15977           while (t1) {
15978             if (t1._call) {
15979               if (time > t1._time) time = t1._time;
15980               t0 = t1, t1 = t1._next;
15981             } else {
15982               t2 = t1._next, t1._next = null;
15983               t1 = t0 ? t0._next = t2 : taskHead = t2;
15984             }
15985           }
15986
15987           taskTail = t0;
15988           sleep(time);
15989         }
15990
15991         function sleep(time) {
15992           if (frame) return; // Soonest alarm already set, or will be.
15993
15994           if (timeout) timeout = clearTimeout(timeout);
15995           var delay = time - clockNow; // Strictly less than if we recomputed clockNow.
15996
15997           if (delay > 24) {
15998             if (time < Infinity) timeout = setTimeout(wake, time - clock.now() - clockSkew);
15999             if (interval) interval = clearInterval(interval);
16000           } else {
16001             if (!interval) clockLast = clock.now(), interval = setInterval(poke, pokeDelay);
16002             frame = 1, setFrame(wake);
16003           }
16004         }
16005
16006         function d3_timeout (callback, delay, time) {
16007           var t = new Timer();
16008           delay = delay == null ? 0 : +delay;
16009           t.restart(function (elapsed) {
16010             t.stop();
16011             callback(elapsed + delay);
16012           }, delay, time);
16013           return t;
16014         }
16015
16016         var emptyOn = dispatch$8("start", "end", "cancel", "interrupt");
16017         var emptyTween = [];
16018         var CREATED = 0;
16019         var SCHEDULED = 1;
16020         var STARTING = 2;
16021         var STARTED = 3;
16022         var RUNNING = 4;
16023         var ENDING = 5;
16024         var ENDED = 6;
16025         function schedule (node, name, id, index, group, timing) {
16026           var schedules = node.__transition;
16027           if (!schedules) node.__transition = {};else if (id in schedules) return;
16028           create$2(node, id, {
16029             name: name,
16030             index: index,
16031             // For context during callback.
16032             group: group,
16033             // For context during callback.
16034             on: emptyOn,
16035             tween: emptyTween,
16036             time: timing.time,
16037             delay: timing.delay,
16038             duration: timing.duration,
16039             ease: timing.ease,
16040             timer: null,
16041             state: CREATED
16042           });
16043         }
16044         function init(node, id) {
16045           var schedule = get$1(node, id);
16046           if (schedule.state > CREATED) throw new Error("too late; already scheduled");
16047           return schedule;
16048         }
16049         function set(node, id) {
16050           var schedule = get$1(node, id);
16051           if (schedule.state > STARTED) throw new Error("too late; already running");
16052           return schedule;
16053         }
16054         function get$1(node, id) {
16055           var schedule = node.__transition;
16056           if (!schedule || !(schedule = schedule[id])) throw new Error("transition not found");
16057           return schedule;
16058         }
16059
16060         function create$2(node, id, self) {
16061           var schedules = node.__transition,
16062               tween; // Initialize the self timer when the transition is created.
16063           // Note the actual delay is not known until the first callback!
16064
16065           schedules[id] = self;
16066           self.timer = timer(schedule, 0, self.time);
16067
16068           function schedule(elapsed) {
16069             self.state = SCHEDULED;
16070             self.timer.restart(start, self.delay, self.time); // If the elapsed delay is less than our first sleep, start immediately.
16071
16072             if (self.delay <= elapsed) start(elapsed - self.delay);
16073           }
16074
16075           function start(elapsed) {
16076             var i, j, n, o; // If the state is not SCHEDULED, then we previously errored on start.
16077
16078             if (self.state !== SCHEDULED) return stop();
16079
16080             for (i in schedules) {
16081               o = schedules[i];
16082               if (o.name !== self.name) continue; // While this element already has a starting transition during this frame,
16083               // defer starting an interrupting transition until that transition has a
16084               // chance to tick (and possibly end); see d3/d3-transition#54!
16085
16086               if (o.state === STARTED) return d3_timeout(start); // Interrupt the active transition, if any.
16087
16088               if (o.state === RUNNING) {
16089                 o.state = ENDED;
16090                 o.timer.stop();
16091                 o.on.call("interrupt", node, node.__data__, o.index, o.group);
16092                 delete schedules[i];
16093               } // Cancel any pre-empted transitions.
16094               else if (+i < id) {
16095                 o.state = ENDED;
16096                 o.timer.stop();
16097                 o.on.call("cancel", node, node.__data__, o.index, o.group);
16098                 delete schedules[i];
16099               }
16100             } // Defer the first tick to end of the current frame; see d3/d3#1576.
16101             // Note the transition may be canceled after start and before the first tick!
16102             // Note this must be scheduled before the start event; see d3/d3-transition#16!
16103             // Assuming this is successful, subsequent callbacks go straight to tick.
16104
16105
16106             d3_timeout(function () {
16107               if (self.state === STARTED) {
16108                 self.state = RUNNING;
16109                 self.timer.restart(tick, self.delay, self.time);
16110                 tick(elapsed);
16111               }
16112             }); // Dispatch the start event.
16113             // Note this must be done before the tween are initialized.
16114
16115             self.state = STARTING;
16116             self.on.call("start", node, node.__data__, self.index, self.group);
16117             if (self.state !== STARTING) return; // interrupted
16118
16119             self.state = STARTED; // Initialize the tween, deleting null tween.
16120
16121             tween = new Array(n = self.tween.length);
16122
16123             for (i = 0, j = -1; i < n; ++i) {
16124               if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) {
16125                 tween[++j] = o;
16126               }
16127             }
16128
16129             tween.length = j + 1;
16130           }
16131
16132           function tick(elapsed) {
16133             var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1),
16134                 i = -1,
16135                 n = tween.length;
16136
16137             while (++i < n) {
16138               tween[i].call(node, t);
16139             } // Dispatch the end event.
16140
16141
16142             if (self.state === ENDING) {
16143               self.on.call("end", node, node.__data__, self.index, self.group);
16144               stop();
16145             }
16146           }
16147
16148           function stop() {
16149             self.state = ENDED;
16150             self.timer.stop();
16151             delete schedules[id];
16152
16153             for (var i in schedules) {
16154               return;
16155             } // eslint-disable-line no-unused-vars
16156
16157
16158             delete node.__transition;
16159           }
16160         }
16161
16162         function interrupt (node, name) {
16163           var schedules = node.__transition,
16164               schedule,
16165               active,
16166               empty = true,
16167               i;
16168           if (!schedules) return;
16169           name = name == null ? null : name + "";
16170
16171           for (i in schedules) {
16172             if ((schedule = schedules[i]).name !== name) {
16173               empty = false;
16174               continue;
16175             }
16176
16177             active = schedule.state > STARTING && schedule.state < ENDING;
16178             schedule.state = ENDED;
16179             schedule.timer.stop();
16180             schedule.on.call(active ? "interrupt" : "cancel", node, node.__data__, schedule.index, schedule.group);
16181             delete schedules[i];
16182           }
16183
16184           if (empty) delete node.__transition;
16185         }
16186
16187         function selection_interrupt (name) {
16188           return this.each(function () {
16189             interrupt(this, name);
16190           });
16191         }
16192
16193         function tweenRemove(id, name) {
16194           var tween0, tween1;
16195           return function () {
16196             var schedule = set(this, id),
16197                 tween = schedule.tween; // If this node shared tween with the previous node,
16198             // just assign the updated shared tween and we’re done!
16199             // Otherwise, copy-on-write.
16200
16201             if (tween !== tween0) {
16202               tween1 = tween0 = tween;
16203
16204               for (var i = 0, n = tween1.length; i < n; ++i) {
16205                 if (tween1[i].name === name) {
16206                   tween1 = tween1.slice();
16207                   tween1.splice(i, 1);
16208                   break;
16209                 }
16210               }
16211             }
16212
16213             schedule.tween = tween1;
16214           };
16215         }
16216
16217         function tweenFunction(id, name, value) {
16218           var tween0, tween1;
16219           if (typeof value !== "function") throw new Error();
16220           return function () {
16221             var schedule = set(this, id),
16222                 tween = schedule.tween; // If this node shared tween with the previous node,
16223             // just assign the updated shared tween and we’re done!
16224             // Otherwise, copy-on-write.
16225
16226             if (tween !== tween0) {
16227               tween1 = (tween0 = tween).slice();
16228
16229               for (var t = {
16230                 name: name,
16231                 value: value
16232               }, i = 0, n = tween1.length; i < n; ++i) {
16233                 if (tween1[i].name === name) {
16234                   tween1[i] = t;
16235                   break;
16236                 }
16237               }
16238
16239               if (i === n) tween1.push(t);
16240             }
16241
16242             schedule.tween = tween1;
16243           };
16244         }
16245
16246         function transition_tween (name, value) {
16247           var id = this._id;
16248           name += "";
16249
16250           if (arguments.length < 2) {
16251             var tween = get$1(this.node(), id).tween;
16252
16253             for (var i = 0, n = tween.length, t; i < n; ++i) {
16254               if ((t = tween[i]).name === name) {
16255                 return t.value;
16256               }
16257             }
16258
16259             return null;
16260           }
16261
16262           return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value));
16263         }
16264         function tweenValue(transition, name, value) {
16265           var id = transition._id;
16266           transition.each(function () {
16267             var schedule = set(this, id);
16268             (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments);
16269           });
16270           return function (node) {
16271             return get$1(node, id).value[name];
16272           };
16273         }
16274
16275         function interpolate (a, b) {
16276           var c;
16277           return (typeof b === "number" ? d3_interpolateNumber : b instanceof color ? d3_interpolateRgb : (c = color(b)) ? (b = c, d3_interpolateRgb) : interpolateString)(a, b);
16278         }
16279
16280         function attrRemove(name) {
16281           return function () {
16282             this.removeAttribute(name);
16283           };
16284         }
16285
16286         function attrRemoveNS(fullname) {
16287           return function () {
16288             this.removeAttributeNS(fullname.space, fullname.local);
16289           };
16290         }
16291
16292         function attrConstant(name, interpolate, value1) {
16293           var string00,
16294               string1 = value1 + "",
16295               interpolate0;
16296           return function () {
16297             var string0 = this.getAttribute(name);
16298             return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1);
16299           };
16300         }
16301
16302         function attrConstantNS(fullname, interpolate, value1) {
16303           var string00,
16304               string1 = value1 + "",
16305               interpolate0;
16306           return function () {
16307             var string0 = this.getAttributeNS(fullname.space, fullname.local);
16308             return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1);
16309           };
16310         }
16311
16312         function attrFunction(name, interpolate, value) {
16313           var string00, string10, interpolate0;
16314           return function () {
16315             var string0,
16316                 value1 = value(this),
16317                 string1;
16318             if (value1 == null) return void this.removeAttribute(name);
16319             string0 = this.getAttribute(name);
16320             string1 = value1 + "";
16321             return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1));
16322           };
16323         }
16324
16325         function attrFunctionNS(fullname, interpolate, value) {
16326           var string00, string10, interpolate0;
16327           return function () {
16328             var string0,
16329                 value1 = value(this),
16330                 string1;
16331             if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local);
16332             string0 = this.getAttributeNS(fullname.space, fullname.local);
16333             string1 = value1 + "";
16334             return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1));
16335           };
16336         }
16337
16338         function transition_attr (name, value) {
16339           var fullname = namespace(name),
16340               i = fullname === "transform" ? interpolateTransformSvg : interpolate;
16341           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));
16342         }
16343
16344         function attrInterpolate(name, i) {
16345           return function (t) {
16346             this.setAttribute(name, i.call(this, t));
16347           };
16348         }
16349
16350         function attrInterpolateNS(fullname, i) {
16351           return function (t) {
16352             this.setAttributeNS(fullname.space, fullname.local, i.call(this, t));
16353           };
16354         }
16355
16356         function attrTweenNS(fullname, value) {
16357           var t0, i0;
16358
16359           function tween() {
16360             var i = value.apply(this, arguments);
16361             if (i !== i0) t0 = (i0 = i) && attrInterpolateNS(fullname, i);
16362             return t0;
16363           }
16364
16365           tween._value = value;
16366           return tween;
16367         }
16368
16369         function attrTween(name, value) {
16370           var t0, i0;
16371
16372           function tween() {
16373             var i = value.apply(this, arguments);
16374             if (i !== i0) t0 = (i0 = i) && attrInterpolate(name, i);
16375             return t0;
16376           }
16377
16378           tween._value = value;
16379           return tween;
16380         }
16381
16382         function transition_attrTween (name, value) {
16383           var key = "attr." + name;
16384           if (arguments.length < 2) return (key = this.tween(key)) && key._value;
16385           if (value == null) return this.tween(key, null);
16386           if (typeof value !== "function") throw new Error();
16387           var fullname = namespace(name);
16388           return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value));
16389         }
16390
16391         function delayFunction(id, value) {
16392           return function () {
16393             init(this, id).delay = +value.apply(this, arguments);
16394           };
16395         }
16396
16397         function delayConstant(id, value) {
16398           return value = +value, function () {
16399             init(this, id).delay = value;
16400           };
16401         }
16402
16403         function transition_delay (value) {
16404           var id = this._id;
16405           return arguments.length ? this.each((typeof value === "function" ? delayFunction : delayConstant)(id, value)) : get$1(this.node(), id).delay;
16406         }
16407
16408         function durationFunction(id, value) {
16409           return function () {
16410             set(this, id).duration = +value.apply(this, arguments);
16411           };
16412         }
16413
16414         function durationConstant(id, value) {
16415           return value = +value, function () {
16416             set(this, id).duration = value;
16417           };
16418         }
16419
16420         function transition_duration (value) {
16421           var id = this._id;
16422           return arguments.length ? this.each((typeof value === "function" ? durationFunction : durationConstant)(id, value)) : get$1(this.node(), id).duration;
16423         }
16424
16425         function easeConstant(id, value) {
16426           if (typeof value !== "function") throw new Error();
16427           return function () {
16428             set(this, id).ease = value;
16429           };
16430         }
16431
16432         function transition_ease (value) {
16433           var id = this._id;
16434           return arguments.length ? this.each(easeConstant(id, value)) : get$1(this.node(), id).ease;
16435         }
16436
16437         function easeVarying(id, value) {
16438           return function () {
16439             var v = value.apply(this, arguments);
16440             if (typeof v !== "function") throw new Error();
16441             set(this, id).ease = v;
16442           };
16443         }
16444
16445         function transition_easeVarying (value) {
16446           if (typeof value !== "function") throw new Error();
16447           return this.each(easeVarying(this._id, value));
16448         }
16449
16450         function transition_filter (match) {
16451           if (typeof match !== "function") match = matcher(match);
16452
16453           for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
16454             for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
16455               if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
16456                 subgroup.push(node);
16457               }
16458             }
16459           }
16460
16461           return new Transition(subgroups, this._parents, this._name, this._id);
16462         }
16463
16464         function transition_merge (transition) {
16465           if (transition._id !== this._id) throw new Error();
16466
16467           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) {
16468             for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
16469               if (node = group0[i] || group1[i]) {
16470                 merge[i] = node;
16471               }
16472             }
16473           }
16474
16475           for (; j < m0; ++j) {
16476             merges[j] = groups0[j];
16477           }
16478
16479           return new Transition(merges, this._parents, this._name, this._id);
16480         }
16481
16482         function start(name) {
16483           return (name + "").trim().split(/^|\s+/).every(function (t) {
16484             var i = t.indexOf(".");
16485             if (i >= 0) t = t.slice(0, i);
16486             return !t || t === "start";
16487           });
16488         }
16489
16490         function onFunction(id, name, listener) {
16491           var on0,
16492               on1,
16493               sit = start(name) ? init : set;
16494           return function () {
16495             var schedule = sit(this, id),
16496                 on = schedule.on; // If this node shared a dispatch with the previous node,
16497             // just assign the updated shared dispatch and we’re done!
16498             // Otherwise, copy-on-write.
16499
16500             if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener);
16501             schedule.on = on1;
16502           };
16503         }
16504
16505         function transition_on (name, listener) {
16506           var id = this._id;
16507           return arguments.length < 2 ? get$1(this.node(), id).on.on(name) : this.each(onFunction(id, name, listener));
16508         }
16509
16510         function removeFunction(id) {
16511           return function () {
16512             var parent = this.parentNode;
16513
16514             for (var i in this.__transition) {
16515               if (+i !== id) return;
16516             }
16517
16518             if (parent) parent.removeChild(this);
16519           };
16520         }
16521
16522         function transition_remove () {
16523           return this.on("end.remove", removeFunction(this._id));
16524         }
16525
16526         function transition_select (select) {
16527           var name = this._name,
16528               id = this._id;
16529           if (typeof select !== "function") select = selector(select);
16530
16531           for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
16532             for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
16533               if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
16534                 if ("__data__" in node) subnode.__data__ = node.__data__;
16535                 subgroup[i] = subnode;
16536                 schedule(subgroup[i], name, id, i, subgroup, get$1(node, id));
16537               }
16538             }
16539           }
16540
16541           return new Transition(subgroups, this._parents, name, id);
16542         }
16543
16544         function transition_selectAll (select) {
16545           var name = this._name,
16546               id = this._id;
16547           if (typeof select !== "function") select = selectorAll(select);
16548
16549           for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
16550             for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
16551               if (node = group[i]) {
16552                 for (var children = select.call(node, node.__data__, i, group), child, inherit = get$1(node, id), k = 0, l = children.length; k < l; ++k) {
16553                   if (child = children[k]) {
16554                     schedule(child, name, id, k, children, inherit);
16555                   }
16556                 }
16557
16558                 subgroups.push(children);
16559                 parents.push(node);
16560               }
16561             }
16562           }
16563
16564           return new Transition(subgroups, parents, name, id);
16565         }
16566
16567         var Selection = selection.prototype.constructor;
16568         function transition_selection () {
16569           return new Selection(this._groups, this._parents);
16570         }
16571
16572         function styleNull(name, interpolate) {
16573           var string00, string10, interpolate0;
16574           return function () {
16575             var string0 = styleValue(this, name),
16576                 string1 = (this.style.removeProperty(name), styleValue(this, name));
16577             return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : interpolate0 = interpolate(string00 = string0, string10 = string1);
16578           };
16579         }
16580
16581         function styleRemove(name) {
16582           return function () {
16583             this.style.removeProperty(name);
16584           };
16585         }
16586
16587         function styleConstant(name, interpolate, value1) {
16588           var string00,
16589               string1 = value1 + "",
16590               interpolate0;
16591           return function () {
16592             var string0 = styleValue(this, name);
16593             return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1);
16594           };
16595         }
16596
16597         function styleFunction(name, interpolate, value) {
16598           var string00, string10, interpolate0;
16599           return function () {
16600             var string0 = styleValue(this, name),
16601                 value1 = value(this),
16602                 string1 = value1 + "";
16603             if (value1 == null) string1 = value1 = (this.style.removeProperty(name), styleValue(this, name));
16604             return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1));
16605           };
16606         }
16607
16608         function styleMaybeRemove(id, name) {
16609           var on0,
16610               on1,
16611               listener0,
16612               key = "style." + name,
16613               event = "end." + key,
16614               remove;
16615           return function () {
16616             var schedule = set(this, id),
16617                 on = schedule.on,
16618                 listener = schedule.value[key] == null ? remove || (remove = styleRemove(name)) : undefined; // If this node shared a dispatch with the previous node,
16619             // just assign the updated shared dispatch and we’re done!
16620             // Otherwise, copy-on-write.
16621
16622             if (on !== on0 || listener0 !== listener) (on1 = (on0 = on).copy()).on(event, listener0 = listener);
16623             schedule.on = on1;
16624           };
16625         }
16626
16627         function transition_style (name, value, priority) {
16628           var i = (name += "") === "transform" ? interpolateTransformCss : interpolate;
16629           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);
16630         }
16631
16632         function styleInterpolate(name, i, priority) {
16633           return function (t) {
16634             this.style.setProperty(name, i.call(this, t), priority);
16635           };
16636         }
16637
16638         function styleTween(name, value, priority) {
16639           var t, i0;
16640
16641           function tween() {
16642             var i = value.apply(this, arguments);
16643             if (i !== i0) t = (i0 = i) && styleInterpolate(name, i, priority);
16644             return t;
16645           }
16646
16647           tween._value = value;
16648           return tween;
16649         }
16650
16651         function transition_styleTween (name, value, priority) {
16652           var key = "style." + (name += "");
16653           if (arguments.length < 2) return (key = this.tween(key)) && key._value;
16654           if (value == null) return this.tween(key, null);
16655           if (typeof value !== "function") throw new Error();
16656           return this.tween(key, styleTween(name, value, priority == null ? "" : priority));
16657         }
16658
16659         function textConstant(value) {
16660           return function () {
16661             this.textContent = value;
16662           };
16663         }
16664
16665         function textFunction(value) {
16666           return function () {
16667             var value1 = value(this);
16668             this.textContent = value1 == null ? "" : value1;
16669           };
16670         }
16671
16672         function transition_text (value) {
16673           return this.tween("text", typeof value === "function" ? textFunction(tweenValue(this, "text", value)) : textConstant(value == null ? "" : value + ""));
16674         }
16675
16676         function textInterpolate(i) {
16677           return function (t) {
16678             this.textContent = i.call(this, t);
16679           };
16680         }
16681
16682         function textTween(value) {
16683           var t0, i0;
16684
16685           function tween() {
16686             var i = value.apply(this, arguments);
16687             if (i !== i0) t0 = (i0 = i) && textInterpolate(i);
16688             return t0;
16689           }
16690
16691           tween._value = value;
16692           return tween;
16693         }
16694
16695         function transition_textTween (value) {
16696           var key = "text";
16697           if (arguments.length < 1) return (key = this.tween(key)) && key._value;
16698           if (value == null) return this.tween(key, null);
16699           if (typeof value !== "function") throw new Error();
16700           return this.tween(key, textTween(value));
16701         }
16702
16703         function transition_transition () {
16704           var name = this._name,
16705               id0 = this._id,
16706               id1 = newId();
16707
16708           for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
16709             for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
16710               if (node = group[i]) {
16711                 var inherit = get$1(node, id0);
16712                 schedule(node, name, id1, i, group, {
16713                   time: inherit.time + inherit.delay + inherit.duration,
16714                   delay: 0,
16715                   duration: inherit.duration,
16716                   ease: inherit.ease
16717                 });
16718               }
16719             }
16720           }
16721
16722           return new Transition(groups, this._parents, name, id1);
16723         }
16724
16725         function transition_end () {
16726           var on0,
16727               on1,
16728               that = this,
16729               id = that._id,
16730               size = that.size();
16731           return new Promise(function (resolve, reject) {
16732             var cancel = {
16733               value: reject
16734             },
16735                 end = {
16736               value: function value() {
16737                 if (--size === 0) resolve();
16738               }
16739             };
16740             that.each(function () {
16741               var schedule = set(this, id),
16742                   on = schedule.on; // If this node shared a dispatch with the previous node,
16743               // just assign the updated shared dispatch and we’re done!
16744               // Otherwise, copy-on-write.
16745
16746               if (on !== on0) {
16747                 on1 = (on0 = on).copy();
16748
16749                 on1._.cancel.push(cancel);
16750
16751                 on1._.interrupt.push(cancel);
16752
16753                 on1._.end.push(end);
16754               }
16755
16756               schedule.on = on1;
16757             }); // The selection was empty, resolve end immediately
16758
16759             if (size === 0) resolve();
16760           });
16761         }
16762
16763         var id = 0;
16764         function Transition(groups, parents, name, id) {
16765           this._groups = groups;
16766           this._parents = parents;
16767           this._name = name;
16768           this._id = id;
16769         }
16770         function newId() {
16771           return ++id;
16772         }
16773         var selection_prototype = selection.prototype;
16774         Transition.prototype = _defineProperty({
16775           constructor: Transition,
16776           select: transition_select,
16777           selectAll: transition_selectAll,
16778           filter: transition_filter,
16779           merge: transition_merge,
16780           selection: transition_selection,
16781           transition: transition_transition,
16782           call: selection_prototype.call,
16783           nodes: selection_prototype.nodes,
16784           node: selection_prototype.node,
16785           size: selection_prototype.size,
16786           empty: selection_prototype.empty,
16787           each: selection_prototype.each,
16788           on: transition_on,
16789           attr: transition_attr,
16790           attrTween: transition_attrTween,
16791           style: transition_style,
16792           styleTween: transition_styleTween,
16793           text: transition_text,
16794           textTween: transition_textTween,
16795           remove: transition_remove,
16796           tween: transition_tween,
16797           delay: transition_delay,
16798           duration: transition_duration,
16799           ease: transition_ease,
16800           easeVarying: transition_easeVarying,
16801           end: transition_end
16802         }, Symbol.iterator, selection_prototype[Symbol.iterator]);
16803
16804         var linear$1 = function linear(t) {
16805           return +t;
16806         };
16807
16808         function cubicInOut(t) {
16809           return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
16810         }
16811
16812         var defaultTiming = {
16813           time: null,
16814           // Set on use.
16815           delay: 0,
16816           duration: 250,
16817           ease: cubicInOut
16818         };
16819
16820         function inherit(node, id) {
16821           var timing;
16822
16823           while (!(timing = node.__transition) || !(timing = timing[id])) {
16824             if (!(node = node.parentNode)) {
16825               throw new Error("transition ".concat(id, " not found"));
16826             }
16827           }
16828
16829           return timing;
16830         }
16831
16832         function selection_transition (name) {
16833           var id, timing;
16834
16835           if (name instanceof Transition) {
16836             id = name._id, name = name._name;
16837           } else {
16838             id = newId(), (timing = defaultTiming).time = now$1(), name = name == null ? null : name + "";
16839           }
16840
16841           for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
16842             for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
16843               if (node = group[i]) {
16844                 schedule(node, name, id, i, group, timing || inherit(node, id));
16845               }
16846             }
16847           }
16848
16849           return new Transition(groups, this._parents, name, id);
16850         }
16851
16852         selection.prototype.interrupt = selection_interrupt;
16853         selection.prototype.transition = selection_transition;
16854
16855         var constant = (function (x) {
16856           return function () {
16857             return x;
16858           };
16859         });
16860
16861         function ZoomEvent(type, _ref) {
16862           var sourceEvent = _ref.sourceEvent,
16863               target = _ref.target,
16864               transform = _ref.transform,
16865               dispatch = _ref.dispatch;
16866           Object.defineProperties(this, {
16867             type: {
16868               value: type,
16869               enumerable: true,
16870               configurable: true
16871             },
16872             sourceEvent: {
16873               value: sourceEvent,
16874               enumerable: true,
16875               configurable: true
16876             },
16877             target: {
16878               value: target,
16879               enumerable: true,
16880               configurable: true
16881             },
16882             transform: {
16883               value: transform,
16884               enumerable: true,
16885               configurable: true
16886             },
16887             _: {
16888               value: dispatch
16889             }
16890           });
16891         }
16892
16893         function Transform(k, x, y) {
16894           this.k = k;
16895           this.x = x;
16896           this.y = y;
16897         }
16898         Transform.prototype = {
16899           constructor: Transform,
16900           scale: function scale(k) {
16901             return k === 1 ? this : new Transform(this.k * k, this.x, this.y);
16902           },
16903           translate: function translate(x, y) {
16904             return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y);
16905           },
16906           apply: function apply(point) {
16907             return [point[0] * this.k + this.x, point[1] * this.k + this.y];
16908           },
16909           applyX: function applyX(x) {
16910             return x * this.k + this.x;
16911           },
16912           applyY: function applyY(y) {
16913             return y * this.k + this.y;
16914           },
16915           invert: function invert(location) {
16916             return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k];
16917           },
16918           invertX: function invertX(x) {
16919             return (x - this.x) / this.k;
16920           },
16921           invertY: function invertY(y) {
16922             return (y - this.y) / this.k;
16923           },
16924           rescaleX: function rescaleX(x) {
16925             return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x));
16926           },
16927           rescaleY: function rescaleY(y) {
16928             return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y));
16929           },
16930           toString: function toString() {
16931             return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")";
16932           }
16933         };
16934         var identity$2 = new Transform(1, 0, 0);
16935
16936         function nopropagation(event) {
16937           event.stopImmediatePropagation();
16938         }
16939         function noevent (event) {
16940           event.preventDefault();
16941           event.stopImmediatePropagation();
16942         }
16943
16944         // except for pinch-to-zoom, which is sent as a wheel+ctrlKey event
16945
16946         function defaultFilter$1(event) {
16947           return (!event.ctrlKey || event.type === 'wheel') && !event.button;
16948         }
16949
16950         function defaultExtent$1() {
16951           var e = this;
16952
16953           if (e instanceof SVGElement) {
16954             e = e.ownerSVGElement || e;
16955
16956             if (e.hasAttribute("viewBox")) {
16957               e = e.viewBox.baseVal;
16958               return [[e.x, e.y], [e.x + e.width, e.y + e.height]];
16959             }
16960
16961             return [[0, 0], [e.width.baseVal.value, e.height.baseVal.value]];
16962           }
16963
16964           return [[0, 0], [e.clientWidth, e.clientHeight]];
16965         }
16966
16967         function defaultTransform() {
16968           return this.__zoom || identity$2;
16969         }
16970
16971         function defaultWheelDelta$1(event) {
16972           return -event.deltaY * (event.deltaMode === 1 ? 0.05 : event.deltaMode ? 1 : 0.002) * (event.ctrlKey ? 10 : 1);
16973         }
16974
16975         function defaultTouchable() {
16976           return navigator.maxTouchPoints || "ontouchstart" in this;
16977         }
16978
16979         function defaultConstrain$1(transform, extent, translateExtent) {
16980           var dx0 = transform.invertX(extent[0][0]) - translateExtent[0][0],
16981               dx1 = transform.invertX(extent[1][0]) - translateExtent[1][0],
16982               dy0 = transform.invertY(extent[0][1]) - translateExtent[0][1],
16983               dy1 = transform.invertY(extent[1][1]) - translateExtent[1][1];
16984           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));
16985         }
16986
16987         function d3_zoom () {
16988           var filter = defaultFilter$1,
16989               extent = defaultExtent$1,
16990               constrain = defaultConstrain$1,
16991               wheelDelta = defaultWheelDelta$1,
16992               touchable = defaultTouchable,
16993               scaleExtent = [0, Infinity],
16994               translateExtent = [[-Infinity, -Infinity], [Infinity, Infinity]],
16995               duration = 250,
16996               interpolate = interpolateZoom,
16997               listeners = dispatch$8("start", "zoom", "end"),
16998               touchstarting,
16999               touchfirst,
17000               touchending,
17001               touchDelay = 500,
17002               wheelDelay = 150,
17003               clickDistance2 = 0,
17004               tapDistance = 10;
17005
17006           function zoom(selection) {
17007             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)");
17008           }
17009
17010           zoom.transform = function (collection, transform, point, event) {
17011             var selection = collection.selection ? collection.selection() : collection;
17012             selection.property("__zoom", defaultTransform);
17013
17014             if (collection !== selection) {
17015               schedule(collection, transform, point, event);
17016             } else {
17017               selection.interrupt().each(function () {
17018                 gesture(this, arguments).event(event).start().zoom(null, typeof transform === "function" ? transform.apply(this, arguments) : transform).end();
17019               });
17020             }
17021           };
17022
17023           zoom.scaleBy = function (selection, k, p, event) {
17024             zoom.scaleTo(selection, function () {
17025               var k0 = this.__zoom.k,
17026                   k1 = typeof k === "function" ? k.apply(this, arguments) : k;
17027               return k0 * k1;
17028             }, p, event);
17029           };
17030
17031           zoom.scaleTo = function (selection, k, p, event) {
17032             zoom.transform(selection, function () {
17033               var e = extent.apply(this, arguments),
17034                   t0 = this.__zoom,
17035                   p0 = p == null ? centroid(e) : typeof p === "function" ? p.apply(this, arguments) : p,
17036                   p1 = t0.invert(p0),
17037                   k1 = typeof k === "function" ? k.apply(this, arguments) : k;
17038               return constrain(translate(scale(t0, k1), p0, p1), e, translateExtent);
17039             }, p, event);
17040           };
17041
17042           zoom.translateBy = function (selection, x, y, event) {
17043             zoom.transform(selection, function () {
17044               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);
17045             }, null, event);
17046           };
17047
17048           zoom.translateTo = function (selection, x, y, p, event) {
17049             zoom.transform(selection, function () {
17050               var e = extent.apply(this, arguments),
17051                   t = this.__zoom,
17052                   p0 = p == null ? centroid(e) : typeof p === "function" ? p.apply(this, arguments) : p;
17053               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);
17054             }, p, event);
17055           };
17056
17057           function scale(transform, k) {
17058             k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], k));
17059             return k === transform.k ? transform : new Transform(k, transform.x, transform.y);
17060           }
17061
17062           function translate(transform, p0, p1) {
17063             var x = p0[0] - p1[0] * transform.k,
17064                 y = p0[1] - p1[1] * transform.k;
17065             return x === transform.x && y === transform.y ? transform : new Transform(transform.k, x, y);
17066           }
17067
17068           function centroid(extent) {
17069             return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2];
17070           }
17071
17072           function schedule(transition, transform, point, event) {
17073             transition.on("start.zoom", function () {
17074               gesture(this, arguments).event(event).start();
17075             }).on("interrupt.zoom end.zoom", function () {
17076               gesture(this, arguments).event(event).end();
17077             }).tween("zoom", function () {
17078               var that = this,
17079                   args = arguments,
17080                   g = gesture(that, args).event(event),
17081                   e = extent.apply(that, args),
17082                   p = point == null ? centroid(e) : typeof point === "function" ? point.apply(that, args) : point,
17083                   w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]),
17084                   a = that.__zoom,
17085                   b = typeof transform === "function" ? transform.apply(that, args) : transform,
17086                   i = interpolate(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k));
17087               return function (t) {
17088                 if (t === 1) t = b; // Avoid rounding error on end.
17089                 else {
17090                   var l = i(t),
17091                       k = w / l[2];
17092                   t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k);
17093                 }
17094                 g.zoom(null, t);
17095               };
17096             });
17097           }
17098
17099           function gesture(that, args, clean) {
17100             return !clean && that.__zooming || new Gesture(that, args);
17101           }
17102
17103           function Gesture(that, args) {
17104             this.that = that;
17105             this.args = args;
17106             this.active = 0;
17107             this.sourceEvent = null;
17108             this.extent = extent.apply(that, args);
17109             this.taps = 0;
17110           }
17111
17112           Gesture.prototype = {
17113             event: function event(_event) {
17114               if (_event) this.sourceEvent = _event;
17115               return this;
17116             },
17117             start: function start() {
17118               if (++this.active === 1) {
17119                 this.that.__zooming = this;
17120                 this.emit("start");
17121               }
17122
17123               return this;
17124             },
17125             zoom: function zoom(key, transform) {
17126               if (this.mouse && key !== "mouse") this.mouse[1] = transform.invert(this.mouse[0]);
17127               if (this.touch0 && key !== "touch") this.touch0[1] = transform.invert(this.touch0[0]);
17128               if (this.touch1 && key !== "touch") this.touch1[1] = transform.invert(this.touch1[0]);
17129               this.that.__zoom = transform;
17130               this.emit("zoom");
17131               return this;
17132             },
17133             end: function end() {
17134               if (--this.active === 0) {
17135                 delete this.that.__zooming;
17136                 this.emit("end");
17137               }
17138
17139               return this;
17140             },
17141             emit: function emit(type) {
17142               var d = select(this.that).datum();
17143               listeners.call(type, this.that, new ZoomEvent(type, {
17144                 sourceEvent: this.sourceEvent,
17145                 target: zoom,
17146                 type: type,
17147                 transform: this.that.__zoom,
17148                 dispatch: listeners
17149               }), d);
17150             }
17151           };
17152
17153           function wheeled(event) {
17154             for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
17155               args[_key - 1] = arguments[_key];
17156             }
17157
17158             if (!filter.apply(this, arguments)) return;
17159             var g = gesture(this, args).event(event),
17160                 t = this.__zoom,
17161                 k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], t.k * Math.pow(2, wheelDelta.apply(this, arguments)))),
17162                 p = pointer(event); // If the mouse is in the same location as before, reuse it.
17163             // If there were recent wheel events, reset the wheel idle timeout.
17164
17165             if (g.wheel) {
17166               if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) {
17167                 g.mouse[1] = t.invert(g.mouse[0] = p);
17168               }
17169
17170               clearTimeout(g.wheel);
17171             } // If this wheel event won’t trigger a transform change, ignore it.
17172             else if (t.k === k) return; // Otherwise, capture the mouse point and location at the start.
17173             else {
17174               g.mouse = [p, t.invert(p)];
17175               interrupt(this);
17176               g.start();
17177             }
17178
17179             noevent(event);
17180             g.wheel = setTimeout(wheelidled, wheelDelay);
17181             g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent, translateExtent));
17182
17183             function wheelidled() {
17184               g.wheel = null;
17185               g.end();
17186             }
17187           }
17188
17189           function mousedowned(event) {
17190             for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
17191               args[_key2 - 1] = arguments[_key2];
17192             }
17193
17194             if (touchending || !filter.apply(this, arguments)) return;
17195             var g = gesture(this, args, true).event(event),
17196                 v = select(event.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true),
17197                 p = pointer(event, currentTarget),
17198                 currentTarget = event.currentTarget,
17199                 x0 = event.clientX,
17200                 y0 = event.clientY;
17201             dragDisable(event.view);
17202             nopropagation(event);
17203             g.mouse = [p, this.__zoom.invert(p)];
17204             interrupt(this);
17205             g.start();
17206
17207             function mousemoved(event) {
17208               noevent(event);
17209
17210               if (!g.moved) {
17211                 var dx = event.clientX - x0,
17212                     dy = event.clientY - y0;
17213                 g.moved = dx * dx + dy * dy > clickDistance2;
17214               }
17215
17216               g.event(event).zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = pointer(event, currentTarget), g.mouse[1]), g.extent, translateExtent));
17217             }
17218
17219             function mouseupped(event) {
17220               v.on("mousemove.zoom mouseup.zoom", null);
17221               yesdrag(event.view, g.moved);
17222               noevent(event);
17223               g.event(event).end();
17224             }
17225           }
17226
17227           function dblclicked(event) {
17228             for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
17229               args[_key3 - 1] = arguments[_key3];
17230             }
17231
17232             if (!filter.apply(this, arguments)) return;
17233             var t0 = this.__zoom,
17234                 p0 = pointer(event.changedTouches ? event.changedTouches[0] : event, this),
17235                 p1 = t0.invert(p0),
17236                 k1 = t0.k * (event.shiftKey ? 0.5 : 2),
17237                 t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, args), translateExtent);
17238             noevent(event);
17239             if (duration > 0) select(this).transition().duration(duration).call(schedule, t1, p0, event);else select(this).call(zoom.transform, t1, p0, event);
17240           }
17241
17242           function touchstarted(event) {
17243             for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
17244               args[_key4 - 1] = arguments[_key4];
17245             }
17246
17247             if (!filter.apply(this, arguments)) return;
17248             var touches = event.touches,
17249                 n = touches.length,
17250                 g = gesture(this, args, event.changedTouches.length === n).event(event),
17251                 started,
17252                 i,
17253                 t,
17254                 p;
17255             nopropagation(event);
17256
17257             for (i = 0; i < n; ++i) {
17258               t = touches[i], p = pointer(t, this);
17259               p = [p, this.__zoom.invert(p), t.identifier];
17260               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;
17261             }
17262
17263             if (touchstarting) touchstarting = clearTimeout(touchstarting);
17264
17265             if (started) {
17266               if (g.taps < 2) touchfirst = p[0], touchstarting = setTimeout(function () {
17267                 touchstarting = null;
17268               }, touchDelay);
17269               interrupt(this);
17270               g.start();
17271             }
17272           }
17273
17274           function touchmoved(event) {
17275             if (!this.__zooming) return;
17276
17277             for (var _len5 = arguments.length, args = new Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) {
17278               args[_key5 - 1] = arguments[_key5];
17279             }
17280
17281             var g = gesture(this, args).event(event),
17282                 touches = event.changedTouches,
17283                 n = touches.length,
17284                 i,
17285                 t,
17286                 p,
17287                 l;
17288             noevent(event);
17289
17290             for (i = 0; i < n; ++i) {
17291               t = touches[i], p = pointer(t, this);
17292               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;
17293             }
17294
17295             t = g.that.__zoom;
17296
17297             if (g.touch1) {
17298               var p0 = g.touch0[0],
17299                   l0 = g.touch0[1],
17300                   p1 = g.touch1[0],
17301                   l1 = g.touch1[1],
17302                   dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp,
17303                   dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl;
17304               t = scale(t, Math.sqrt(dp / dl));
17305               p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2];
17306               l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];
17307             } else if (g.touch0) p = g.touch0[0], l = g.touch0[1];else return;
17308
17309             g.zoom("touch", constrain(translate(t, p, l), g.extent, translateExtent));
17310           }
17311
17312           function touchended(event) {
17313             for (var _len6 = arguments.length, args = new Array(_len6 > 1 ? _len6 - 1 : 0), _key6 = 1; _key6 < _len6; _key6++) {
17314               args[_key6 - 1] = arguments[_key6];
17315             }
17316
17317             if (!this.__zooming) return;
17318             var g = gesture(this, args).event(event),
17319                 touches = event.changedTouches,
17320                 n = touches.length,
17321                 i,
17322                 t;
17323             nopropagation(event);
17324             if (touchending) clearTimeout(touchending);
17325             touchending = setTimeout(function () {
17326               touchending = null;
17327             }, touchDelay);
17328
17329             for (i = 0; i < n; ++i) {
17330               t = touches[i];
17331               if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0;else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1;
17332             }
17333
17334             if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1;
17335             if (g.touch0) g.touch0[1] = this.__zoom.invert(g.touch0[0]);else {
17336               g.end(); // If this was a dbltap, reroute to the (optional) dblclick.zoom handler.
17337
17338               if (g.taps === 2) {
17339                 t = pointer(t, this);
17340
17341                 if (Math.hypot(touchfirst[0] - t[0], touchfirst[1] - t[1]) < tapDistance) {
17342                   var p = select(this).on("dblclick.zoom");
17343                   if (p) p.apply(this, arguments);
17344                 }
17345               }
17346             }
17347           }
17348
17349           zoom.wheelDelta = function (_) {
17350             return arguments.length ? (wheelDelta = typeof _ === "function" ? _ : constant(+_), zoom) : wheelDelta;
17351           };
17352
17353           zoom.filter = function (_) {
17354             return arguments.length ? (filter = typeof _ === "function" ? _ : constant(!!_), zoom) : filter;
17355           };
17356
17357           zoom.touchable = function (_) {
17358             return arguments.length ? (touchable = typeof _ === "function" ? _ : constant(!!_), zoom) : touchable;
17359           };
17360
17361           zoom.extent = function (_) {
17362             return arguments.length ? (extent = typeof _ === "function" ? _ : constant([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent;
17363           };
17364
17365           zoom.scaleExtent = function (_) {
17366             return arguments.length ? (scaleExtent[0] = +_[0], scaleExtent[1] = +_[1], zoom) : [scaleExtent[0], scaleExtent[1]];
17367           };
17368
17369           zoom.translateExtent = function (_) {
17370             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]]];
17371           };
17372
17373           zoom.constrain = function (_) {
17374             return arguments.length ? (constrain = _, zoom) : constrain;
17375           };
17376
17377           zoom.duration = function (_) {
17378             return arguments.length ? (duration = +_, zoom) : duration;
17379           };
17380
17381           zoom.interpolate = function (_) {
17382             return arguments.length ? (interpolate = _, zoom) : interpolate;
17383           };
17384
17385           zoom.on = function () {
17386             var value = listeners.on.apply(listeners, arguments);
17387             return value === listeners ? zoom : value;
17388           };
17389
17390           zoom.clickDistance = function (_) {
17391             return arguments.length ? (clickDistance2 = (_ = +_) * _, zoom) : Math.sqrt(clickDistance2);
17392           };
17393
17394           zoom.tapDistance = function (_) {
17395             return arguments.length ? (tapDistance = +_, zoom) : tapDistance;
17396           };
17397
17398           return zoom;
17399         }
17400
17401         /*
17402             Bypasses features of D3's default projection stream pipeline that are unnecessary:
17403             * Antimeridian clipping
17404             * Spherical rotation
17405             * Resampling
17406         */
17407
17408         function geoRawMercator() {
17409           var project = mercatorRaw;
17410           var k = 512 / Math.PI; // scale
17411
17412           var x = 0;
17413           var y = 0; // translate
17414
17415           var clipExtent = [[0, 0], [0, 0]];
17416
17417           function projection(point) {
17418             point = project(point[0] * Math.PI / 180, point[1] * Math.PI / 180);
17419             return [point[0] * k + x, y - point[1] * k];
17420           }
17421
17422           projection.invert = function (point) {
17423             point = project.invert((point[0] - x) / k, (y - point[1]) / k);
17424             return point && [point[0] * 180 / Math.PI, point[1] * 180 / Math.PI];
17425           };
17426
17427           projection.scale = function (_) {
17428             if (!arguments.length) return k;
17429             k = +_;
17430             return projection;
17431           };
17432
17433           projection.translate = function (_) {
17434             if (!arguments.length) return [x, y];
17435             x = +_[0];
17436             y = +_[1];
17437             return projection;
17438           };
17439
17440           projection.clipExtent = function (_) {
17441             if (!arguments.length) return clipExtent;
17442             clipExtent = _;
17443             return projection;
17444           };
17445
17446           projection.transform = function (obj) {
17447             if (!arguments.length) return identity$2.translate(x, y).scale(k);
17448             x = +obj.x;
17449             y = +obj.y;
17450             k = +obj.k;
17451             return projection;
17452           };
17453
17454           projection.stream = d3_geoTransform({
17455             point: function point(x, y) {
17456               var vec = projection([x, y]);
17457               this.stream.point(vec[0], vec[1]);
17458             }
17459           }).stream;
17460           return projection;
17461         }
17462
17463         function geoOrthoNormalizedDotProduct(a, b, origin) {
17464           if (geoVecEqual(origin, a) || geoVecEqual(origin, b)) {
17465             return 1; // coincident points, treat as straight and try to remove
17466           }
17467
17468           return geoVecNormalizedDot(a, b, origin);
17469         }
17470
17471         function geoOrthoFilterDotProduct(dotp, epsilon, lowerThreshold, upperThreshold, allowStraightAngles) {
17472           var val = Math.abs(dotp);
17473
17474           if (val < epsilon) {
17475             return 0; // already orthogonal
17476           } else if (allowStraightAngles && Math.abs(val - 1) < epsilon) {
17477             return 0; // straight angle, which is okay in this case
17478           } else if (val < lowerThreshold || val > upperThreshold) {
17479             return dotp; // can be adjusted
17480           } else {
17481             return null; // ignore vertex
17482           }
17483         }
17484
17485         function geoOrthoCalcScore(points, isClosed, epsilon, threshold) {
17486           var score = 0;
17487           var first = isClosed ? 0 : 1;
17488           var last = isClosed ? points.length : points.length - 1;
17489           var coords = points.map(function (p) {
17490             return p.coord;
17491           });
17492           var lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180);
17493           var upperThreshold = Math.cos(threshold * Math.PI / 180);
17494
17495           for (var i = first; i < last; i++) {
17496             var a = coords[(i - 1 + coords.length) % coords.length];
17497             var origin = coords[i];
17498             var b = coords[(i + 1) % coords.length];
17499             var dotp = geoOrthoFilterDotProduct(geoOrthoNormalizedDotProduct(a, b, origin), epsilon, lowerThreshold, upperThreshold);
17500             if (dotp === null) continue; // ignore vertex
17501
17502             score = score + 2.0 * Math.min(Math.abs(dotp - 1.0), Math.min(Math.abs(dotp), Math.abs(dotp + 1)));
17503           }
17504
17505           return score;
17506         } // returns the maximum angle less than `lessThan` between the actual corner and a 0° or 90° corner
17507
17508         function geoOrthoMaxOffsetAngle(coords, isClosed, lessThan) {
17509           var max = -Infinity;
17510           var first = isClosed ? 0 : 1;
17511           var last = isClosed ? coords.length : coords.length - 1;
17512
17513           for (var i = first; i < last; i++) {
17514             var a = coords[(i - 1 + coords.length) % coords.length];
17515             var origin = coords[i];
17516             var b = coords[(i + 1) % coords.length];
17517             var normalizedDotP = geoOrthoNormalizedDotProduct(a, b, origin);
17518             var angle = Math.acos(Math.abs(normalizedDotP)) * 180 / Math.PI;
17519             if (angle > 45) angle = 90 - angle;
17520             if (angle >= lessThan) continue;
17521             if (angle > max) max = angle;
17522           }
17523
17524           if (max === -Infinity) return null;
17525           return max;
17526         } // similar to geoOrthoCalcScore, but returns quickly if there is something to do
17527
17528         function geoOrthoCanOrthogonalize(coords, isClosed, epsilon, threshold, allowStraightAngles) {
17529           var score = null;
17530           var first = isClosed ? 0 : 1;
17531           var last = isClosed ? coords.length : coords.length - 1;
17532           var lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180);
17533           var upperThreshold = Math.cos(threshold * Math.PI / 180);
17534
17535           for (var i = first; i < last; i++) {
17536             var a = coords[(i - 1 + coords.length) % coords.length];
17537             var origin = coords[i];
17538             var b = coords[(i + 1) % coords.length];
17539             var dotp = geoOrthoFilterDotProduct(geoOrthoNormalizedDotProduct(a, b, origin), epsilon, lowerThreshold, upperThreshold, allowStraightAngles);
17540             if (dotp === null) continue; // ignore vertex
17541
17542             if (Math.abs(dotp) > 0) return 1; // something to do
17543
17544             score = 0; // already square
17545           }
17546
17547           return score;
17548         }
17549
17550         var call$3 = functionCall;
17551         var fixRegExpWellKnownSymbolLogic$1 = fixRegexpWellKnownSymbolLogic;
17552         var anObject$1 = anObject$n;
17553         var toLength$3 = toLength$c;
17554         var toString$8 = toString$k;
17555         var requireObjectCoercible$7 = requireObjectCoercible$e;
17556         var getMethod$1 = getMethod$7;
17557         var advanceStringIndex = advanceStringIndex$3;
17558         var regExpExec$1 = regexpExecAbstract;
17559
17560         // @@match logic
17561         fixRegExpWellKnownSymbolLogic$1('match', function (MATCH, nativeMatch, maybeCallNative) {
17562           return [
17563             // `String.prototype.match` method
17564             // https://tc39.es/ecma262/#sec-string.prototype.match
17565             function match(regexp) {
17566               var O = requireObjectCoercible$7(this);
17567               var matcher = regexp == undefined ? undefined : getMethod$1(regexp, MATCH);
17568               return matcher ? call$3(matcher, regexp, O) : new RegExp(regexp)[MATCH](toString$8(O));
17569             },
17570             // `RegExp.prototype[@@match]` method
17571             // https://tc39.es/ecma262/#sec-regexp.prototype-@@match
17572             function (string) {
17573               var rx = anObject$1(this);
17574               var S = toString$8(string);
17575               var res = maybeCallNative(nativeMatch, rx, S);
17576
17577               if (res.done) return res.value;
17578
17579               if (!rx.global) return regExpExec$1(rx, S);
17580
17581               var fullUnicode = rx.unicode;
17582               rx.lastIndex = 0;
17583               var A = [];
17584               var n = 0;
17585               var result;
17586               while ((result = regExpExec$1(rx, S)) !== null) {
17587                 var matchStr = toString$8(result[0]);
17588                 A[n] = matchStr;
17589                 if (matchStr === '') rx.lastIndex = advanceStringIndex(S, toLength$3(rx.lastIndex), fullUnicode);
17590                 n++;
17591               }
17592               return n === 0 ? null : A;
17593             }
17594           ];
17595         });
17596
17597         var $$s = _export;
17598         var FREEZING = freezing;
17599         var fails$9 = fails$S;
17600         var isObject$4 = isObject$s;
17601         var onFreeze = internalMetadata.exports.onFreeze;
17602
17603         // eslint-disable-next-line es/no-object-freeze -- safe
17604         var $freeze = Object.freeze;
17605         var FAILS_ON_PRIMITIVES = fails$9(function () { $freeze(1); });
17606
17607         // `Object.freeze` method
17608         // https://tc39.es/ecma262/#sec-object.freeze
17609         $$s({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES, sham: !FREEZING }, {
17610           freeze: function freeze(it) {
17611             return $freeze && isObject$4(it) ? $freeze(onFreeze(it)) : it;
17612           }
17613         });
17614
17615         // Returns true if a and b have the same elements at the same indices.
17616         function utilArrayIdentical(a, b) {
17617           // an array is always identical to itself
17618           if (a === b) return true;
17619           var i = a.length;
17620           if (i !== b.length) return false;
17621
17622           while (i--) {
17623             if (a[i] !== b[i]) return false;
17624           }
17625
17626           return true;
17627         } // http://2ality.com/2015/01/es6-set-operations.html
17628         // Difference (a \ b): create a set that contains those elements of set a that are not in set b.
17629         // This operation is also sometimes called minus (-).
17630         // var a = [1,2,3];
17631         // var b = [4,3,2];
17632         // utilArrayDifference(a, b)
17633         //   [1]
17634         // utilArrayDifference(b, a)
17635         //   [4]
17636
17637         function utilArrayDifference(a, b) {
17638           var other = new Set(b);
17639           return Array.from(new Set(a)).filter(function (v) {
17640             return !other.has(v);
17641           });
17642         } // Intersection (a ∩ b): create a set that contains those elements of set a that are also in set b.
17643         // var a = [1,2,3];
17644         // var b = [4,3,2];
17645         // utilArrayIntersection(a, b)
17646         //   [2,3]
17647
17648         function utilArrayIntersection(a, b) {
17649           var other = new Set(b);
17650           return Array.from(new Set(a)).filter(function (v) {
17651             return other.has(v);
17652           });
17653         } // Union (a ∪ b): create a set that contains the elements of both set a and set b.
17654         // var a = [1,2,3];
17655         // var b = [4,3,2];
17656         // utilArrayUnion(a, b)
17657         //   [1,2,3,4]
17658
17659         function utilArrayUnion(a, b) {
17660           var result = new Set(a);
17661           b.forEach(function (v) {
17662             result.add(v);
17663           });
17664           return Array.from(result);
17665         } // Returns an Array with all the duplicates removed
17666         // var a = [1,1,2,3,3];
17667         // utilArrayUniq(a)
17668         //   [1,2,3]
17669
17670         function utilArrayUniq(a) {
17671           return Array.from(new Set(a));
17672         } // Splits array into chunks of given chunk size
17673         // var a = [1,2,3,4,5,6,7];
17674         // utilArrayChunk(a, 3);
17675         //   [[1,2,3],[4,5,6],[7]];
17676
17677         function utilArrayChunk(a, chunkSize) {
17678           if (!chunkSize || chunkSize < 0) return [a.slice()];
17679           var result = new Array(Math.ceil(a.length / chunkSize));
17680           return Array.from(result, function (item, i) {
17681             return a.slice(i * chunkSize, i * chunkSize + chunkSize);
17682           });
17683         } // Flattens two level array into a single level
17684         // var a = [[1,2,3],[4,5,6],[7]];
17685         // utilArrayFlatten(a);
17686         //   [1,2,3,4,5,6,7];
17687
17688         function utilArrayFlatten(a) {
17689           return a.reduce(function (acc, val) {
17690             return acc.concat(val);
17691           }, []);
17692         } // Groups the items of the Array according to the given key
17693         // `key` can be passed as a property or as a key function
17694         //
17695         // var pets = [
17696         //     { type: 'Dog', name: 'Spot' },
17697         //     { type: 'Cat', name: 'Tiger' },
17698         //     { type: 'Dog', name: 'Rover' },
17699         //     { type: 'Cat', name: 'Leo' }
17700         // ];
17701         //
17702         // utilArrayGroupBy(pets, 'type')
17703         //   {
17704         //     'Dog': [{type: 'Dog', name: 'Spot'}, {type: 'Dog', name: 'Rover'}],
17705         //     'Cat': [{type: 'Cat', name: 'Tiger'}, {type: 'Cat', name: 'Leo'}]
17706         //   }
17707         //
17708         // utilArrayGroupBy(pets, function(item) { return item.name.length; })
17709         //   {
17710         //     3: [{type: 'Cat', name: 'Leo'}],
17711         //     4: [{type: 'Dog', name: 'Spot'}],
17712         //     5: [{type: 'Cat', name: 'Tiger'}, {type: 'Dog', name: 'Rover'}]
17713         //   }
17714
17715         function utilArrayGroupBy(a, key) {
17716           return a.reduce(function (acc, item) {
17717             var group = typeof key === 'function' ? key(item) : item[key];
17718             (acc[group] = acc[group] || []).push(item);
17719             return acc;
17720           }, {});
17721         } // Returns an Array with all the duplicates removed
17722         // where uniqueness determined by the given key
17723         // `key` can be passed as a property or as a key function
17724         //
17725         // var pets = [
17726         //     { type: 'Dog', name: 'Spot' },
17727         //     { type: 'Cat', name: 'Tiger' },
17728         //     { type: 'Dog', name: 'Rover' },
17729         //     { type: 'Cat', name: 'Leo' }
17730         // ];
17731         //
17732         // utilArrayUniqBy(pets, 'type')
17733         //   [
17734         //     { type: 'Dog', name: 'Spot' },
17735         //     { type: 'Cat', name: 'Tiger' }
17736         //   ]
17737         //
17738         // utilArrayUniqBy(pets, function(item) { return item.name.length; })
17739         //   [
17740         //     { type: 'Dog', name: 'Spot' },
17741         //     { type: 'Cat', name: 'Tiger' },
17742         //     { type: 'Cat', name: 'Leo' }
17743         //   }
17744
17745         function utilArrayUniqBy(a, key) {
17746           var seen = new Set();
17747           return a.reduce(function (acc, item) {
17748             var val = typeof key === 'function' ? key(item) : item[key];
17749
17750             if (val && !seen.has(val)) {
17751               seen.add(val);
17752               acc.push(item);
17753             }
17754
17755             return acc;
17756           }, []);
17757         }
17758
17759         var uncurryThis$d = functionUncurryThis;
17760
17761         // `thisNumberValue` abstract operation
17762         // https://tc39.es/ecma262/#sec-thisnumbervalue
17763         var thisNumberValue$3 = uncurryThis$d(1.0.valueOf);
17764
17765         var DESCRIPTORS$3 = descriptors;
17766         var global$a = global$1m;
17767         var uncurryThis$c = functionUncurryThis;
17768         var isForced = isForced_1;
17769         var redefine$2 = redefine$h.exports;
17770         var hasOwn$1 = hasOwnProperty_1;
17771         var inheritIfRequired = inheritIfRequired$4;
17772         var isPrototypeOf = objectIsPrototypeOf;
17773         var isSymbol$1 = isSymbol$6;
17774         var toPrimitive$1 = toPrimitive$3;
17775         var fails$8 = fails$S;
17776         var getOwnPropertyNames = objectGetOwnPropertyNames.f;
17777         var getOwnPropertyDescriptor$2 = objectGetOwnPropertyDescriptor.f;
17778         var defineProperty = objectDefineProperty.f;
17779         var thisNumberValue$2 = thisNumberValue$3;
17780         var trim$2 = stringTrim.trim;
17781
17782         var NUMBER = 'Number';
17783         var NativeNumber = global$a[NUMBER];
17784         var NumberPrototype = NativeNumber.prototype;
17785         var TypeError$4 = global$a.TypeError;
17786         var arraySlice$1 = uncurryThis$c(''.slice);
17787         var charCodeAt$1 = uncurryThis$c(''.charCodeAt);
17788
17789         // `ToNumeric` abstract operation
17790         // https://tc39.es/ecma262/#sec-tonumeric
17791         var toNumeric = function (value) {
17792           var primValue = toPrimitive$1(value, 'number');
17793           return typeof primValue == 'bigint' ? primValue : toNumber$1(primValue);
17794         };
17795
17796         // `ToNumber` abstract operation
17797         // https://tc39.es/ecma262/#sec-tonumber
17798         var toNumber$1 = function (argument) {
17799           var it = toPrimitive$1(argument, 'number');
17800           var first, third, radix, maxCode, digits, length, index, code;
17801           if (isSymbol$1(it)) throw TypeError$4('Cannot convert a Symbol value to a number');
17802           if (typeof it == 'string' && it.length > 2) {
17803             it = trim$2(it);
17804             first = charCodeAt$1(it, 0);
17805             if (first === 43 || first === 45) {
17806               third = charCodeAt$1(it, 2);
17807               if (third === 88 || third === 120) return NaN; // Number('+0x1') should be NaN, old V8 fix
17808             } else if (first === 48) {
17809               switch (charCodeAt$1(it, 1)) {
17810                 case 66: case 98: radix = 2; maxCode = 49; break; // fast equal of /^0b[01]+$/i
17811                 case 79: case 111: radix = 8; maxCode = 55; break; // fast equal of /^0o[0-7]+$/i
17812                 default: return +it;
17813               }
17814               digits = arraySlice$1(it, 2);
17815               length = digits.length;
17816               for (index = 0; index < length; index++) {
17817                 code = charCodeAt$1(digits, index);
17818                 // parseInt parses a string to a first unavailable symbol
17819                 // but ToNumber should return NaN if a string contains unavailable symbols
17820                 if (code < 48 || code > maxCode) return NaN;
17821               } return parseInt(digits, radix);
17822             }
17823           } return +it;
17824         };
17825
17826         // `Number` constructor
17827         // https://tc39.es/ecma262/#sec-number-constructor
17828         if (isForced(NUMBER, !NativeNumber(' 0o1') || !NativeNumber('0b1') || NativeNumber('+0x1'))) {
17829           var NumberWrapper = function Number(value) {
17830             var n = arguments.length < 1 ? 0 : NativeNumber(toNumeric(value));
17831             var dummy = this;
17832             // check on 1..constructor(foo) case
17833             return isPrototypeOf(NumberPrototype, dummy) && fails$8(function () { thisNumberValue$2(dummy); })
17834               ? inheritIfRequired(Object(n), dummy, NumberWrapper) : n;
17835           };
17836           for (var keys = DESCRIPTORS$3 ? getOwnPropertyNames(NativeNumber) : (
17837             // ES3:
17838             'MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,' +
17839             // ES2015 (in case, if modules with ES2015 Number statics required before):
17840             'EPSILON,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,isFinite,isInteger,isNaN,isSafeInteger,parseFloat,parseInt,' +
17841             // ESNext
17842             'fromString,range'
17843           ).split(','), j$1 = 0, key; keys.length > j$1; j$1++) {
17844             if (hasOwn$1(NativeNumber, key = keys[j$1]) && !hasOwn$1(NumberWrapper, key)) {
17845               defineProperty(NumberWrapper, key, getOwnPropertyDescriptor$2(NativeNumber, key));
17846             }
17847           }
17848           NumberWrapper.prototype = NumberPrototype;
17849           NumberPrototype.constructor = NumberWrapper;
17850           redefine$2(global$a, NUMBER, NumberWrapper);
17851         }
17852
17853         var diacritics = {};
17854
17855         var remove$6 = diacritics.remove = removeDiacritics;
17856         var replacementList = [{
17857           base: ' ',
17858           chars: "\xA0"
17859         }, {
17860           base: '0',
17861           chars: "\u07C0"
17862         }, {
17863           base: 'A',
17864           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"
17865         }, {
17866           base: 'AA',
17867           chars: "\uA732"
17868         }, {
17869           base: 'AE',
17870           chars: "\xC6\u01FC\u01E2"
17871         }, {
17872           base: 'AO',
17873           chars: "\uA734"
17874         }, {
17875           base: 'AU',
17876           chars: "\uA736"
17877         }, {
17878           base: 'AV',
17879           chars: "\uA738\uA73A"
17880         }, {
17881           base: 'AY',
17882           chars: "\uA73C"
17883         }, {
17884           base: 'B',
17885           chars: "\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0181"
17886         }, {
17887           base: 'C',
17888           chars: "\u24B8\uFF23\uA73E\u1E08\u0106C\u0108\u010A\u010C\xC7\u0187\u023B"
17889         }, {
17890           base: 'D',
17891           chars: "\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018A\u0189\u1D05\uA779"
17892         }, {
17893           base: 'Dh',
17894           chars: "\xD0"
17895         }, {
17896           base: 'DZ',
17897           chars: "\u01F1\u01C4"
17898         }, {
17899           base: 'Dz',
17900           chars: "\u01F2\u01C5"
17901         }, {
17902           base: 'E',
17903           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"
17904         }, {
17905           base: 'F',
17906           chars: "\uA77C\u24BB\uFF26\u1E1E\u0191\uA77B"
17907         }, {
17908           base: 'G',
17909           chars: "\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E\u0262"
17910         }, {
17911           base: 'H',
17912           chars: "\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D"
17913         }, {
17914           base: 'I',
17915           chars: "\u24BE\uFF29\xCC\xCD\xCE\u0128\u012A\u012C\u0130\xCF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197"
17916         }, {
17917           base: 'J',
17918           chars: "\u24BF\uFF2A\u0134\u0248\u0237"
17919         }, {
17920           base: 'K',
17921           chars: "\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2"
17922         }, {
17923           base: 'L',
17924           chars: "\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780"
17925         }, {
17926           base: 'LJ',
17927           chars: "\u01C7"
17928         }, {
17929           base: 'Lj',
17930           chars: "\u01C8"
17931         }, {
17932           base: 'M',
17933           chars: "\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C\u03FB"
17934         }, {
17935           base: 'N',
17936           chars: "\uA7A4\u0220\u24C3\uFF2E\u01F8\u0143\xD1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u019D\uA790\u1D0E"
17937         }, {
17938           base: 'NJ',
17939           chars: "\u01CA"
17940         }, {
17941           base: 'Nj',
17942           chars: "\u01CB"
17943         }, {
17944           base: 'O',
17945           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"
17946         }, {
17947           base: 'OE',
17948           chars: "\u0152"
17949         }, {
17950           base: 'OI',
17951           chars: "\u01A2"
17952         }, {
17953           base: 'OO',
17954           chars: "\uA74E"
17955         }, {
17956           base: 'OU',
17957           chars: "\u0222"
17958         }, {
17959           base: 'P',
17960           chars: "\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754"
17961         }, {
17962           base: 'Q',
17963           chars: "\u24C6\uFF31\uA756\uA758\u024A"
17964         }, {
17965           base: 'R',
17966           chars: "\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782"
17967         }, {
17968           base: 'S',
17969           chars: "\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784"
17970         }, {
17971           base: 'T',
17972           chars: "\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786"
17973         }, {
17974           base: 'Th',
17975           chars: "\xDE"
17976         }, {
17977           base: 'TZ',
17978           chars: "\uA728"
17979         }, {
17980           base: 'U',
17981           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"
17982         }, {
17983           base: 'V',
17984           chars: "\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245"
17985         }, {
17986           base: 'VY',
17987           chars: "\uA760"
17988         }, {
17989           base: 'W',
17990           chars: "\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72"
17991         }, {
17992           base: 'X',
17993           chars: "\u24CD\uFF38\u1E8A\u1E8C"
17994         }, {
17995           base: 'Y',
17996           chars: "\u24CE\uFF39\u1EF2\xDD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE"
17997         }, {
17998           base: 'Z',
17999           chars: "\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762"
18000         }, {
18001           base: 'a',
18002           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"
18003         }, {
18004           base: 'aa',
18005           chars: "\uA733"
18006         }, {
18007           base: 'ae',
18008           chars: "\xE6\u01FD\u01E3"
18009         }, {
18010           base: 'ao',
18011           chars: "\uA735"
18012         }, {
18013           base: 'au',
18014           chars: "\uA737"
18015         }, {
18016           base: 'av',
18017           chars: "\uA739\uA73B"
18018         }, {
18019           base: 'ay',
18020           chars: "\uA73D"
18021         }, {
18022           base: 'b',
18023           chars: "\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253\u0182"
18024         }, {
18025           base: 'c',
18026           chars: "\uFF43\u24D2\u0107\u0109\u010B\u010D\xE7\u1E09\u0188\u023C\uA73F\u2184"
18027         }, {
18028           base: 'd',
18029           chars: "\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\u018B\u13E7\u0501\uA7AA"
18030         }, {
18031           base: 'dh',
18032           chars: "\xF0"
18033         }, {
18034           base: 'dz',
18035           chars: "\u01F3\u01C6"
18036         }, {
18037           base: 'e',
18038           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"
18039         }, {
18040           base: 'f',
18041           chars: "\u24D5\uFF46\u1E1F\u0192"
18042         }, {
18043           base: 'ff',
18044           chars: "\uFB00"
18045         }, {
18046           base: 'fi',
18047           chars: "\uFB01"
18048         }, {
18049           base: 'fl',
18050           chars: "\uFB02"
18051         }, {
18052           base: 'ffi',
18053           chars: "\uFB03"
18054         }, {
18055           base: 'ffl',
18056           chars: "\uFB04"
18057         }, {
18058           base: 'g',
18059           chars: "\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\uA77F\u1D79"
18060         }, {
18061           base: 'h',
18062           chars: "\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265"
18063         }, {
18064           base: 'hv',
18065           chars: "\u0195"
18066         }, {
18067           base: 'i',
18068           chars: "\u24D8\uFF49\xEC\xED\xEE\u0129\u012B\u012D\xEF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131"
18069         }, {
18070           base: 'j',
18071           chars: "\u24D9\uFF4A\u0135\u01F0\u0249"
18072         }, {
18073           base: 'k',
18074           chars: "\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3"
18075         }, {
18076           base: 'l',
18077           chars: "\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747\u026D"
18078         }, {
18079           base: 'lj',
18080           chars: "\u01C9"
18081         }, {
18082           base: 'm',
18083           chars: "\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F"
18084         }, {
18085           base: 'n',
18086           chars: "\u24DD\uFF4E\u01F9\u0144\xF1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5\u043B\u0509"
18087         }, {
18088           base: 'nj',
18089           chars: "\u01CC"
18090         }, {
18091           base: 'o',
18092           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"
18093         }, {
18094           base: 'oe',
18095           chars: "\u0153"
18096         }, {
18097           base: 'oi',
18098           chars: "\u01A3"
18099         }, {
18100           base: 'oo',
18101           chars: "\uA74F"
18102         }, {
18103           base: 'ou',
18104           chars: "\u0223"
18105         }, {
18106           base: 'p',
18107           chars: "\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755\u03C1"
18108         }, {
18109           base: 'q',
18110           chars: "\u24E0\uFF51\u024B\uA757\uA759"
18111         }, {
18112           base: 'r',
18113           chars: "\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783"
18114         }, {
18115           base: 's',
18116           chars: "\u24E2\uFF53\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B\u0282"
18117         }, {
18118           base: 'ss',
18119           chars: "\xDF"
18120         }, {
18121           base: 't',
18122           chars: "\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787"
18123         }, {
18124           base: 'th',
18125           chars: "\xFE"
18126         }, {
18127           base: 'tz',
18128           chars: "\uA729"
18129         }, {
18130           base: 'u',
18131           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"
18132         }, {
18133           base: 'v',
18134           chars: "\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C"
18135         }, {
18136           base: 'vy',
18137           chars: "\uA761"
18138         }, {
18139           base: 'w',
18140           chars: "\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73"
18141         }, {
18142           base: 'x',
18143           chars: "\u24E7\uFF58\u1E8B\u1E8D"
18144         }, {
18145           base: 'y',
18146           chars: "\u24E8\uFF59\u1EF3\xFD\u0177\u1EF9\u0233\u1E8F\xFF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF"
18147         }, {
18148           base: 'z',
18149           chars: "\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763"
18150         }];
18151         var diacriticsMap = {};
18152
18153         for (var i$1 = 0; i$1 < replacementList.length; i$1 += 1) {
18154           var chars = replacementList[i$1].chars;
18155
18156           for (var j = 0; j < chars.length; j += 1) {
18157             diacriticsMap[chars[j]] = replacementList[i$1].base;
18158           }
18159         }
18160
18161         function removeDiacritics(str) {
18162           return str.replace(/[^\u0000-\u007e]/g, function (c) {
18163             return diacriticsMap[c] || c;
18164           });
18165         }
18166
18167         diacritics.replacementList = replacementList;
18168         diacritics.diacriticsMap = diacriticsMap;
18169
18170         var lib = {};
18171
18172         var isArabic$1 = {};
18173
18174         Object.defineProperty(isArabic$1, "__esModule", {
18175           value: true
18176         });
18177         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
18178         ];
18179
18180         function isArabic(_char) {
18181           if (_char.length > 1) {
18182             // allow the newer chars?
18183             throw new Error('isArabic works on only one-character strings');
18184           }
18185
18186           var code = _char.charCodeAt(0);
18187
18188           for (var i = 0; i < arabicBlocks.length; i++) {
18189             var block = arabicBlocks[i];
18190
18191             if (code >= block[0] && code <= block[1]) {
18192               return true;
18193             }
18194           }
18195
18196           return false;
18197         }
18198
18199         isArabic$1.isArabic = isArabic;
18200
18201         function isMath(_char2) {
18202           if (_char2.length > 2) {
18203             // allow the newer chars?
18204             throw new Error('isMath works on only one-character strings');
18205           }
18206
18207           var code = _char2.charCodeAt(0);
18208
18209           return code >= 0x660 && code <= 0x66C || code >= 0x6F0 && code <= 0x6F9;
18210         }
18211
18212         isArabic$1.isMath = isMath;
18213
18214         var GlyphSplitter$1 = {};
18215
18216         var reference = {};
18217
18218         var unicodeArabic = {};
18219
18220         Object.defineProperty(unicodeArabic, "__esModule", {
18221           value: true
18222         });
18223         var arabicReference = {
18224           "alef": {
18225             "normal": ["\u0627"],
18226             "madda_above": {
18227               "normal": ["\u0627\u0653", "\u0622"],
18228               "isolated": "\uFE81",
18229               "final": "\uFE82"
18230             },
18231             "hamza_above": {
18232               "normal": ["\u0627\u0654", "\u0623"],
18233               "isolated": "\uFE83",
18234               "final": "\uFE84"
18235             },
18236             "hamza_below": {
18237               "normal": ["\u0627\u0655", "\u0625"],
18238               "isolated": "\uFE87",
18239               "final": "\uFE88"
18240             },
18241             "wasla": {
18242               "normal": "\u0671",
18243               "isolated": "\uFB50",
18244               "final": "\uFB51"
18245             },
18246             "wavy_hamza_above": ["\u0672"],
18247             "wavy_hamza_below": ["\u0627\u065F", "\u0673"],
18248             "high_hamza": ["\u0675", "\u0627\u0674"],
18249             "indic_two_above": ["\u0773"],
18250             "indic_three_above": ["\u0774"],
18251             "fathatan": {
18252               "normal": ["\u0627\u064B"],
18253               "final": "\uFD3C",
18254               "isolated": "\uFD3D"
18255             },
18256             "isolated": "\uFE8D",
18257             "final": "\uFE8E"
18258           },
18259           "beh": {
18260             "normal": ["\u0628"],
18261             "dotless": ["\u066E"],
18262             "three_dots_horizontally_below": ["\u0750"],
18263             "dot_below_three_dots_above": ["\u0751"],
18264             "three_dots_pointing_upwards_below": ["\u0752"],
18265             "three_dots_pointing_upwards_below_two_dots_above": ["\u0753"],
18266             "two_dots_below_dot_above": ["\u0754"],
18267             "inverted_small_v_below": ["\u0755"],
18268             "small_v": ["\u0756"],
18269             "small_v_below": ["\u08A0"],
18270             "hamza_above": ["\u08A1"],
18271             "small_meem_above": ["\u08B6"],
18272             "isolated": "\uFE8F",
18273             "final": "\uFE90",
18274             "initial": "\uFE91",
18275             "medial": "\uFE92"
18276           },
18277           "teh marbuta": {
18278             "normal": ["\u0629"],
18279             "isolated": "\uFE93",
18280             "final": "\uFE94"
18281           },
18282           "teh": {
18283             "normal": ["\u062A"],
18284             "ring": ["\u067C"],
18285             "three_dots_above_downwards": ["\u067D"],
18286             "small_teh_above": ["\u08B8"],
18287             "isolated": "\uFE95",
18288             "final": "\uFE96",
18289             "initial": "\uFE97",
18290             "medial": "\uFE98"
18291           },
18292           "theh": {
18293             "normal": ["\u062B"],
18294             "isolated": "\uFE99",
18295             "final": "\uFE9A",
18296             "initial": "\uFE9B",
18297             "medial": "\uFE9C"
18298           },
18299           "jeem": {
18300             "normal": ["\u062C"],
18301             "two_dots_above": ["\u08A2"],
18302             "isolated": "\uFE9D",
18303             "final": "\uFE9E",
18304             "initial": "\uFE9F",
18305             "medial": "\uFEA0"
18306           },
18307           "hah": {
18308             "normal": ["\u062D"],
18309             "hamza_above": ["\u0681"],
18310             "two_dots_vertical_above": ["\u0682"],
18311             "three_dots_above": ["\u0685"],
18312             "two_dots_above": ["\u0757"],
18313             "three_dots_pointing_upwards_below": ["\u0758"],
18314             "small_tah_below": ["\u076E"],
18315             "small_tah_two_dots": ["\u076F"],
18316             "small_tah_above": ["\u0772"],
18317             "indic_four_below": ["\u077C"],
18318             "isolated": "\uFEA1",
18319             "final": "\uFEA2",
18320             "initial": "\uFEA3",
18321             "medial": "\uFEA4"
18322           },
18323           "khah": {
18324             "normal": ["\u062E"],
18325             "isolated": "\uFEA5",
18326             "final": "\uFEA6",
18327             "initial": "\uFEA7",
18328             "medial": "\uFEA8"
18329           },
18330           "dal": {
18331             "normal": ["\u062F"],
18332             "ring": ["\u0689"],
18333             "dot_below": ["\u068A"],
18334             "dot_below_small_tah": ["\u068B"],
18335             "three_dots_above_downwards": ["\u068F"],
18336             "four_dots_above": ["\u0690"],
18337             "inverted_v": ["\u06EE"],
18338             "two_dots_vertically_below_small_tah": ["\u0759"],
18339             "inverted_small_v_below": ["\u075A"],
18340             "three_dots_below": ["\u08AE"],
18341             "isolated": "\uFEA9",
18342             "final": "\uFEAA"
18343           },
18344           "thal": {
18345             "normal": ["\u0630"],
18346             "isolated": "\uFEAB",
18347             "final": "\uFEAC"
18348           },
18349           "reh": {
18350             "normal": ["\u0631"],
18351             "small_v": ["\u0692"],
18352             "ring": ["\u0693"],
18353             "dot_below": ["\u0694"],
18354             "small_v_below": ["\u0695"],
18355             "dot_below_dot_above": ["\u0696"],
18356             "two_dots_above": ["\u0697"],
18357             "four_dots_above": ["\u0699"],
18358             "inverted_v": ["\u06EF"],
18359             "stroke": ["\u075B"],
18360             "two_dots_vertically_above": ["\u076B"],
18361             "hamza_above": ["\u076C"],
18362             "small_tah_two_dots": ["\u0771"],
18363             "loop": ["\u08AA"],
18364             "small_noon_above": ["\u08B9"],
18365             "isolated": "\uFEAD",
18366             "final": "\uFEAE"
18367           },
18368           "zain": {
18369             "normal": ["\u0632"],
18370             "inverted_v_above": ["\u08B2"],
18371             "isolated": "\uFEAF",
18372             "final": "\uFEB0"
18373           },
18374           "seen": {
18375             "normal": ["\u0633"],
18376             "dot_below_dot_above": ["\u069A"],
18377             "three_dots_below": ["\u069B"],
18378             "three_dots_below_three_dots_above": ["\u069C"],
18379             "four_dots_above": ["\u075C"],
18380             "two_dots_vertically_above": ["\u076D"],
18381             "small_tah_two_dots": ["\u0770"],
18382             "indic_four_above": ["\u077D"],
18383             "inverted_v": ["\u077E"],
18384             "isolated": "\uFEB1",
18385             "final": "\uFEB2",
18386             "initial": "\uFEB3",
18387             "medial": "\uFEB4"
18388           },
18389           "sheen": {
18390             "normal": ["\u0634"],
18391             "dot_below": ["\u06FA"],
18392             "isolated": "\uFEB5",
18393             "final": "\uFEB6",
18394             "initial": "\uFEB7",
18395             "medial": "\uFEB8"
18396           },
18397           "sad": {
18398             "normal": ["\u0635"],
18399             "two_dots_below": ["\u069D"],
18400             "three_dots_above": ["\u069E"],
18401             "three_dots_below": ["\u08AF"],
18402             "isolated": "\uFEB9",
18403             "final": "\uFEBA",
18404             "initial": "\uFEBB",
18405             "medial": "\uFEBC"
18406           },
18407           "dad": {
18408             "normal": ["\u0636"],
18409             "dot_below": ["\u06FB"],
18410             "isolated": "\uFEBD",
18411             "final": "\uFEBE",
18412             "initial": "\uFEBF",
18413             "medial": "\uFEC0"
18414           },
18415           "tah": {
18416             "normal": ["\u0637"],
18417             "three_dots_above": ["\u069F"],
18418             "two_dots_above": ["\u08A3"],
18419             "isolated": "\uFEC1",
18420             "final": "\uFEC2",
18421             "initial": "\uFEC3",
18422             "medial": "\uFEC4"
18423           },
18424           "zah": {
18425             "normal": ["\u0638"],
18426             "isolated": "\uFEC5",
18427             "final": "\uFEC6",
18428             "initial": "\uFEC7",
18429             "medial": "\uFEC8"
18430           },
18431           "ain": {
18432             "normal": ["\u0639"],
18433             "three_dots_above": ["\u06A0"],
18434             "two_dots_above": ["\u075D"],
18435             "three_dots_pointing_downwards_above": ["\u075E"],
18436             "two_dots_vertically_above": ["\u075F"],
18437             "three_dots_below": ["\u08B3"],
18438             "isolated": "\uFEC9",
18439             "final": "\uFECA",
18440             "initial": "\uFECB",
18441             "medial": "\uFECC"
18442           },
18443           "ghain": {
18444             "normal": ["\u063A"],
18445             "dot_below": ["\u06FC"],
18446             "isolated": "\uFECD",
18447             "final": "\uFECE",
18448             "initial": "\uFECF",
18449             "medial": "\uFED0"
18450           },
18451           "feh": {
18452             "normal": ["\u0641"],
18453             "dotless": ["\u06A1"],
18454             "dot_moved_below": ["\u06A2"],
18455             "dot_below": ["\u06A3"],
18456             "three_dots_below": ["\u06A5"],
18457             "two_dots_below": ["\u0760"],
18458             "three_dots_pointing_upwards_below": ["\u0761"],
18459             "dot_below_three_dots_above": ["\u08A4"],
18460             "isolated": "\uFED1",
18461             "final": "\uFED2",
18462             "initial": "\uFED3",
18463             "medial": "\uFED4"
18464           },
18465           "qaf": {
18466             "normal": ["\u0642"],
18467             "dotless": ["\u066F"],
18468             "dot_above": ["\u06A7"],
18469             "three_dots_above": ["\u06A8"],
18470             "dot_below": ["\u08A5"],
18471             "isolated": "\uFED5",
18472             "final": "\uFED6",
18473             "initial": "\uFED7",
18474             "medial": "\uFED8"
18475           },
18476           "kaf": {
18477             "normal": ["\u0643"],
18478             "swash": ["\u06AA"],
18479             "ring": ["\u06AB"],
18480             "dot_above": ["\u06AC"],
18481             "three_dots_below": ["\u06AE"],
18482             "two_dots_above": ["\u077F"],
18483             "dot_below": ["\u08B4"],
18484             "isolated": "\uFED9",
18485             "final": "\uFEDA",
18486             "initial": "\uFEDB",
18487             "medial": "\uFEDC"
18488           },
18489           "lam": {
18490             "normal": ["\u0644"],
18491             "small_v": ["\u06B5"],
18492             "dot_above": ["\u06B6"],
18493             "three_dots_above": ["\u06B7"],
18494             "three_dots_below": ["\u06B8"],
18495             "bar": ["\u076A"],
18496             "double_bar": ["\u08A6"],
18497             "isolated": "\uFEDD",
18498             "final": "\uFEDE",
18499             "initial": "\uFEDF",
18500             "medial": "\uFEE0"
18501           },
18502           "meem": {
18503             "normal": ["\u0645"],
18504             "dot_above": ["\u0765"],
18505             "dot_below": ["\u0766"],
18506             "three_dots_above": ["\u08A7"],
18507             "isolated": "\uFEE1",
18508             "final": "\uFEE2",
18509             "initial": "\uFEE3",
18510             "medial": "\uFEE4"
18511           },
18512           "noon": {
18513             "normal": ["\u0646"],
18514             "dot_below": ["\u06B9"],
18515             "ring": ["\u06BC"],
18516             "three_dots_above": ["\u06BD"],
18517             "two_dots_below": ["\u0767"],
18518             "small_tah": ["\u0768"],
18519             "small_v": ["\u0769"],
18520             "isolated": "\uFEE5",
18521             "final": "\uFEE6",
18522             "initial": "\uFEE7",
18523             "medial": "\uFEE8"
18524           },
18525           "heh": {
18526             "normal": ["\u0647"],
18527             "isolated": "\uFEE9",
18528             "final": "\uFEEA",
18529             "initial": "\uFEEB",
18530             "medial": "\uFEEC"
18531           },
18532           "waw": {
18533             "normal": ["\u0648"],
18534             "hamza_above": {
18535               "normal": ["\u0624", "\u0648\u0654"],
18536               "isolated": "\uFE85",
18537               "final": "\uFE86"
18538             },
18539             "high_hamza": ["\u0676", "\u0648\u0674"],
18540             "ring": ["\u06C4"],
18541             "two_dots_above": ["\u06CA"],
18542             "dot_above": ["\u06CF"],
18543             "indic_two_above": ["\u0778"],
18544             "indic_three_above": ["\u0779"],
18545             "dot_within": ["\u08AB"],
18546             "isolated": "\uFEED",
18547             "final": "\uFEEE"
18548           },
18549           "alef_maksura": {
18550             "normal": ["\u0649"],
18551             "hamza_above": ["\u0626", "\u064A\u0654"],
18552             "initial": "\uFBE8",
18553             "medial": "\uFBE9",
18554             "isolated": "\uFEEF",
18555             "final": "\uFEF0"
18556           },
18557           "yeh": {
18558             "normal": ["\u064A"],
18559             "hamza_above": {
18560               "normal": ["\u0626", "\u0649\u0654"],
18561               "isolated": "\uFE89",
18562               "final": "\uFE8A",
18563               "initial": "\uFE8B",
18564               "medial": "\uFE8C"
18565             },
18566             "two_dots_below_hamza_above": ["\u08A8"],
18567             "high_hamza": ["\u0678", "\u064A\u0674"],
18568             "tail": ["\u06CD"],
18569             "small_v": ["\u06CE"],
18570             "three_dots_below": ["\u06D1"],
18571             "two_dots_below_dot_above": ["\u08A9"],
18572             "two_dots_below_small_noon_above": ["\u08BA"],
18573             "isolated": "\uFEF1",
18574             "final": "\uFEF2",
18575             "initial": "\uFEF3",
18576             "medial": "\uFEF4"
18577           },
18578           "tteh": {
18579             "normal": ["\u0679"],
18580             "isolated": "\uFB66",
18581             "final": "\uFB67",
18582             "initial": "\uFB68",
18583             "medial": "\uFB69"
18584           },
18585           "tteheh": {
18586             "normal": ["\u067A"],
18587             "isolated": "\uFB5E",
18588             "final": "\uFB5F",
18589             "initial": "\uFB60",
18590             "medial": "\uFB61"
18591           },
18592           "beeh": {
18593             "normal": ["\u067B"],
18594             "isolated": "\uFB52",
18595             "final": "\uFB53",
18596             "initial": "\uFB54",
18597             "medial": "\uFB55"
18598           },
18599           "peh": {
18600             "normal": ["\u067E"],
18601             "small_meem_above": ["\u08B7"],
18602             "isolated": "\uFB56",
18603             "final": "\uFB57",
18604             "initial": "\uFB58",
18605             "medial": "\uFB59"
18606           },
18607           "teheh": {
18608             "normal": ["\u067F"],
18609             "isolated": "\uFB62",
18610             "final": "\uFB63",
18611             "initial": "\uFB64",
18612             "medial": "\uFB65"
18613           },
18614           "beheh": {
18615             "normal": ["\u0680"],
18616             "isolated": "\uFB5A",
18617             "final": "\uFB5B",
18618             "initial": "\uFB5C",
18619             "medial": "\uFB5D"
18620           },
18621           "nyeh": {
18622             "normal": ["\u0683"],
18623             "isolated": "\uFB76",
18624             "final": "\uFB77",
18625             "initial": "\uFB78",
18626             "medial": "\uFB79"
18627           },
18628           "dyeh": {
18629             "normal": ["\u0684"],
18630             "isolated": "\uFB72",
18631             "final": "\uFB73",
18632             "initial": "\uFB74",
18633             "medial": "\uFB75"
18634           },
18635           "tcheh": {
18636             "normal": ["\u0686"],
18637             "dot_above": ["\u06BF"],
18638             "isolated": "\uFB7A",
18639             "final": "\uFB7B",
18640             "initial": "\uFB7C",
18641             "medial": "\uFB7D"
18642           },
18643           "tcheheh": {
18644             "normal": ["\u0687"],
18645             "isolated": "\uFB7E",
18646             "final": "\uFB7F",
18647             "initial": "\uFB80",
18648             "medial": "\uFB81"
18649           },
18650           "ddal": {
18651             "normal": ["\u0688"],
18652             "isolated": "\uFB88",
18653             "final": "\uFB89"
18654           },
18655           "dahal": {
18656             "normal": ["\u068C"],
18657             "isolated": "\uFB84",
18658             "final": "\uFB85"
18659           },
18660           "ddahal": {
18661             "normal": ["\u068D"],
18662             "isolated": "\uFB82",
18663             "final": "\uFB83"
18664           },
18665           "dul": {
18666             "normal": ["\u068F", "\u068E"],
18667             "isolated": "\uFB86",
18668             "final": "\uFB87"
18669           },
18670           "rreh": {
18671             "normal": ["\u0691"],
18672             "isolated": "\uFB8C",
18673             "final": "\uFB8D"
18674           },
18675           "jeh": {
18676             "normal": ["\u0698"],
18677             "isolated": "\uFB8A",
18678             "final": "\uFB8B"
18679           },
18680           "veh": {
18681             "normal": ["\u06A4"],
18682             "isolated": "\uFB6A",
18683             "final": "\uFB6B",
18684             "initial": "\uFB6C",
18685             "medial": "\uFB6D"
18686           },
18687           "peheh": {
18688             "normal": ["\u06A6"],
18689             "isolated": "\uFB6E",
18690             "final": "\uFB6F",
18691             "initial": "\uFB70",
18692             "medial": "\uFB71"
18693           },
18694           "keheh": {
18695             "normal": ["\u06A9"],
18696             "dot_above": ["\u0762"],
18697             "three_dots_above": ["\u0763"],
18698             "three_dots_pointing_upwards_below": ["\u0764"],
18699             "isolated": "\uFB8E",
18700             "final": "\uFB8F",
18701             "initial": "\uFB90",
18702             "medial": "\uFB91"
18703           },
18704           "ng": {
18705             "normal": ["\u06AD"],
18706             "isolated": "\uFBD3",
18707             "final": "\uFBD4",
18708             "initial": "\uFBD5",
18709             "medial": "\uFBD6"
18710           },
18711           "gaf": {
18712             "normal": ["\u06AF"],
18713             "ring": ["\u06B0"],
18714             "two_dots_below": ["\u06B2"],
18715             "three_dots_above": ["\u06B4"],
18716             "inverted_stroke": ["\u08B0"],
18717             "isolated": "\uFB92",
18718             "final": "\uFB93",
18719             "initial": "\uFB94",
18720             "medial": "\uFB95"
18721           },
18722           "ngoeh": {
18723             "normal": ["\u06B1"],
18724             "isolated": "\uFB9A",
18725             "final": "\uFB9B",
18726             "initial": "\uFB9C",
18727             "medial": "\uFB9D"
18728           },
18729           "gueh": {
18730             "normal": ["\u06B3"],
18731             "isolated": "\uFB96",
18732             "final": "\uFB97",
18733             "initial": "\uFB98",
18734             "medial": "\uFB99"
18735           },
18736           "noon ghunna": {
18737             "normal": ["\u06BA"],
18738             "isolated": "\uFB9E",
18739             "final": "\uFB9F"
18740           },
18741           "rnoon": {
18742             "normal": ["\u06BB"],
18743             "isolated": "\uFBA0",
18744             "final": "\uFBA1",
18745             "initial": "\uFBA2",
18746             "medial": "\uFBA3"
18747           },
18748           "heh doachashmee": {
18749             "normal": ["\u06BE"],
18750             "isolated": "\uFBAA",
18751             "final": "\uFBAB",
18752             "initial": "\uFBAC",
18753             "medial": "\uFBAD"
18754           },
18755           "heh goal": {
18756             "normal": ["\u06C1"],
18757             "hamza_above": ["\u06C1\u0654", "\u06C2"],
18758             "isolated": "\uFBA6",
18759             "final": "\uFBA7",
18760             "initial": "\uFBA8",
18761             "medial": "\uFBA9"
18762           },
18763           "teh marbuta goal": {
18764             "normal": ["\u06C3"]
18765           },
18766           "kirghiz oe": {
18767             "normal": ["\u06C5"],
18768             "isolated": "\uFBE0",
18769             "final": "\uFBE1"
18770           },
18771           "oe": {
18772             "normal": ["\u06C6"],
18773             "isolated": "\uFBD9",
18774             "final": "\uFBDA"
18775           },
18776           "u": {
18777             "normal": ["\u06C7"],
18778             "hamza_above": {
18779               "normal": ["\u0677", "\u06C7\u0674"],
18780               "isolated": "\uFBDD"
18781             },
18782             "isolated": "\uFBD7",
18783             "final": "\uFBD8"
18784           },
18785           "yu": {
18786             "normal": ["\u06C8"],
18787             "isolated": "\uFBDB",
18788             "final": "\uFBDC"
18789           },
18790           "kirghiz yu": {
18791             "normal": ["\u06C9"],
18792             "isolated": "\uFBE2",
18793             "final": "\uFBE3"
18794           },
18795           "ve": {
18796             "normal": ["\u06CB"],
18797             "isolated": "\uFBDE",
18798             "final": "\uFBDF"
18799           },
18800           "farsi yeh": {
18801             "normal": ["\u06CC"],
18802             "indic_two_above": ["\u0775"],
18803             "indic_three_above": ["\u0776"],
18804             "indic_four_above": ["\u0777"],
18805             "isolated": "\uFBFC",
18806             "final": "\uFBFD",
18807             "initial": "\uFBFE",
18808             "medial": "\uFBFF"
18809           },
18810           "e": {
18811             "normal": ["\u06D0"],
18812             "isolated": "\uFBE4",
18813             "final": "\uFBE5",
18814             "initial": "\uFBE6",
18815             "medial": "\uFBE7"
18816           },
18817           "yeh barree": {
18818             "normal": ["\u06D2"],
18819             "hamza_above": {
18820               "normal": ["\u06D2\u0654", "\u06D3"],
18821               "isolated": "\uFBB0",
18822               "final": "\uFBB1"
18823             },
18824             "indic_two_above": ["\u077A"],
18825             "indic_three_above": ["\u077B"],
18826             "isolated": "\uFBAE",
18827             "final": "\uFBAF"
18828           },
18829           "ae": {
18830             "normal": ["\u06D5"],
18831             "isolated": "\u06D5",
18832             "final": "\uFEEA",
18833             "yeh_above": {
18834               "normal": ["\u06C0", "\u06D5\u0654"],
18835               "isolated": "\uFBA4",
18836               "final": "\uFBA5"
18837             }
18838           },
18839           "rohingya yeh": {
18840             "normal": ["\u08AC"]
18841           },
18842           "low alef": {
18843             "normal": ["\u08AD"]
18844           },
18845           "straight waw": {
18846             "normal": ["\u08B1"]
18847           },
18848           "african feh": {
18849             "normal": ["\u08BB"]
18850           },
18851           "african qaf": {
18852             "normal": ["\u08BC"]
18853           },
18854           "african noon": {
18855             "normal": ["\u08BD"]
18856           }
18857         };
18858
18859         unicodeArabic["default"] = arabicReference;
18860
18861         var unicodeLigatures = {};
18862
18863         Object.defineProperty(unicodeLigatures, "__esModule", {
18864           value: true
18865         });
18866         var ligatureReference = {
18867           "\u0626\u0627": {
18868             "isolated": "\uFBEA",
18869             "final": "\uFBEB"
18870           },
18871           "\u0626\u06D5": {
18872             "isolated": "\uFBEC",
18873             "final": "\uFBED"
18874           },
18875           "\u0626\u0648": {
18876             "isolated": "\uFBEE",
18877             "final": "\uFBEF"
18878           },
18879           "\u0626\u06C7": {
18880             "isolated": "\uFBF0",
18881             "final": "\uFBF1"
18882           },
18883           "\u0626\u06C6": {
18884             "isolated": "\uFBF2",
18885             "final": "\uFBF3"
18886           },
18887           "\u0626\u06C8": {
18888             "isolated": "\uFBF4",
18889             "final": "\uFBF5"
18890           },
18891           "\u0626\u06D0": {
18892             "isolated": "\uFBF6",
18893             "final": "\uFBF7",
18894             "initial": "\uFBF8"
18895           },
18896           "\u0626\u0649": {
18897             "uighur_kirghiz": {
18898               "isolated": "\uFBF9",
18899               "final": "\uFBFA",
18900               "initial": "\uFBFB"
18901             },
18902             "isolated": "\uFC03",
18903             "final": "\uFC68"
18904           },
18905           "\u0626\u062C": {
18906             "isolated": "\uFC00",
18907             "initial": "\uFC97"
18908           },
18909           "\u0626\u062D": {
18910             "isolated": "\uFC01",
18911             "initial": "\uFC98"
18912           },
18913           "\u0626\u0645": {
18914             "isolated": "\uFC02",
18915             "final": "\uFC66",
18916             "initial": "\uFC9A",
18917             "medial": "\uFCDF"
18918           },
18919           "\u0626\u064A": {
18920             "isolated": "\uFC04",
18921             "final": "\uFC69"
18922           },
18923           "\u0628\u062C": {
18924             "isolated": "\uFC05",
18925             "initial": "\uFC9C"
18926           },
18927           "\u0628\u062D": {
18928             "isolated": "\uFC06",
18929             "initial": "\uFC9D"
18930           },
18931           "\u0628\u062E": {
18932             "isolated": "\uFC07",
18933             "initial": "\uFC9E"
18934           },
18935           "\u0628\u0645": {
18936             "isolated": "\uFC08",
18937             "final": "\uFC6C",
18938             "initial": "\uFC9F",
18939             "medial": "\uFCE1"
18940           },
18941           "\u0628\u0649": {
18942             "isolated": "\uFC09",
18943             "final": "\uFC6E"
18944           },
18945           "\u0628\u064A": {
18946             "isolated": "\uFC0A",
18947             "final": "\uFC6F"
18948           },
18949           "\u062A\u062C": {
18950             "isolated": "\uFC0B",
18951             "initial": "\uFCA1"
18952           },
18953           "\u062A\u062D": {
18954             "isolated": "\uFC0C",
18955             "initial": "\uFCA2"
18956           },
18957           "\u062A\u062E": {
18958             "isolated": "\uFC0D",
18959             "initial": "\uFCA3"
18960           },
18961           "\u062A\u0645": {
18962             "isolated": "\uFC0E",
18963             "final": "\uFC72",
18964             "initial": "\uFCA4",
18965             "medial": "\uFCE3"
18966           },
18967           "\u062A\u0649": {
18968             "isolated": "\uFC0F",
18969             "final": "\uFC74"
18970           },
18971           "\u062A\u064A": {
18972             "isolated": "\uFC10",
18973             "final": "\uFC75"
18974           },
18975           "\u062B\u062C": {
18976             "isolated": "\uFC11"
18977           },
18978           "\u062B\u0645": {
18979             "isolated": "\uFC12",
18980             "final": "\uFC78",
18981             "initial": "\uFCA6",
18982             "medial": "\uFCE5"
18983           },
18984           "\u062B\u0649": {
18985             "isolated": "\uFC13",
18986             "final": "\uFC7A"
18987           },
18988           "\u062B\u0648": {
18989             "isolated": "\uFC14"
18990           },
18991           "\u062C\u062D": {
18992             "isolated": "\uFC15",
18993             "initial": "\uFCA7"
18994           },
18995           "\u062C\u0645": {
18996             "isolated": "\uFC16",
18997             "initial": "\uFCA8"
18998           },
18999           "\u062D\u062C": {
19000             "isolated": "\uFC17",
19001             "initial": "\uFCA9"
19002           },
19003           "\u062D\u0645": {
19004             "isolated": "\uFC18",
19005             "initial": "\uFCAA"
19006           },
19007           "\u062E\u062C": {
19008             "isolated": "\uFC19",
19009             "initial": "\uFCAB"
19010           },
19011           "\u062E\u062D": {
19012             "isolated": "\uFC1A"
19013           },
19014           "\u062E\u0645": {
19015             "isolated": "\uFC1B",
19016             "initial": "\uFCAC"
19017           },
19018           "\u0633\u062C": {
19019             "isolated": "\uFC1C",
19020             "initial": "\uFCAD",
19021             "medial": "\uFD34"
19022           },
19023           "\u0633\u062D": {
19024             "isolated": "\uFC1D",
19025             "initial": "\uFCAE",
19026             "medial": "\uFD35"
19027           },
19028           "\u0633\u062E": {
19029             "isolated": "\uFC1E",
19030             "initial": "\uFCAF",
19031             "medial": "\uFD36"
19032           },
19033           "\u0633\u0645": {
19034             "isolated": "\uFC1F",
19035             "initial": "\uFCB0",
19036             "medial": "\uFCE7"
19037           },
19038           "\u0635\u062D": {
19039             "isolated": "\uFC20",
19040             "initial": "\uFCB1"
19041           },
19042           "\u0635\u0645": {
19043             "isolated": "\uFC21",
19044             "initial": "\uFCB3"
19045           },
19046           "\u0636\u062C": {
19047             "isolated": "\uFC22",
19048             "initial": "\uFCB4"
19049           },
19050           "\u0636\u062D": {
19051             "isolated": "\uFC23",
19052             "initial": "\uFCB5"
19053           },
19054           "\u0636\u062E": {
19055             "isolated": "\uFC24",
19056             "initial": "\uFCB6"
19057           },
19058           "\u0636\u0645": {
19059             "isolated": "\uFC25",
19060             "initial": "\uFCB7"
19061           },
19062           "\u0637\u062D": {
19063             "isolated": "\uFC26",
19064             "initial": "\uFCB8"
19065           },
19066           "\u0637\u0645": {
19067             "isolated": "\uFC27",
19068             "initial": "\uFD33",
19069             "medial": "\uFD3A"
19070           },
19071           "\u0638\u0645": {
19072             "isolated": "\uFC28",
19073             "initial": "\uFCB9",
19074             "medial": "\uFD3B"
19075           },
19076           "\u0639\u062C": {
19077             "isolated": "\uFC29",
19078             "initial": "\uFCBA"
19079           },
19080           "\u0639\u0645": {
19081             "isolated": "\uFC2A",
19082             "initial": "\uFCBB"
19083           },
19084           "\u063A\u062C": {
19085             "isolated": "\uFC2B",
19086             "initial": "\uFCBC"
19087           },
19088           "\u063A\u0645": {
19089             "isolated": "\uFC2C",
19090             "initial": "\uFCBD"
19091           },
19092           "\u0641\u062C": {
19093             "isolated": "\uFC2D",
19094             "initial": "\uFCBE"
19095           },
19096           "\u0641\u062D": {
19097             "isolated": "\uFC2E",
19098             "initial": "\uFCBF"
19099           },
19100           "\u0641\u062E": {
19101             "isolated": "\uFC2F",
19102             "initial": "\uFCC0"
19103           },
19104           "\u0641\u0645": {
19105             "isolated": "\uFC30",
19106             "initial": "\uFCC1"
19107           },
19108           "\u0641\u0649": {
19109             "isolated": "\uFC31",
19110             "final": "\uFC7C"
19111           },
19112           "\u0641\u064A": {
19113             "isolated": "\uFC32",
19114             "final": "\uFC7D"
19115           },
19116           "\u0642\u062D": {
19117             "isolated": "\uFC33",
19118             "initial": "\uFCC2"
19119           },
19120           "\u0642\u0645": {
19121             "isolated": "\uFC34",
19122             "initial": "\uFCC3"
19123           },
19124           "\u0642\u0649": {
19125             "isolated": "\uFC35",
19126             "final": "\uFC7E"
19127           },
19128           "\u0642\u064A": {
19129             "isolated": "\uFC36",
19130             "final": "\uFC7F"
19131           },
19132           "\u0643\u0627": {
19133             "isolated": "\uFC37",
19134             "final": "\uFC80"
19135           },
19136           "\u0643\u062C": {
19137             "isolated": "\uFC38",
19138             "initial": "\uFCC4"
19139           },
19140           "\u0643\u062D": {
19141             "isolated": "\uFC39",
19142             "initial": "\uFCC5"
19143           },
19144           "\u0643\u062E": {
19145             "isolated": "\uFC3A",
19146             "initial": "\uFCC6"
19147           },
19148           "\u0643\u0644": {
19149             "isolated": "\uFC3B",
19150             "final": "\uFC81",
19151             "initial": "\uFCC7",
19152             "medial": "\uFCEB"
19153           },
19154           "\u0643\u0645": {
19155             "isolated": "\uFC3C",
19156             "final": "\uFC82",
19157             "initial": "\uFCC8",
19158             "medial": "\uFCEC"
19159           },
19160           "\u0643\u0649": {
19161             "isolated": "\uFC3D",
19162             "final": "\uFC83"
19163           },
19164           "\u0643\u064A": {
19165             "isolated": "\uFC3E",
19166             "final": "\uFC84"
19167           },
19168           "\u0644\u062C": {
19169             "isolated": "\uFC3F",
19170             "initial": "\uFCC9"
19171           },
19172           "\u0644\u062D": {
19173             "isolated": "\uFC40",
19174             "initial": "\uFCCA"
19175           },
19176           "\u0644\u062E": {
19177             "isolated": "\uFC41",
19178             "initial": "\uFCCB"
19179           },
19180           "\u0644\u0645": {
19181             "isolated": "\uFC42",
19182             "final": "\uFC85",
19183             "initial": "\uFCCC",
19184             "medial": "\uFCED"
19185           },
19186           "\u0644\u0649": {
19187             "isolated": "\uFC43",
19188             "final": "\uFC86"
19189           },
19190           "\u0644\u064A": {
19191             "isolated": "\uFC44",
19192             "final": "\uFC87"
19193           },
19194           "\u0645\u062C": {
19195             "isolated": "\uFC45",
19196             "initial": "\uFCCE"
19197           },
19198           "\u0645\u062D": {
19199             "isolated": "\uFC46",
19200             "initial": "\uFCCF"
19201           },
19202           "\u0645\u062E": {
19203             "isolated": "\uFC47",
19204             "initial": "\uFCD0"
19205           },
19206           "\u0645\u0645": {
19207             "isolated": "\uFC48",
19208             "final": "\uFC89",
19209             "initial": "\uFCD1"
19210           },
19211           "\u0645\u0649": {
19212             "isolated": "\uFC49"
19213           },
19214           "\u0645\u064A": {
19215             "isolated": "\uFC4A"
19216           },
19217           "\u0646\u062C": {
19218             "isolated": "\uFC4B",
19219             "initial": "\uFCD2"
19220           },
19221           "\u0646\u062D": {
19222             "isolated": "\uFC4C",
19223             "initial": "\uFCD3"
19224           },
19225           "\u0646\u062E": {
19226             "isolated": "\uFC4D",
19227             "initial": "\uFCD4"
19228           },
19229           "\u0646\u0645": {
19230             "isolated": "\uFC4E",
19231             "final": "\uFC8C",
19232             "initial": "\uFCD5",
19233             "medial": "\uFCEE"
19234           },
19235           "\u0646\u0649": {
19236             "isolated": "\uFC4F",
19237             "final": "\uFC8E"
19238           },
19239           "\u0646\u064A": {
19240             "isolated": "\uFC50",
19241             "final": "\uFC8F"
19242           },
19243           "\u0647\u062C": {
19244             "isolated": "\uFC51",
19245             "initial": "\uFCD7"
19246           },
19247           "\u0647\u0645": {
19248             "isolated": "\uFC52",
19249             "initial": "\uFCD8"
19250           },
19251           "\u0647\u0649": {
19252             "isolated": "\uFC53"
19253           },
19254           "\u0647\u064A": {
19255             "isolated": "\uFC54"
19256           },
19257           "\u064A\u062C": {
19258             "isolated": "\uFC55",
19259             "initial": "\uFCDA"
19260           },
19261           "\u064A\u062D": {
19262             "isolated": "\uFC56",
19263             "initial": "\uFCDB"
19264           },
19265           "\u064A\u062E": {
19266             "isolated": "\uFC57",
19267             "initial": "\uFCDC"
19268           },
19269           "\u064A\u0645": {
19270             "isolated": "\uFC58",
19271             "final": "\uFC93",
19272             "initial": "\uFCDD",
19273             "medial": "\uFCF0"
19274           },
19275           "\u064A\u0649": {
19276             "isolated": "\uFC59",
19277             "final": "\uFC95"
19278           },
19279           "\u064A\u064A": {
19280             "isolated": "\uFC5A",
19281             "final": "\uFC96"
19282           },
19283           "\u0630\u0670": {
19284             "isolated": "\uFC5B"
19285           },
19286           "\u0631\u0670": {
19287             "isolated": "\uFC5C"
19288           },
19289           "\u0649\u0670": {
19290             "isolated": "\uFC5D",
19291             "final": "\uFC90"
19292           },
19293           "\u064C\u0651": {
19294             "isolated": "\uFC5E"
19295           },
19296           "\u064D\u0651": {
19297             "isolated": "\uFC5F"
19298           },
19299           "\u064E\u0651": {
19300             "isolated": "\uFC60"
19301           },
19302           "\u064F\u0651": {
19303             "isolated": "\uFC61"
19304           },
19305           "\u0650\u0651": {
19306             "isolated": "\uFC62"
19307           },
19308           "\u0651\u0670": {
19309             "isolated": "\uFC63"
19310           },
19311           "\u0626\u0631": {
19312             "final": "\uFC64"
19313           },
19314           "\u0626\u0632": {
19315             "final": "\uFC65"
19316           },
19317           "\u0626\u0646": {
19318             "final": "\uFC67"
19319           },
19320           "\u0628\u0631": {
19321             "final": "\uFC6A"
19322           },
19323           "\u0628\u0632": {
19324             "final": "\uFC6B"
19325           },
19326           "\u0628\u0646": {
19327             "final": "\uFC6D"
19328           },
19329           "\u062A\u0631": {
19330             "final": "\uFC70"
19331           },
19332           "\u062A\u0632": {
19333             "final": "\uFC71"
19334           },
19335           "\u062A\u0646": {
19336             "final": "\uFC73"
19337           },
19338           "\u062B\u0631": {
19339             "final": "\uFC76"
19340           },
19341           "\u062B\u0632": {
19342             "final": "\uFC77"
19343           },
19344           "\u062B\u0646": {
19345             "final": "\uFC79"
19346           },
19347           "\u062B\u064A": {
19348             "final": "\uFC7B"
19349           },
19350           "\u0645\u0627": {
19351             "final": "\uFC88"
19352           },
19353           "\u0646\u0631": {
19354             "final": "\uFC8A"
19355           },
19356           "\u0646\u0632": {
19357             "final": "\uFC8B"
19358           },
19359           "\u0646\u0646": {
19360             "final": "\uFC8D"
19361           },
19362           "\u064A\u0631": {
19363             "final": "\uFC91"
19364           },
19365           "\u064A\u0632": {
19366             "final": "\uFC92"
19367           },
19368           "\u064A\u0646": {
19369             "final": "\uFC94"
19370           },
19371           "\u0626\u062E": {
19372             "initial": "\uFC99"
19373           },
19374           "\u0626\u0647": {
19375             "initial": "\uFC9B",
19376             "medial": "\uFCE0"
19377           },
19378           "\u0628\u0647": {
19379             "initial": "\uFCA0",
19380             "medial": "\uFCE2"
19381           },
19382           "\u062A\u0647": {
19383             "initial": "\uFCA5",
19384             "medial": "\uFCE4"
19385           },
19386           "\u0635\u062E": {
19387             "initial": "\uFCB2"
19388           },
19389           "\u0644\u0647": {
19390             "initial": "\uFCCD"
19391           },
19392           "\u0646\u0647": {
19393             "initial": "\uFCD6",
19394             "medial": "\uFCEF"
19395           },
19396           "\u0647\u0670": {
19397             "initial": "\uFCD9"
19398           },
19399           "\u064A\u0647": {
19400             "initial": "\uFCDE",
19401             "medial": "\uFCF1"
19402           },
19403           "\u062B\u0647": {
19404             "medial": "\uFCE6"
19405           },
19406           "\u0633\u0647": {
19407             "medial": "\uFCE8",
19408             "initial": "\uFD31"
19409           },
19410           "\u0634\u0645": {
19411             "medial": "\uFCE9",
19412             "isolated": "\uFD0C",
19413             "final": "\uFD28",
19414             "initial": "\uFD30"
19415           },
19416           "\u0634\u0647": {
19417             "medial": "\uFCEA",
19418             "initial": "\uFD32"
19419           },
19420           "\u0640\u064E\u0651": {
19421             "medial": "\uFCF2"
19422           },
19423           "\u0640\u064F\u0651": {
19424             "medial": "\uFCF3"
19425           },
19426           "\u0640\u0650\u0651": {
19427             "medial": "\uFCF4"
19428           },
19429           "\u0637\u0649": {
19430             "isolated": "\uFCF5",
19431             "final": "\uFD11"
19432           },
19433           "\u0637\u064A": {
19434             "isolated": "\uFCF6",
19435             "final": "\uFD12"
19436           },
19437           "\u0639\u0649": {
19438             "isolated": "\uFCF7",
19439             "final": "\uFD13"
19440           },
19441           "\u0639\u064A": {
19442             "isolated": "\uFCF8",
19443             "final": "\uFD14"
19444           },
19445           "\u063A\u0649": {
19446             "isolated": "\uFCF9",
19447             "final": "\uFD15"
19448           },
19449           "\u063A\u064A": {
19450             "isolated": "\uFCFA",
19451             "final": "\uFD16"
19452           },
19453           "\u0633\u0649": {
19454             "isolated": "\uFCFB"
19455           },
19456           "\u0633\u064A": {
19457             "isolated": "\uFCFC",
19458             "final": "\uFD18"
19459           },
19460           "\u0634\u0649": {
19461             "isolated": "\uFCFD",
19462             "final": "\uFD19"
19463           },
19464           "\u0634\u064A": {
19465             "isolated": "\uFCFE",
19466             "final": "\uFD1A"
19467           },
19468           "\u062D\u0649": {
19469             "isolated": "\uFCFF",
19470             "final": "\uFD1B"
19471           },
19472           "\u062D\u064A": {
19473             "isolated": "\uFD00",
19474             "final": "\uFD1C"
19475           },
19476           "\u062C\u0649": {
19477             "isolated": "\uFD01",
19478             "final": "\uFD1D"
19479           },
19480           "\u062C\u064A": {
19481             "isolated": "\uFD02",
19482             "final": "\uFD1E"
19483           },
19484           "\u062E\u0649": {
19485             "isolated": "\uFD03",
19486             "final": "\uFD1F"
19487           },
19488           "\u062E\u064A": {
19489             "isolated": "\uFD04",
19490             "final": "\uFD20"
19491           },
19492           "\u0635\u0649": {
19493             "isolated": "\uFD05",
19494             "final": "\uFD21"
19495           },
19496           "\u0635\u064A": {
19497             "isolated": "\uFD06",
19498             "final": "\uFD22"
19499           },
19500           "\u0636\u0649": {
19501             "isolated": "\uFD07",
19502             "final": "\uFD23"
19503           },
19504           "\u0636\u064A": {
19505             "isolated": "\uFD08",
19506             "final": "\uFD24"
19507           },
19508           "\u0634\u062C": {
19509             "isolated": "\uFD09",
19510             "final": "\uFD25",
19511             "initial": "\uFD2D",
19512             "medial": "\uFD37"
19513           },
19514           "\u0634\u062D": {
19515             "isolated": "\uFD0A",
19516             "final": "\uFD26",
19517             "initial": "\uFD2E",
19518             "medial": "\uFD38"
19519           },
19520           "\u0634\u062E": {
19521             "isolated": "\uFD0B",
19522             "final": "\uFD27",
19523             "initial": "\uFD2F",
19524             "medial": "\uFD39"
19525           },
19526           "\u0634\u0631": {
19527             "isolated": "\uFD0D",
19528             "final": "\uFD29"
19529           },
19530           "\u0633\u0631": {
19531             "isolated": "\uFD0E",
19532             "final": "\uFD2A"
19533           },
19534           "\u0635\u0631": {
19535             "isolated": "\uFD0F",
19536             "final": "\uFD2B"
19537           },
19538           "\u0636\u0631": {
19539             "isolated": "\uFD10",
19540             "final": "\uFD2C"
19541           },
19542           "\u0633\u0639": {
19543             "final": "\uFD17"
19544           },
19545           "\u062A\u062C\u0645": {
19546             "initial": "\uFD50"
19547           },
19548           "\u062A\u062D\u062C": {
19549             "final": "\uFD51",
19550             "initial": "\uFD52"
19551           },
19552           "\u062A\u062D\u0645": {
19553             "initial": "\uFD53"
19554           },
19555           "\u062A\u062E\u0645": {
19556             "initial": "\uFD54"
19557           },
19558           "\u062A\u0645\u062C": {
19559             "initial": "\uFD55"
19560           },
19561           "\u062A\u0645\u062D": {
19562             "initial": "\uFD56"
19563           },
19564           "\u062A\u0645\u062E": {
19565             "initial": "\uFD57"
19566           },
19567           "\u062C\u0645\u062D": {
19568             "final": "\uFD58",
19569             "initial": "\uFD59"
19570           },
19571           "\u062D\u0645\u064A": {
19572             "final": "\uFD5A"
19573           },
19574           "\u062D\u0645\u0649": {
19575             "final": "\uFD5B"
19576           },
19577           "\u0633\u062D\u062C": {
19578             "initial": "\uFD5C"
19579           },
19580           "\u0633\u062C\u062D": {
19581             "initial": "\uFD5D"
19582           },
19583           "\u0633\u062C\u0649": {
19584             "final": "\uFD5E"
19585           },
19586           "\u0633\u0645\u062D": {
19587             "final": "\uFD5F",
19588             "initial": "\uFD60"
19589           },
19590           "\u0633\u0645\u062C": {
19591             "initial": "\uFD61"
19592           },
19593           "\u0633\u0645\u0645": {
19594             "final": "\uFD62",
19595             "initial": "\uFD63"
19596           },
19597           "\u0635\u062D\u062D": {
19598             "final": "\uFD64",
19599             "initial": "\uFD65"
19600           },
19601           "\u0635\u0645\u0645": {
19602             "final": "\uFD66",
19603             "initial": "\uFDC5"
19604           },
19605           "\u0634\u062D\u0645": {
19606             "final": "\uFD67",
19607             "initial": "\uFD68"
19608           },
19609           "\u0634\u062C\u064A": {
19610             "final": "\uFD69"
19611           },
19612           "\u0634\u0645\u062E": {
19613             "final": "\uFD6A",
19614             "initial": "\uFD6B"
19615           },
19616           "\u0634\u0645\u0645": {
19617             "final": "\uFD6C",
19618             "initial": "\uFD6D"
19619           },
19620           "\u0636\u062D\u0649": {
19621             "final": "\uFD6E"
19622           },
19623           "\u0636\u062E\u0645": {
19624             "final": "\uFD6F",
19625             "initial": "\uFD70"
19626           },
19627           "\u0636\u0645\u062D": {
19628             "final": "\uFD71"
19629           },
19630           "\u0637\u0645\u062D": {
19631             "initial": "\uFD72"
19632           },
19633           "\u0637\u0645\u0645": {
19634             "initial": "\uFD73"
19635           },
19636           "\u0637\u0645\u064A": {
19637             "final": "\uFD74"
19638           },
19639           "\u0639\u062C\u0645": {
19640             "final": "\uFD75",
19641             "initial": "\uFDC4"
19642           },
19643           "\u0639\u0645\u0645": {
19644             "final": "\uFD76",
19645             "initial": "\uFD77"
19646           },
19647           "\u0639\u0645\u0649": {
19648             "final": "\uFD78"
19649           },
19650           "\u063A\u0645\u0645": {
19651             "final": "\uFD79"
19652           },
19653           "\u063A\u0645\u064A": {
19654             "final": "\uFD7A"
19655           },
19656           "\u063A\u0645\u0649": {
19657             "final": "\uFD7B"
19658           },
19659           "\u0641\u062E\u0645": {
19660             "final": "\uFD7C",
19661             "initial": "\uFD7D"
19662           },
19663           "\u0642\u0645\u062D": {
19664             "final": "\uFD7E",
19665             "initial": "\uFDB4"
19666           },
19667           "\u0642\u0645\u0645": {
19668             "final": "\uFD7F"
19669           },
19670           "\u0644\u062D\u0645": {
19671             "final": "\uFD80",
19672             "initial": "\uFDB5"
19673           },
19674           "\u0644\u062D\u064A": {
19675             "final": "\uFD81"
19676           },
19677           "\u0644\u062D\u0649": {
19678             "final": "\uFD82"
19679           },
19680           "\u0644\u062C\u062C": {
19681             "initial": "\uFD83",
19682             "final": "\uFD84"
19683           },
19684           "\u0644\u062E\u0645": {
19685             "final": "\uFD85",
19686             "initial": "\uFD86"
19687           },
19688           "\u0644\u0645\u062D": {
19689             "final": "\uFD87",
19690             "initial": "\uFD88"
19691           },
19692           "\u0645\u062D\u062C": {
19693             "initial": "\uFD89"
19694           },
19695           "\u0645\u062D\u0645": {
19696             "initial": "\uFD8A"
19697           },
19698           "\u0645\u062D\u064A": {
19699             "final": "\uFD8B"
19700           },
19701           "\u0645\u062C\u062D": {
19702             "initial": "\uFD8C"
19703           },
19704           "\u0645\u062C\u0645": {
19705             "initial": "\uFD8D"
19706           },
19707           "\u0645\u062E\u062C": {
19708             "initial": "\uFD8E"
19709           },
19710           "\u0645\u062E\u0645": {
19711             "initial": "\uFD8F"
19712           },
19713           "\u0645\u062C\u062E": {
19714             "initial": "\uFD92"
19715           },
19716           "\u0647\u0645\u062C": {
19717             "initial": "\uFD93"
19718           },
19719           "\u0647\u0645\u0645": {
19720             "initial": "\uFD94"
19721           },
19722           "\u0646\u062D\u0645": {
19723             "initial": "\uFD95"
19724           },
19725           "\u0646\u062D\u0649": {
19726             "final": "\uFD96"
19727           },
19728           "\u0646\u062C\u0645": {
19729             "final": "\uFD97",
19730             "initial": "\uFD98"
19731           },
19732           "\u0646\u062C\u0649": {
19733             "final": "\uFD99"
19734           },
19735           "\u0646\u0645\u064A": {
19736             "final": "\uFD9A"
19737           },
19738           "\u0646\u0645\u0649": {
19739             "final": "\uFD9B"
19740           },
19741           "\u064A\u0645\u0645": {
19742             "final": "\uFD9C",
19743             "initial": "\uFD9D"
19744           },
19745           "\u0628\u062E\u064A": {
19746             "final": "\uFD9E"
19747           },
19748           "\u062A\u062C\u064A": {
19749             "final": "\uFD9F"
19750           },
19751           "\u062A\u062C\u0649": {
19752             "final": "\uFDA0"
19753           },
19754           "\u062A\u062E\u064A": {
19755             "final": "\uFDA1"
19756           },
19757           "\u062A\u062E\u0649": {
19758             "final": "\uFDA2"
19759           },
19760           "\u062A\u0645\u064A": {
19761             "final": "\uFDA3"
19762           },
19763           "\u062A\u0645\u0649": {
19764             "final": "\uFDA4"
19765           },
19766           "\u062C\u0645\u064A": {
19767             "final": "\uFDA5"
19768           },
19769           "\u062C\u062D\u0649": {
19770             "final": "\uFDA6"
19771           },
19772           "\u062C\u0645\u0649": {
19773             "final": "\uFDA7"
19774           },
19775           "\u0633\u062E\u0649": {
19776             "final": "\uFDA8"
19777           },
19778           "\u0635\u062D\u064A": {
19779             "final": "\uFDA9"
19780           },
19781           "\u0634\u062D\u064A": {
19782             "final": "\uFDAA"
19783           },
19784           "\u0636\u062D\u064A": {
19785             "final": "\uFDAB"
19786           },
19787           "\u0644\u062C\u064A": {
19788             "final": "\uFDAC"
19789           },
19790           "\u0644\u0645\u064A": {
19791             "final": "\uFDAD"
19792           },
19793           "\u064A\u062D\u064A": {
19794             "final": "\uFDAE"
19795           },
19796           "\u064A\u062C\u064A": {
19797             "final": "\uFDAF"
19798           },
19799           "\u064A\u0645\u064A": {
19800             "final": "\uFDB0"
19801           },
19802           "\u0645\u0645\u064A": {
19803             "final": "\uFDB1"
19804           },
19805           "\u0642\u0645\u064A": {
19806             "final": "\uFDB2"
19807           },
19808           "\u0646\u062D\u064A": {
19809             "final": "\uFDB3"
19810           },
19811           "\u0639\u0645\u064A": {
19812             "final": "\uFDB6"
19813           },
19814           "\u0643\u0645\u064A": {
19815             "final": "\uFDB7"
19816           },
19817           "\u0646\u062C\u062D": {
19818             "initial": "\uFDB8",
19819             "final": "\uFDBD"
19820           },
19821           "\u0645\u062E\u064A": {
19822             "final": "\uFDB9"
19823           },
19824           "\u0644\u062C\u0645": {
19825             "initial": "\uFDBA",
19826             "final": "\uFDBC"
19827           },
19828           "\u0643\u0645\u0645": {
19829             "final": "\uFDBB",
19830             "initial": "\uFDC3"
19831           },
19832           "\u062C\u062D\u064A": {
19833             "final": "\uFDBE"
19834           },
19835           "\u062D\u062C\u064A": {
19836             "final": "\uFDBF"
19837           },
19838           "\u0645\u062C\u064A": {
19839             "final": "\uFDC0"
19840           },
19841           "\u0641\u0645\u064A": {
19842             "final": "\uFDC1"
19843           },
19844           "\u0628\u062D\u064A": {
19845             "final": "\uFDC2"
19846           },
19847           "\u0633\u062E\u064A": {
19848             "final": "\uFDC6"
19849           },
19850           "\u0646\u062C\u064A": {
19851             "final": "\uFDC7"
19852           },
19853           "\u0644\u0622": {
19854             "isolated": "\uFEF5",
19855             "final": "\uFEF6"
19856           },
19857           "\u0644\u0623": {
19858             "isolated": "\uFEF7",
19859             "final": "\uFEF8"
19860           },
19861           "\u0644\u0625": {
19862             "isolated": "\uFEF9",
19863             "final": "\uFEFA"
19864           },
19865           "\u0644\u0627": {
19866             "isolated": "\uFEFB",
19867             "final": "\uFEFC"
19868           },
19869           "words": {
19870             "\u0635\u0644\u06D2": "\uFDF0",
19871             "\u0642\u0644\u06D2": "\uFDF1",
19872             "\u0627\u0644\u0644\u0647": "\uFDF2",
19873             "\u0627\u0643\u0628\u0631": "\uFDF3",
19874             "\u0645\u062D\u0645\u062F": "\uFDF4",
19875             "\u0635\u0644\u0639\u0645": "\uFDF5",
19876             "\u0631\u0633\u0648\u0644": "\uFDF6",
19877             "\u0639\u0644\u064A\u0647": "\uFDF7",
19878             "\u0648\u0633\u0644\u0645": "\uFDF8",
19879             "\u0635\u0644\u0649": "\uFDF9",
19880             "\u0635\u0644\u0649\u0627\u0644\u0644\u0647\u0639\u0644\u064A\u0647\u0648\u0633\u0644\u0645": "\uFDFA",
19881             "\u062C\u0644\u062C\u0644\u0627\u0644\u0647": "\uFDFB",
19882             "\u0631\u06CC\u0627\u0644": "\uFDFC"
19883           }
19884         };
19885
19886         unicodeLigatures["default"] = ligatureReference;
19887
19888         Object.defineProperty(reference, "__esModule", {
19889           value: true
19890         });
19891         var unicode_arabic_1$3 = unicodeArabic;
19892         var unicode_ligatures_1$2 = unicodeLigatures;
19893         var letterList = Object.keys(unicode_arabic_1$3["default"]);
19894         reference.letterList = letterList;
19895         var ligatureList = Object.keys(unicode_ligatures_1$2["default"]);
19896         reference.ligatureList = ligatureList;
19897         var ligatureWordList = Object.keys(unicode_ligatures_1$2["default"].words);
19898         reference.ligatureWordList = ligatureWordList;
19899         var lams = "\u0644\u06B5\u06B6\u06B7\u06B8";
19900         reference.lams = lams;
19901         var alefs = "\u0627\u0622\u0623\u0625\u0671\u0672\u0673\u0675\u0773\u0774";
19902         reference.alefs = alefs; // for (var l = 1; l < lams.length; l++) {
19903         //   console.log('-');
19904         //   for (var a = 0; a < alefs.length; a++) {
19905         //     console.log(a + ': ' + lams[l] + alefs[a]);
19906         //   }
19907         // }
19908
19909         var tashkeel = "\u0605\u0640\u0670\u0674\u06DF\u06E7\u06E8";
19910         reference.tashkeel = tashkeel;
19911
19912         function addToTashkeel(start, finish) {
19913           for (var i = start; i <= finish; i++) {
19914             reference.tashkeel = tashkeel += String.fromCharCode(i);
19915           }
19916         }
19917
19918         addToTashkeel(0x0610, 0x061A);
19919         addToTashkeel(0x064B, 0x065F);
19920         addToTashkeel(0x06D6, 0x06DC);
19921         addToTashkeel(0x06E0, 0x06E4);
19922         addToTashkeel(0x06EA, 0x06ED);
19923         addToTashkeel(0x08D3, 0x08E1);
19924         addToTashkeel(0x08E3, 0x08FF);
19925         addToTashkeel(0xFE70, 0xFE7F);
19926         var lineBreakers = "\u0627\u0629\u0648\u06C0\u06CF\u06FD\u06FE\u076B\u076C\u0771\u0773\u0774\u0778\u0779\u08E2\u08B1\u08B2\u08B9";
19927         reference.lineBreakers = lineBreakers;
19928
19929         function addToLineBreakers(start, finish) {
19930           for (var i = start; i <= finish; i++) {
19931             reference.lineBreakers = lineBreakers += String.fromCharCode(i);
19932           }
19933         }
19934
19935         addToLineBreakers(0x0600, 0x061F); // it's OK to include tashkeel in this range as it is ignored
19936
19937         addToLineBreakers(0x0621, 0x0625);
19938         addToLineBreakers(0x062F, 0x0632);
19939         addToLineBreakers(0x0660, 0x066D); // numerals, math
19940
19941         addToLineBreakers(0x0671, 0x0677);
19942         addToLineBreakers(0x0688, 0x0699);
19943         addToLineBreakers(0x06C3, 0x06CB);
19944         addToLineBreakers(0x06D2, 0x06F9);
19945         addToLineBreakers(0x0759, 0x075B);
19946         addToLineBreakers(0x08AA, 0x08AE);
19947         addToLineBreakers(0xFB50, 0xFDFD); // presentation forms look like they could connect, but never do
19948         // Presentation Forms A includes diacritics but they are meant to stand alone
19949
19950         addToLineBreakers(0xFE80, 0xFEFC); // presentation forms look like they could connect, but never do
19951         // numerals, math
19952
19953         addToLineBreakers(0x10E60, 0x10E7F);
19954         addToLineBreakers(0x1EC70, 0x1ECBF);
19955         addToLineBreakers(0x1EE00, 0x1EEFF);
19956
19957         Object.defineProperty(GlyphSplitter$1, "__esModule", {
19958           value: true
19959         });
19960         var isArabic_1$6 = isArabic$1;
19961         var reference_1$5 = reference;
19962
19963         function GlyphSplitter(word) {
19964           var letters = [];
19965           var lastLetter = '';
19966           word.split('').forEach(function (letter) {
19967             if (isArabic_1$6.isArabic(letter)) {
19968               if (reference_1$5.tashkeel.indexOf(letter) > -1) {
19969                 letters[letters.length - 1] += letter;
19970               } 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)) {
19971                 // valid LA forms
19972                 letters[letters.length - 1] += letter;
19973               } else {
19974                 letters.push(letter);
19975               }
19976             } else {
19977               letters.push(letter);
19978             }
19979
19980             if (reference_1$5.tashkeel.indexOf(letter) === -1) {
19981               lastLetter = letter;
19982             }
19983           });
19984           return letters;
19985         }
19986
19987         GlyphSplitter$1.GlyphSplitter = GlyphSplitter;
19988
19989         var BaselineSplitter$1 = {};
19990
19991         Object.defineProperty(BaselineSplitter$1, "__esModule", {
19992           value: true
19993         });
19994         var isArabic_1$5 = isArabic$1;
19995         var reference_1$4 = reference;
19996
19997         function BaselineSplitter(word) {
19998           var letters = [];
19999           var lastLetter = '';
20000           word.split('').forEach(function (letter) {
20001             if (isArabic_1$5.isArabic(letter) && isArabic_1$5.isArabic(lastLetter)) {
20002               if (lastLetter.length && reference_1$4.tashkeel.indexOf(letter) > -1) {
20003                 letters[letters.length - 1] += letter;
20004               } else if (reference_1$4.lineBreakers.indexOf(lastLetter) > -1) {
20005                 letters.push(letter);
20006               } else {
20007                 letters[letters.length - 1] += letter;
20008               }
20009             } else {
20010               letters.push(letter);
20011             }
20012
20013             if (reference_1$4.tashkeel.indexOf(letter) === -1) {
20014               // don't allow tashkeel to hide line break
20015               lastLetter = letter;
20016             }
20017           });
20018           return letters;
20019         }
20020
20021         BaselineSplitter$1.BaselineSplitter = BaselineSplitter;
20022
20023         var Normalization = {};
20024
20025         Object.defineProperty(Normalization, "__esModule", {
20026           value: true
20027         });
20028         var unicode_arabic_1$2 = unicodeArabic;
20029         var unicode_ligatures_1$1 = unicodeLigatures;
20030         var isArabic_1$4 = isArabic$1;
20031         var reference_1$3 = reference;
20032
20033         function Normal(word, breakPresentationForm) {
20034           // default is to turn initial/isolated/medial/final presentation form to generic
20035           if (typeof breakPresentationForm === 'undefined') {
20036             breakPresentationForm = true;
20037           }
20038
20039           var returnable = '';
20040           word.split('').forEach(function (letter) {
20041             if (!isArabic_1$4.isArabic(letter)) {
20042               returnable += letter;
20043               return;
20044             }
20045
20046             for (var w = 0; w < reference_1$3.letterList.length; w++) {
20047               // ok so we are checking this potential lettertron
20048               var letterForms = unicode_arabic_1$2["default"][reference_1$3.letterList[w]];
20049               var versions = Object.keys(letterForms);
20050
20051               for (var v = 0; v < versions.length; v++) {
20052                 var localVersion = letterForms[versions[v]];
20053
20054                 if (_typeof(localVersion) === 'object' && typeof localVersion.indexOf === 'undefined') {
20055                   // look at this embedded object
20056                   var embeddedForms = Object.keys(localVersion);
20057
20058                   for (var ef = 0; ef < embeddedForms.length; ef++) {
20059                     var form = localVersion[embeddedForms[ef]];
20060
20061                     if (form === letter || _typeof(form) === 'object' && form.indexOf && form.indexOf(letter) > -1) {
20062                       // match
20063                       // console.log('embedded match');
20064                       if (form === letter) {
20065                         // match exact
20066                         if (breakPresentationForm && localVersion['normal'] && ['isolated', 'initial', 'medial', 'final'].indexOf(embeddedForms[ef]) > -1) {
20067                           // replace presentation form
20068                           // console.log('keeping normal form of the letter');
20069                           if (_typeof(localVersion['normal']) === 'object') {
20070                             returnable += localVersion['normal'][0];
20071                           } else {
20072                             returnable += localVersion['normal'];
20073                           }
20074
20075                           return;
20076                         } // console.log('keeping this letter');
20077
20078
20079                         returnable += letter;
20080                         return;
20081                       } else if (_typeof(form) === 'object' && form.indexOf && form.indexOf(letter) > -1) {
20082                         // match
20083                         returnable += form[0]; // console.log('added the first letter from the same array');
20084
20085                         return;
20086                       }
20087                     }
20088                   }
20089                 } else if (localVersion === letter) {
20090                   // match exact
20091                   if (breakPresentationForm && letterForms['normal'] && ['isolated', 'initial', 'medial', 'final'].indexOf(versions[v]) > -1) {
20092                     // replace presentation form
20093                     // console.log('keeping normal form of the letter');
20094                     if (_typeof(letterForms['normal']) === 'object') {
20095                       returnable += letterForms['normal'][0];
20096                     } else {
20097                       returnable += letterForms['normal'];
20098                     }
20099
20100                     return;
20101                   } // console.log('keeping this letter');
20102
20103
20104                   returnable += letter;
20105                   return;
20106                 } else if (_typeof(localVersion) === 'object' && localVersion.indexOf && localVersion.indexOf(letter) > -1) {
20107                   // match
20108                   returnable += localVersion[0]; // console.log('added the first letter from the same array');
20109
20110                   return;
20111                 }
20112               }
20113             } // try ligatures
20114
20115
20116             for (var v2 = 0; v2 < reference_1$3.ligatureList.length; v2++) {
20117               var normalForm = reference_1$3.ligatureList[v2];
20118
20119               if (normalForm !== 'words') {
20120                 var ligForms = Object.keys(unicode_ligatures_1$1["default"][normalForm]);
20121
20122                 for (var f = 0; f < ligForms.length; f++) {
20123                   if (unicode_ligatures_1$1["default"][normalForm][ligForms[f]] === letter) {
20124                     returnable += normalForm;
20125                     return;
20126                   }
20127                 }
20128               }
20129             } // try words ligatures
20130
20131
20132             for (var v3 = 0; v3 < reference_1$3.ligatureWordList.length; v3++) {
20133               var _normalForm = reference_1$3.ligatureWordList[v3];
20134
20135               if (unicode_ligatures_1$1["default"].words[_normalForm] === letter) {
20136                 returnable += _normalForm;
20137                 return;
20138               }
20139             }
20140
20141             returnable += letter; // console.log('kept the letter')
20142           });
20143           return returnable;
20144         }
20145
20146         Normalization.Normal = Normal;
20147
20148         var CharShaper$1 = {};
20149
20150         Object.defineProperty(CharShaper$1, "__esModule", {
20151           value: true
20152         });
20153         var unicode_arabic_1$1 = unicodeArabic;
20154         var isArabic_1$3 = isArabic$1;
20155         var reference_1$2 = reference;
20156
20157         function CharShaper(letter, form) {
20158           if (!isArabic_1$3.isArabic(letter)) {
20159             // fail not Arabic
20160             throw new Error('Not Arabic');
20161           }
20162
20163           if (letter === "\u0621") {
20164             // hamza alone
20165             return "\u0621";
20166           }
20167
20168           for (var w = 0; w < reference_1$2.letterList.length; w++) {
20169             // ok so we are checking this potential lettertron
20170             var letterForms = unicode_arabic_1$1["default"][reference_1$2.letterList[w]];
20171             var versions = Object.keys(letterForms);
20172
20173             for (var v = 0; v < versions.length; v++) {
20174               var localVersion = letterForms[versions[v]];
20175
20176               if (localVersion === letter || _typeof(localVersion) === 'object' && localVersion.indexOf && localVersion.indexOf(letter) > -1) {
20177                 if (versions.indexOf(form) > -1) {
20178                   return letterForms[form];
20179                 }
20180               } else if (_typeof(localVersion) === 'object' && typeof localVersion.indexOf === 'undefined') {
20181                 // check embedded
20182                 var embeddedVersions = Object.keys(localVersion);
20183
20184                 for (var ev = 0; ev < embeddedVersions.length; ev++) {
20185                   if (localVersion[embeddedVersions[ev]] === letter || _typeof(localVersion[embeddedVersions[ev]]) === 'object' && localVersion[embeddedVersions[ev]].indexOf && localVersion[embeddedVersions[ev]].indexOf(letter) > -1) {
20186                     if (embeddedVersions.indexOf(form) > -1) {
20187                       return localVersion[form];
20188                     }
20189                   }
20190                 }
20191               }
20192             }
20193           }
20194         }
20195
20196         CharShaper$1.CharShaper = CharShaper;
20197
20198         var WordShaper$2 = {};
20199
20200         Object.defineProperty(WordShaper$2, "__esModule", {
20201           value: true
20202         });
20203         var isArabic_1$2 = isArabic$1;
20204         var reference_1$1 = reference;
20205         var CharShaper_1$1 = CharShaper$1;
20206         var unicode_ligatures_1 = unicodeLigatures;
20207
20208         function WordShaper$1(word) {
20209           var state = 'initial';
20210           var output = '';
20211
20212           for (var w = 0; w < word.length; w++) {
20213             var nextLetter = ' ';
20214
20215             for (var nxw = w + 1; nxw < word.length; nxw++) {
20216               if (!isArabic_1$2.isArabic(word[nxw])) {
20217                 break;
20218               }
20219
20220               if (reference_1$1.tashkeel.indexOf(word[nxw]) === -1) {
20221                 nextLetter = word[nxw];
20222                 break;
20223               }
20224             }
20225
20226             if (!isArabic_1$2.isArabic(word[w]) || isArabic_1$2.isMath(word[w])) {
20227               // space or other non-Arabic
20228               output += word[w];
20229               state = 'initial';
20230             } else if (reference_1$1.tashkeel.indexOf(word[w]) > -1) {
20231               // tashkeel - add without changing state
20232               output += word[w];
20233             } else if (nextLetter === ' ' // last Arabic letter in this word
20234             || reference_1$1.lineBreakers.indexOf(word[w]) > -1) {
20235               // the current letter is known to break lines
20236               output += CharShaper_1$1.CharShaper(word[w], state === 'initial' ? 'isolated' : 'final');
20237               state = 'initial';
20238             } else if (reference_1$1.lams.indexOf(word[w]) > -1 && reference_1$1.alefs.indexOf(nextLetter) > -1) {
20239               // LA letters - advance an additional letter after this
20240               output += unicode_ligatures_1["default"][word[w] + nextLetter][state === 'initial' ? 'isolated' : 'final'];
20241
20242               while (word[w] !== nextLetter) {
20243                 w++;
20244               }
20245
20246               state = 'initial';
20247             } else {
20248               output += CharShaper_1$1.CharShaper(word[w], state);
20249               state = 'medial';
20250             }
20251           }
20252
20253           return output;
20254         }
20255
20256         WordShaper$2.WordShaper = WordShaper$1;
20257
20258         var ParentLetter$1 = {};
20259
20260         Object.defineProperty(ParentLetter$1, "__esModule", {
20261           value: true
20262         });
20263         var unicode_arabic_1 = unicodeArabic;
20264         var isArabic_1$1 = isArabic$1;
20265         var reference_1 = reference;
20266
20267         function ParentLetter(letter) {
20268           if (!isArabic_1$1.isArabic(letter)) {
20269             throw new Error('Not an Arabic letter');
20270           }
20271
20272           for (var w = 0; w < reference_1.letterList.length; w++) {
20273             // ok so we are checking this potential lettertron
20274             var letterForms = unicode_arabic_1["default"][reference_1.letterList[w]];
20275             var versions = Object.keys(letterForms);
20276
20277             for (var v = 0; v < versions.length; v++) {
20278               var localVersion = letterForms[versions[v]];
20279
20280               if (_typeof(localVersion) === 'object' && typeof localVersion.indexOf === 'undefined') {
20281                 // look at this embedded object
20282                 var embeddedForms = Object.keys(localVersion);
20283
20284                 for (var ef = 0; ef < embeddedForms.length; ef++) {
20285                   var form = localVersion[embeddedForms[ef]];
20286
20287                   if (form === letter || _typeof(form) === 'object' && form.indexOf && form.indexOf(letter) > -1) {
20288                     // match
20289                     return localVersion;
20290                   }
20291                 }
20292               } else if (localVersion === letter || _typeof(localVersion) === 'object' && localVersion.indexOf && localVersion.indexOf(letter) > -1) {
20293                 // match
20294                 return letterForms;
20295               }
20296             }
20297
20298             return null;
20299           }
20300         }
20301
20302         ParentLetter$1.ParentLetter = ParentLetter;
20303
20304         function GrandparentLetter(letter) {
20305           if (!isArabic_1$1.isArabic(letter)) {
20306             throw new Error('Not an Arabic letter');
20307           }
20308
20309           for (var w = 0; w < reference_1.letterList.length; w++) {
20310             // ok so we are checking this potential lettertron
20311             var letterForms = unicode_arabic_1["default"][reference_1.letterList[w]];
20312             var versions = Object.keys(letterForms);
20313
20314             for (var v = 0; v < versions.length; v++) {
20315               var localVersion = letterForms[versions[v]];
20316
20317               if (_typeof(localVersion) === 'object' && typeof localVersion.indexOf === 'undefined') {
20318                 // look at this embedded object
20319                 var embeddedForms = Object.keys(localVersion);
20320
20321                 for (var ef = 0; ef < embeddedForms.length; ef++) {
20322                   var form = localVersion[embeddedForms[ef]];
20323
20324                   if (form === letter || _typeof(form) === 'object' && form.indexOf && form.indexOf(letter) > -1) {
20325                     // match
20326                     return letterForms;
20327                   }
20328                 }
20329               } else if (localVersion === letter || _typeof(localVersion) === 'object' && localVersion.indexOf && localVersion.indexOf(letter) > -1) {
20330                 // match
20331                 return letterForms;
20332               }
20333             }
20334
20335             return null;
20336           }
20337         }
20338
20339         ParentLetter$1.GrandparentLetter = GrandparentLetter;
20340
20341         Object.defineProperty(lib, "__esModule", {
20342           value: true
20343         });
20344         var isArabic_1 = isArabic$1;
20345         lib.isArabic = isArabic_1.isArabic;
20346         var GlyphSplitter_1 = GlyphSplitter$1;
20347         lib.GlyphSplitter = GlyphSplitter_1.GlyphSplitter;
20348         var BaselineSplitter_1 = BaselineSplitter$1;
20349         lib.BaselineSplitter = BaselineSplitter_1.BaselineSplitter;
20350         var Normalization_1 = Normalization;
20351         lib.Normal = Normalization_1.Normal;
20352         var CharShaper_1 = CharShaper$1;
20353         lib.CharShaper = CharShaper_1.CharShaper;
20354         var WordShaper_1 = WordShaper$2;
20355         var WordShaper = lib.WordShaper = WordShaper_1.WordShaper;
20356         var ParentLetter_1 = ParentLetter$1;
20357         lib.ParentLetter = ParentLetter_1.ParentLetter;
20358         lib.GrandparentLetter = ParentLetter_1.GrandparentLetter;
20359
20360         var rtlRegex = /[\u0590-\u05FF\u0600-\u06FF\u0750-\u07BF\u08A0–\u08BF]/;
20361         function fixRTLTextForSvg(inputText) {
20362           var ret = '',
20363               rtlBuffer = [];
20364           var arabicRegex = /[\u0600-\u06FF]/g;
20365           var arabicDiacritics = /[\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06ED]/g;
20366           var arabicMath = /[\u0660-\u066C\u06F0-\u06F9]+/g;
20367           var thaanaVowel = /[\u07A6-\u07B0]/;
20368           var hebrewSign = /[\u0591-\u05bd\u05bf\u05c1-\u05c5\u05c7]/; // Arabic word shaping
20369
20370           if (arabicRegex.test(inputText)) {
20371             inputText = WordShaper(inputText);
20372           }
20373
20374           for (var n = 0; n < inputText.length; n++) {
20375             var c = inputText[n];
20376
20377             if (arabicMath.test(c)) {
20378               // Arabic numbers go LTR
20379               ret += rtlBuffer.reverse().join('');
20380               rtlBuffer = [c];
20381             } else {
20382               if (rtlBuffer.length && arabicMath.test(rtlBuffer[rtlBuffer.length - 1])) {
20383                 ret += rtlBuffer.reverse().join('');
20384                 rtlBuffer = [];
20385               }
20386
20387               if ((thaanaVowel.test(c) || hebrewSign.test(c) || arabicDiacritics.test(c)) && rtlBuffer.length) {
20388                 rtlBuffer[rtlBuffer.length - 1] += c;
20389               } else if (rtlRegex.test(c) // include Arabic presentation forms
20390               || c.charCodeAt(0) >= 64336 && c.charCodeAt(0) <= 65023 || c.charCodeAt(0) >= 65136 && c.charCodeAt(0) <= 65279) {
20391                 rtlBuffer.push(c);
20392               } else if (c === ' ' && rtlBuffer.length) {
20393                 // whitespace within RTL text
20394                 rtlBuffer = [rtlBuffer.reverse().join('') + ' '];
20395               } else {
20396                 // non-RTL character
20397                 ret += rtlBuffer.reverse().join('') + c;
20398                 rtlBuffer = [];
20399               }
20400             }
20401           }
20402
20403           ret += rtlBuffer.reverse().join('');
20404           return ret;
20405         }
20406
20407         var DESCRIPTORS$2 = descriptors;
20408         var uncurryThis$b = functionUncurryThis;
20409         var objectKeys = objectKeys$4;
20410         var toIndexedObject = toIndexedObject$c;
20411         var $propertyIsEnumerable = objectPropertyIsEnumerable.f;
20412
20413         var propertyIsEnumerable = uncurryThis$b($propertyIsEnumerable);
20414         var push$2 = uncurryThis$b([].push);
20415
20416         // `Object.{ entries, values }` methods implementation
20417         var createMethod$1 = function (TO_ENTRIES) {
20418           return function (it) {
20419             var O = toIndexedObject(it);
20420             var keys = objectKeys(O);
20421             var length = keys.length;
20422             var i = 0;
20423             var result = [];
20424             var key;
20425             while (length > i) {
20426               key = keys[i++];
20427               if (!DESCRIPTORS$2 || propertyIsEnumerable(O, key)) {
20428                 push$2(result, TO_ENTRIES ? [key, O[key]] : O[key]);
20429               }
20430             }
20431             return result;
20432           };
20433         };
20434
20435         var objectToArray = {
20436           // `Object.entries` method
20437           // https://tc39.es/ecma262/#sec-object.entries
20438           entries: createMethod$1(true),
20439           // `Object.values` method
20440           // https://tc39.es/ecma262/#sec-object.values
20441           values: createMethod$1(false)
20442         };
20443
20444         var $$r = _export;
20445         var $values = objectToArray.values;
20446
20447         // `Object.values` method
20448         // https://tc39.es/ecma262/#sec-object.values
20449         $$r({ target: 'Object', stat: true }, {
20450           values: function values(O) {
20451             return $values(O);
20452           }
20453         });
20454
20455         // https://github.com/openstreetmap/iD/issues/772
20456         // http://mathiasbynens.be/notes/localstorage-pattern#comment-9
20457         var _storage;
20458
20459         try {
20460           _storage = localStorage;
20461         } catch (e) {} // eslint-disable-line no-empty
20462
20463
20464         _storage = _storage || function () {
20465           var s = {};
20466           return {
20467             getItem: function getItem(k) {
20468               return s[k];
20469             },
20470             setItem: function setItem(k, v) {
20471               return s[k] = v;
20472             },
20473             removeItem: function removeItem(k) {
20474               return delete s[k];
20475             }
20476           };
20477         }();
20478
20479         var _listeners = {}; //
20480         // corePreferences is an interface for persisting basic key-value strings
20481         // within and between iD sessions on the same site.
20482         //
20483
20484         /**
20485          * @param {string} k
20486          * @param {string?} v
20487          * @returns {boolean} true if the action succeeded
20488          */
20489
20490         function corePreferences(k, v) {
20491           try {
20492             if (v === undefined) return _storage.getItem(k);else if (v === null) _storage.removeItem(k);else _storage.setItem(k, v);
20493
20494             if (_listeners[k]) {
20495               _listeners[k].forEach(function (handler) {
20496                 return handler(v);
20497               });
20498             }
20499
20500             return true;
20501           } catch (e) {
20502             /* eslint-disable no-console */
20503             if (typeof console !== 'undefined') {
20504               console.error('localStorage quota exceeded');
20505             }
20506             /* eslint-enable no-console */
20507
20508
20509             return false;
20510           }
20511         } // adds an event listener which is triggered whenever
20512
20513
20514         corePreferences.onChange = function (k, handler) {
20515           _listeners[k] = _listeners[k] || [];
20516
20517           _listeners[k].push(handler);
20518         };
20519
20520         var vparse = {exports: {}};
20521
20522         (function (module) {
20523           (function (window) {
20524
20525             function parseVersion(v) {
20526               var m = v.replace(/[^0-9.]/g, '').match(/[0-9]*\.|[0-9]+/g) || [];
20527               v = {
20528                 major: +m[0] || 0,
20529                 minor: +m[1] || 0,
20530                 patch: +m[2] || 0,
20531                 build: +m[3] || 0
20532               };
20533               v.isEmpty = !v.major && !v.minor && !v.patch && !v.build;
20534               v.parsed = [v.major, v.minor, v.patch, v.build];
20535               v.text = v.parsed.join('.');
20536               v.compare = compare;
20537               return v;
20538             }
20539
20540             function compare(v) {
20541               if (typeof v === 'string') {
20542                 v = parseVersion(v);
20543               }
20544
20545               for (var i = 0; i < 4; i++) {
20546                 if (this.parsed[i] !== v.parsed[i]) {
20547                   return this.parsed[i] > v.parsed[i] ? 1 : -1;
20548                 }
20549               }
20550
20551               return 0;
20552             }
20553             /* istanbul ignore next */
20554
20555
20556             if (module && 'object' === 'object') {
20557               module.exports = parseVersion;
20558             } else {
20559               window.parseVersion = parseVersion;
20560             }
20561           })(commonjsGlobal);
20562         })(vparse);
20563
20564         var parseVersion = vparse.exports;
20565
20566         var name = "iD";
20567         var version = "2.20.3";
20568         var description = "A friendly editor for OpenStreetMap";
20569         var main = "dist/iD.min.js";
20570         var repository = "github:openstreetmap/iD";
20571         var homepage = "https://github.com/openstreetmap/iD";
20572         var bugs = "https://github.com/openstreetmap/iD/issues";
20573         var keywords = ["editor","openstreetmap"];
20574         var license = "ISC";
20575         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"};
20576         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"};
20577         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"};
20578         var engines = {node:">=10"};
20579         var browserslist = ["> 0.2%, last 6 major versions, Firefox ESR, IE 11, maintained node versions"];
20580         var packageJSON = {
20581         name: name,
20582         version: version,
20583         description: description,
20584         main: main,
20585         repository: repository,
20586         homepage: homepage,
20587         bugs: bugs,
20588         keywords: keywords,
20589         license: license,
20590         scripts: scripts,
20591         dependencies: dependencies,
20592         devDependencies: devDependencies,
20593         engines: engines,
20594         browserslist: browserslist
20595         };
20596
20597         var _mainFileFetcher = coreFileFetcher(); // singleton
20598         // coreFileFetcher asynchronously fetches data from JSON files
20599         //
20600
20601         function coreFileFetcher() {
20602           var ociVersion = packageJSON.devDependencies['osm-community-index'];
20603           var v = parseVersion(ociVersion);
20604           var vMinor = "".concat(v.major, ".").concat(v.minor);
20605           var _this = {};
20606           var _inflight = {};
20607           var _fileMap = {
20608             'address_formats': 'data/address_formats.min.json',
20609             'deprecated': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/deprecated.min.json',
20610             'discarded': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/discarded.min.json',
20611             'imagery': 'data/imagery.min.json',
20612             'intro_graph': 'data/intro_graph.min.json',
20613             'keepRight': 'data/keepRight.min.json',
20614             'languages': 'data/languages.min.json',
20615             'locales': 'locales/index.min.json',
20616             'oci_defaults': "https://cdn.jsdelivr.net/npm/osm-community-index@".concat(vMinor, "/dist/defaults.min.json"),
20617             'oci_features': "https://cdn.jsdelivr.net/npm/osm-community-index@".concat(vMinor, "/dist/featureCollection.min.json"),
20618             'oci_resources': "https://cdn.jsdelivr.net/npm/osm-community-index@".concat(vMinor, "/dist/resources.min.json"),
20619             'preset_categories': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/preset_categories.min.json',
20620             'preset_defaults': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/preset_defaults.min.json',
20621             'preset_fields': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/fields.min.json',
20622             'preset_presets': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/presets.min.json',
20623             'phone_formats': 'data/phone_formats.min.json',
20624             'qa_data': 'data/qa_data.min.json',
20625             'shortcuts': 'data/shortcuts.min.json',
20626             'territory_languages': 'data/territory_languages.min.json',
20627             'wmf_sitematrix': 'https://cdn.jsdelivr.net/npm/wmf-sitematrix@0.1/wikipedia.min.json'
20628           };
20629           var _cachedData = {}; // expose the cache; useful for tests
20630
20631           _this.cache = function () {
20632             return _cachedData;
20633           }; // Returns a Promise to fetch data
20634           // (resolved with the data if we have it already)
20635
20636
20637           _this.get = function (which) {
20638             if (_cachedData[which]) {
20639               return Promise.resolve(_cachedData[which]);
20640             }
20641
20642             var file = _fileMap[which];
20643
20644             var url = file && _this.asset(file);
20645
20646             if (!url) {
20647               return Promise.reject("Unknown data file for \"".concat(which, "\""));
20648             }
20649
20650             var prom = _inflight[url];
20651
20652             if (!prom) {
20653               _inflight[url] = prom = fetch(url).then(function (response) {
20654                 // fetch in PhantomJS tests may return ok=false and status=0 even if it's okay
20655                 if (!response.ok && response.status !== 0 || !response.json) {
20656                   throw new Error(response.status + ' ' + response.statusText);
20657                 }
20658
20659                 if (response.status === 204 || response.status === 205) return; // No Content, Reset Content
20660
20661                 return response.json();
20662               }).then(function (result) {
20663                 delete _inflight[url];
20664
20665                 if (!result) {
20666                   throw new Error("No data loaded for \"".concat(which, "\""));
20667                 }
20668
20669                 _cachedData[which] = result;
20670                 return result;
20671               })["catch"](function (err) {
20672                 delete _inflight[url];
20673                 throw err;
20674               });
20675             }
20676
20677             return prom;
20678           }; // Accessor for the file map
20679
20680
20681           _this.fileMap = function (val) {
20682             if (!arguments.length) return _fileMap;
20683             _fileMap = val;
20684             return _this;
20685           };
20686
20687           var _assetPath = '';
20688
20689           _this.assetPath = function (val) {
20690             if (!arguments.length) return _assetPath;
20691             _assetPath = val;
20692             return _this;
20693           };
20694
20695           var _assetMap = {};
20696
20697           _this.assetMap = function (val) {
20698             if (!arguments.length) return _assetMap;
20699             _assetMap = val;
20700             return _this;
20701           };
20702
20703           _this.asset = function (val) {
20704             if (/^http(s)?:\/\//i.test(val)) return val;
20705             var filename = _assetPath + val;
20706             return _assetMap[filename] || filename;
20707           };
20708
20709           return _this;
20710         }
20711
20712         var global$9 = global$1m;
20713         var toIntegerOrInfinity$1 = toIntegerOrInfinity$b;
20714         var toString$7 = toString$k;
20715         var requireObjectCoercible$6 = requireObjectCoercible$e;
20716
20717         var RangeError$5 = global$9.RangeError;
20718
20719         // `String.prototype.repeat` method implementation
20720         // https://tc39.es/ecma262/#sec-string.prototype.repeat
20721         var stringRepeat = function repeat(count) {
20722           var str = toString$7(requireObjectCoercible$6(this));
20723           var result = '';
20724           var n = toIntegerOrInfinity$1(count);
20725           if (n < 0 || n == Infinity) throw RangeError$5('Wrong number of repetitions');
20726           for (;n > 0; (n >>>= 1) && (str += str)) if (n & 1) result += str;
20727           return result;
20728         };
20729
20730         var $$q = _export;
20731         var global$8 = global$1m;
20732         var uncurryThis$a = functionUncurryThis;
20733         var toIntegerOrInfinity = toIntegerOrInfinity$b;
20734         var thisNumberValue$1 = thisNumberValue$3;
20735         var $repeat$1 = stringRepeat;
20736         var fails$7 = fails$S;
20737
20738         var RangeError$4 = global$8.RangeError;
20739         var String$1 = global$8.String;
20740         var floor$2 = Math.floor;
20741         var repeat$2 = uncurryThis$a($repeat$1);
20742         var stringSlice$3 = uncurryThis$a(''.slice);
20743         var un$ToFixed = uncurryThis$a(1.0.toFixed);
20744
20745         var pow$1 = function (x, n, acc) {
20746           return n === 0 ? acc : n % 2 === 1 ? pow$1(x, n - 1, acc * x) : pow$1(x * x, n / 2, acc);
20747         };
20748
20749         var log = function (x) {
20750           var n = 0;
20751           var x2 = x;
20752           while (x2 >= 4096) {
20753             n += 12;
20754             x2 /= 4096;
20755           }
20756           while (x2 >= 2) {
20757             n += 1;
20758             x2 /= 2;
20759           } return n;
20760         };
20761
20762         var multiply = function (data, n, c) {
20763           var index = -1;
20764           var c2 = c;
20765           while (++index < 6) {
20766             c2 += n * data[index];
20767             data[index] = c2 % 1e7;
20768             c2 = floor$2(c2 / 1e7);
20769           }
20770         };
20771
20772         var divide = function (data, n) {
20773           var index = 6;
20774           var c = 0;
20775           while (--index >= 0) {
20776             c += data[index];
20777             data[index] = floor$2(c / n);
20778             c = (c % n) * 1e7;
20779           }
20780         };
20781
20782         var dataToString = function (data) {
20783           var index = 6;
20784           var s = '';
20785           while (--index >= 0) {
20786             if (s !== '' || index === 0 || data[index] !== 0) {
20787               var t = String$1(data[index]);
20788               s = s === '' ? t : s + repeat$2('0', 7 - t.length) + t;
20789             }
20790           } return s;
20791         };
20792
20793         var FORCED$6 = fails$7(function () {
20794           return un$ToFixed(0.00008, 3) !== '0.000' ||
20795             un$ToFixed(0.9, 0) !== '1' ||
20796             un$ToFixed(1.255, 2) !== '1.25' ||
20797             un$ToFixed(1000000000000000128.0, 0) !== '1000000000000000128';
20798         }) || !fails$7(function () {
20799           // V8 ~ Android 4.3-
20800           un$ToFixed({});
20801         });
20802
20803         // `Number.prototype.toFixed` method
20804         // https://tc39.es/ecma262/#sec-number.prototype.tofixed
20805         $$q({ target: 'Number', proto: true, forced: FORCED$6 }, {
20806           toFixed: function toFixed(fractionDigits) {
20807             var number = thisNumberValue$1(this);
20808             var fractDigits = toIntegerOrInfinity(fractionDigits);
20809             var data = [0, 0, 0, 0, 0, 0];
20810             var sign = '';
20811             var result = '0';
20812             var e, z, j, k;
20813
20814             if (fractDigits < 0 || fractDigits > 20) throw RangeError$4('Incorrect fraction digits');
20815             // eslint-disable-next-line no-self-compare -- NaN check
20816             if (number != number) return 'NaN';
20817             if (number <= -1e21 || number >= 1e21) return String$1(number);
20818             if (number < 0) {
20819               sign = '-';
20820               number = -number;
20821             }
20822             if (number > 1e-21) {
20823               e = log(number * pow$1(2, 69, 1)) - 69;
20824               z = e < 0 ? number * pow$1(2, -e, 1) : number / pow$1(2, e, 1);
20825               z *= 0x10000000000000;
20826               e = 52 - e;
20827               if (e > 0) {
20828                 multiply(data, 0, z);
20829                 j = fractDigits;
20830                 while (j >= 7) {
20831                   multiply(data, 1e7, 0);
20832                   j -= 7;
20833                 }
20834                 multiply(data, pow$1(10, j, 1), 0);
20835                 j = e - 1;
20836                 while (j >= 23) {
20837                   divide(data, 1 << 23);
20838                   j -= 23;
20839                 }
20840                 divide(data, 1 << j);
20841                 multiply(data, 1, 1);
20842                 divide(data, 2);
20843                 result = dataToString(data);
20844               } else {
20845                 multiply(data, 0, z);
20846                 multiply(data, 1 << -e, 0);
20847                 result = dataToString(data) + repeat$2('0', fractDigits);
20848               }
20849             }
20850             if (fractDigits > 0) {
20851               k = result.length;
20852               result = sign + (k <= fractDigits
20853                 ? '0.' + repeat$2('0', fractDigits - k) + result
20854                 : stringSlice$3(result, 0, k - fractDigits) + '.' + stringSlice$3(result, k - fractDigits));
20855             } else {
20856               result = sign + result;
20857             } return result;
20858           }
20859         });
20860
20861         var global$7 = global$1m;
20862
20863         var globalIsFinite = global$7.isFinite;
20864
20865         // `Number.isFinite` method
20866         // https://tc39.es/ecma262/#sec-number.isfinite
20867         // eslint-disable-next-line es/no-number-isfinite -- safe
20868         var numberIsFinite$1 = Number.isFinite || function isFinite(it) {
20869           return typeof it == 'number' && globalIsFinite(it);
20870         };
20871
20872         var $$p = _export;
20873         var numberIsFinite = numberIsFinite$1;
20874
20875         // `Number.isFinite` method
20876         // https://tc39.es/ecma262/#sec-number.isfinite
20877         $$p({ target: 'Number', stat: true }, { isFinite: numberIsFinite });
20878
20879         var $$o = _export;
20880         var global$6 = global$1m;
20881         var uncurryThis$9 = functionUncurryThis;
20882         var toAbsoluteIndex = toAbsoluteIndex$8;
20883
20884         var RangeError$3 = global$6.RangeError;
20885         var fromCharCode$1 = String.fromCharCode;
20886         // eslint-disable-next-line es/no-string-fromcodepoint -- required for testing
20887         var $fromCodePoint = String.fromCodePoint;
20888         var join$2 = uncurryThis$9([].join);
20889
20890         // length should be 1, old FF problem
20891         var INCORRECT_LENGTH = !!$fromCodePoint && $fromCodePoint.length != 1;
20892
20893         // `String.fromCodePoint` method
20894         // https://tc39.es/ecma262/#sec-string.fromcodepoint
20895         $$o({ target: 'String', stat: true, forced: INCORRECT_LENGTH }, {
20896           // eslint-disable-next-line no-unused-vars -- required for `.length`
20897           fromCodePoint: function fromCodePoint(x) {
20898             var elements = [];
20899             var length = arguments.length;
20900             var i = 0;
20901             var code;
20902             while (length > i) {
20903               code = +arguments[i++];
20904               if (toAbsoluteIndex(code, 0x10FFFF) !== code) throw RangeError$3(code + ' is not a valid code point');
20905               elements[i] = code < 0x10000
20906                 ? fromCharCode$1(code)
20907                 : fromCharCode$1(((code -= 0x10000) >> 10) + 0xD800, code % 0x400 + 0xDC00);
20908             } return join$2(elements, '');
20909           }
20910         });
20911
20912         var call$2 = functionCall;
20913         var fixRegExpWellKnownSymbolLogic = fixRegexpWellKnownSymbolLogic;
20914         var anObject = anObject$n;
20915         var requireObjectCoercible$5 = requireObjectCoercible$e;
20916         var sameValue = sameValue$1;
20917         var toString$6 = toString$k;
20918         var getMethod = getMethod$7;
20919         var regExpExec = regexpExecAbstract;
20920
20921         // @@search logic
20922         fixRegExpWellKnownSymbolLogic('search', function (SEARCH, nativeSearch, maybeCallNative) {
20923           return [
20924             // `String.prototype.search` method
20925             // https://tc39.es/ecma262/#sec-string.prototype.search
20926             function search(regexp) {
20927               var O = requireObjectCoercible$5(this);
20928               var searcher = regexp == undefined ? undefined : getMethod(regexp, SEARCH);
20929               return searcher ? call$2(searcher, regexp, O) : new RegExp(regexp)[SEARCH](toString$6(O));
20930             },
20931             // `RegExp.prototype[@@search]` method
20932             // https://tc39.es/ecma262/#sec-regexp.prototype-@@search
20933             function (string) {
20934               var rx = anObject(this);
20935               var S = toString$6(string);
20936               var res = maybeCallNative(nativeSearch, rx, S);
20937
20938               if (res.done) return res.value;
20939
20940               var previousLastIndex = rx.lastIndex;
20941               if (!sameValue(previousLastIndex, 0)) rx.lastIndex = 0;
20942               var result = regExpExec(rx, S);
20943               if (!sameValue(rx.lastIndex, previousLastIndex)) rx.lastIndex = previousLastIndex;
20944               return result === null ? -1 : result.index;
20945             }
20946           ];
20947         });
20948
20949         var rbush$2 = {exports: {}};
20950
20951         var quickselect$2 = {exports: {}};
20952
20953         (function (module, exports) {
20954           (function (global, factory) {
20955             module.exports = factory() ;
20956           })(commonjsGlobal, function () {
20957
20958             function quickselect(arr, k, left, right, compare) {
20959               quickselectStep(arr, k, left || 0, right || arr.length - 1, compare || defaultCompare);
20960             }
20961
20962             function quickselectStep(arr, k, left, right, compare) {
20963               while (right > left) {
20964                 if (right - left > 600) {
20965                   var n = right - left + 1;
20966                   var m = k - left + 1;
20967                   var z = Math.log(n);
20968                   var s = 0.5 * Math.exp(2 * z / 3);
20969                   var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
20970                   var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
20971                   var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
20972                   quickselectStep(arr, k, newLeft, newRight, compare);
20973                 }
20974
20975                 var t = arr[k];
20976                 var i = left;
20977                 var j = right;
20978                 swap(arr, left, k);
20979                 if (compare(arr[right], t) > 0) swap(arr, left, right);
20980
20981                 while (i < j) {
20982                   swap(arr, i, j);
20983                   i++;
20984                   j--;
20985
20986                   while (compare(arr[i], t) < 0) {
20987                     i++;
20988                   }
20989
20990                   while (compare(arr[j], t) > 0) {
20991                     j--;
20992                   }
20993                 }
20994
20995                 if (compare(arr[left], t) === 0) swap(arr, left, j);else {
20996                   j++;
20997                   swap(arr, j, right);
20998                 }
20999                 if (j <= k) left = j + 1;
21000                 if (k <= j) right = j - 1;
21001               }
21002             }
21003
21004             function swap(arr, i, j) {
21005               var tmp = arr[i];
21006               arr[i] = arr[j];
21007               arr[j] = tmp;
21008             }
21009
21010             function defaultCompare(a, b) {
21011               return a < b ? -1 : a > b ? 1 : 0;
21012             }
21013
21014             return quickselect;
21015           });
21016         })(quickselect$2);
21017
21018         rbush$2.exports = rbush$1;
21019
21020         rbush$2.exports["default"] = rbush$1;
21021
21022         var quickselect$1 = quickselect$2.exports;
21023
21024         function rbush$1(maxEntries, format) {
21025           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
21026
21027           this._maxEntries = Math.max(4, maxEntries || 9);
21028           this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
21029
21030           if (format) {
21031             this._initFormat(format);
21032           }
21033
21034           this.clear();
21035         }
21036
21037         rbush$1.prototype = {
21038           all: function all() {
21039             return this._all(this.data, []);
21040           },
21041           search: function search(bbox) {
21042             var node = this.data,
21043                 result = [],
21044                 toBBox = this.toBBox;
21045             if (!intersects$1(bbox, node)) return result;
21046             var nodesToSearch = [],
21047                 i,
21048                 len,
21049                 child,
21050                 childBBox;
21051
21052             while (node) {
21053               for (i = 0, len = node.children.length; i < len; i++) {
21054                 child = node.children[i];
21055                 childBBox = node.leaf ? toBBox(child) : child;
21056
21057                 if (intersects$1(bbox, childBBox)) {
21058                   if (node.leaf) result.push(child);else if (contains$1(bbox, childBBox)) this._all(child, result);else nodesToSearch.push(child);
21059                 }
21060               }
21061
21062               node = nodesToSearch.pop();
21063             }
21064
21065             return result;
21066           },
21067           collides: function collides(bbox) {
21068             var node = this.data,
21069                 toBBox = this.toBBox;
21070             if (!intersects$1(bbox, node)) return false;
21071             var nodesToSearch = [],
21072                 i,
21073                 len,
21074                 child,
21075                 childBBox;
21076
21077             while (node) {
21078               for (i = 0, len = node.children.length; i < len; i++) {
21079                 child = node.children[i];
21080                 childBBox = node.leaf ? toBBox(child) : child;
21081
21082                 if (intersects$1(bbox, childBBox)) {
21083                   if (node.leaf || contains$1(bbox, childBBox)) return true;
21084                   nodesToSearch.push(child);
21085                 }
21086               }
21087
21088               node = nodesToSearch.pop();
21089             }
21090
21091             return false;
21092           },
21093           load: function load(data) {
21094             if (!(data && data.length)) return this;
21095
21096             if (data.length < this._minEntries) {
21097               for (var i = 0, len = data.length; i < len; i++) {
21098                 this.insert(data[i]);
21099               }
21100
21101               return this;
21102             } // recursively build the tree with the given data from scratch using OMT algorithm
21103
21104
21105             var node = this._build(data.slice(), 0, data.length - 1, 0);
21106
21107             if (!this.data.children.length) {
21108               // save as is if tree is empty
21109               this.data = node;
21110             } else if (this.data.height === node.height) {
21111               // split root if trees have the same height
21112               this._splitRoot(this.data, node);
21113             } else {
21114               if (this.data.height < node.height) {
21115                 // swap trees if inserted one is bigger
21116                 var tmpNode = this.data;
21117                 this.data = node;
21118                 node = tmpNode;
21119               } // insert the small tree into the large tree at appropriate level
21120
21121
21122               this._insert(node, this.data.height - node.height - 1, true);
21123             }
21124
21125             return this;
21126           },
21127           insert: function insert(item) {
21128             if (item) this._insert(item, this.data.height - 1);
21129             return this;
21130           },
21131           clear: function clear() {
21132             this.data = createNode$1([]);
21133             return this;
21134           },
21135           remove: function remove(item, equalsFn) {
21136             if (!item) return this;
21137             var node = this.data,
21138                 bbox = this.toBBox(item),
21139                 path = [],
21140                 indexes = [],
21141                 i,
21142                 parent,
21143                 index,
21144                 goingUp; // depth-first iterative tree traversal
21145
21146             while (node || path.length) {
21147               if (!node) {
21148                 // go up
21149                 node = path.pop();
21150                 parent = path[path.length - 1];
21151                 i = indexes.pop();
21152                 goingUp = true;
21153               }
21154
21155               if (node.leaf) {
21156                 // check current node
21157                 index = findItem$1(item, node.children, equalsFn);
21158
21159                 if (index !== -1) {
21160                   // item found, remove the item and condense tree upwards
21161                   node.children.splice(index, 1);
21162                   path.push(node);
21163
21164                   this._condense(path);
21165
21166                   return this;
21167                 }
21168               }
21169
21170               if (!goingUp && !node.leaf && contains$1(node, bbox)) {
21171                 // go down
21172                 path.push(node);
21173                 indexes.push(i);
21174                 i = 0;
21175                 parent = node;
21176                 node = node.children[0];
21177               } else if (parent) {
21178                 // go right
21179                 i++;
21180                 node = parent.children[i];
21181                 goingUp = false;
21182               } else node = null; // nothing found
21183
21184             }
21185
21186             return this;
21187           },
21188           toBBox: function toBBox(item) {
21189             return item;
21190           },
21191           compareMinX: compareNodeMinX$1,
21192           compareMinY: compareNodeMinY$1,
21193           toJSON: function toJSON() {
21194             return this.data;
21195           },
21196           fromJSON: function fromJSON(data) {
21197             this.data = data;
21198             return this;
21199           },
21200           _all: function _all(node, result) {
21201             var nodesToSearch = [];
21202
21203             while (node) {
21204               if (node.leaf) result.push.apply(result, node.children);else nodesToSearch.push.apply(nodesToSearch, node.children);
21205               node = nodesToSearch.pop();
21206             }
21207
21208             return result;
21209           },
21210           _build: function _build(items, left, right, height) {
21211             var N = right - left + 1,
21212                 M = this._maxEntries,
21213                 node;
21214
21215             if (N <= M) {
21216               // reached leaf level; return leaf
21217               node = createNode$1(items.slice(left, right + 1));
21218               calcBBox$1(node, this.toBBox);
21219               return node;
21220             }
21221
21222             if (!height) {
21223               // target height of the bulk-loaded tree
21224               height = Math.ceil(Math.log(N) / Math.log(M)); // target number of root entries to maximize storage utilization
21225
21226               M = Math.ceil(N / Math.pow(M, height - 1));
21227             }
21228
21229             node = createNode$1([]);
21230             node.leaf = false;
21231             node.height = height; // split the items into M mostly square tiles
21232
21233             var N2 = Math.ceil(N / M),
21234                 N1 = N2 * Math.ceil(Math.sqrt(M)),
21235                 i,
21236                 j,
21237                 right2,
21238                 right3;
21239             multiSelect$1(items, left, right, N1, this.compareMinX);
21240
21241             for (i = left; i <= right; i += N1) {
21242               right2 = Math.min(i + N1 - 1, right);
21243               multiSelect$1(items, i, right2, N2, this.compareMinY);
21244
21245               for (j = i; j <= right2; j += N2) {
21246                 right3 = Math.min(j + N2 - 1, right2); // pack each entry recursively
21247
21248                 node.children.push(this._build(items, j, right3, height - 1));
21249               }
21250             }
21251
21252             calcBBox$1(node, this.toBBox);
21253             return node;
21254           },
21255           _chooseSubtree: function _chooseSubtree(bbox, node, level, path) {
21256             var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;
21257
21258             while (true) {
21259               path.push(node);
21260               if (node.leaf || path.length - 1 === level) break;
21261               minArea = minEnlargement = Infinity;
21262
21263               for (i = 0, len = node.children.length; i < len; i++) {
21264                 child = node.children[i];
21265                 area = bboxArea$1(child);
21266                 enlargement = enlargedArea$1(bbox, child) - area; // choose entry with the least area enlargement
21267
21268                 if (enlargement < minEnlargement) {
21269                   minEnlargement = enlargement;
21270                   minArea = area < minArea ? area : minArea;
21271                   targetNode = child;
21272                 } else if (enlargement === minEnlargement) {
21273                   // otherwise choose one with the smallest area
21274                   if (area < minArea) {
21275                     minArea = area;
21276                     targetNode = child;
21277                   }
21278                 }
21279               }
21280
21281               node = targetNode || node.children[0];
21282             }
21283
21284             return node;
21285           },
21286           _insert: function _insert(item, level, isNode) {
21287             var toBBox = this.toBBox,
21288                 bbox = isNode ? item : toBBox(item),
21289                 insertPath = []; // find the best node for accommodating the item, saving all nodes along the path too
21290
21291             var node = this._chooseSubtree(bbox, this.data, level, insertPath); // put the item into the node
21292
21293
21294             node.children.push(item);
21295             extend$2(node, bbox); // split on node overflow; propagate upwards if necessary
21296
21297             while (level >= 0) {
21298               if (insertPath[level].children.length > this._maxEntries) {
21299                 this._split(insertPath, level);
21300
21301                 level--;
21302               } else break;
21303             } // adjust bboxes along the insertion path
21304
21305
21306             this._adjustParentBBoxes(bbox, insertPath, level);
21307           },
21308           // split overflowed node into two
21309           _split: function _split(insertPath, level) {
21310             var node = insertPath[level],
21311                 M = node.children.length,
21312                 m = this._minEntries;
21313
21314             this._chooseSplitAxis(node, m, M);
21315
21316             var splitIndex = this._chooseSplitIndex(node, m, M);
21317
21318             var newNode = createNode$1(node.children.splice(splitIndex, node.children.length - splitIndex));
21319             newNode.height = node.height;
21320             newNode.leaf = node.leaf;
21321             calcBBox$1(node, this.toBBox);
21322             calcBBox$1(newNode, this.toBBox);
21323             if (level) insertPath[level - 1].children.push(newNode);else this._splitRoot(node, newNode);
21324           },
21325           _splitRoot: function _splitRoot(node, newNode) {
21326             // split root node
21327             this.data = createNode$1([node, newNode]);
21328             this.data.height = node.height + 1;
21329             this.data.leaf = false;
21330             calcBBox$1(this.data, this.toBBox);
21331           },
21332           _chooseSplitIndex: function _chooseSplitIndex(node, m, M) {
21333             var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;
21334             minOverlap = minArea = Infinity;
21335
21336             for (i = m; i <= M - m; i++) {
21337               bbox1 = distBBox$1(node, 0, i, this.toBBox);
21338               bbox2 = distBBox$1(node, i, M, this.toBBox);
21339               overlap = intersectionArea$1(bbox1, bbox2);
21340               area = bboxArea$1(bbox1) + bboxArea$1(bbox2); // choose distribution with minimum overlap
21341
21342               if (overlap < minOverlap) {
21343                 minOverlap = overlap;
21344                 index = i;
21345                 minArea = area < minArea ? area : minArea;
21346               } else if (overlap === minOverlap) {
21347                 // otherwise choose distribution with minimum area
21348                 if (area < minArea) {
21349                   minArea = area;
21350                   index = i;
21351                 }
21352               }
21353             }
21354
21355             return index;
21356           },
21357           // sorts node children by the best axis for split
21358           _chooseSplitAxis: function _chooseSplitAxis(node, m, M) {
21359             var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX$1,
21360                 compareMinY = node.leaf ? this.compareMinY : compareNodeMinY$1,
21361                 xMargin = this._allDistMargin(node, m, M, compareMinX),
21362                 yMargin = this._allDistMargin(node, m, M, compareMinY); // if total distributions margin value is minimal for x, sort by minX,
21363             // otherwise it's already sorted by minY
21364
21365
21366             if (xMargin < yMargin) node.children.sort(compareMinX);
21367           },
21368           // total margin of all possible split distributions where each node is at least m full
21369           _allDistMargin: function _allDistMargin(node, m, M, compare) {
21370             node.children.sort(compare);
21371             var toBBox = this.toBBox,
21372                 leftBBox = distBBox$1(node, 0, m, toBBox),
21373                 rightBBox = distBBox$1(node, M - m, M, toBBox),
21374                 margin = bboxMargin$1(leftBBox) + bboxMargin$1(rightBBox),
21375                 i,
21376                 child;
21377
21378             for (i = m; i < M - m; i++) {
21379               child = node.children[i];
21380               extend$2(leftBBox, node.leaf ? toBBox(child) : child);
21381               margin += bboxMargin$1(leftBBox);
21382             }
21383
21384             for (i = M - m - 1; i >= m; i--) {
21385               child = node.children[i];
21386               extend$2(rightBBox, node.leaf ? toBBox(child) : child);
21387               margin += bboxMargin$1(rightBBox);
21388             }
21389
21390             return margin;
21391           },
21392           _adjustParentBBoxes: function _adjustParentBBoxes(bbox, path, level) {
21393             // adjust bboxes along the given tree path
21394             for (var i = level; i >= 0; i--) {
21395               extend$2(path[i], bbox);
21396             }
21397           },
21398           _condense: function _condense(path) {
21399             // go through the path, removing empty nodes and updating bboxes
21400             for (var i = path.length - 1, siblings; i >= 0; i--) {
21401               if (path[i].children.length === 0) {
21402                 if (i > 0) {
21403                   siblings = path[i - 1].children;
21404                   siblings.splice(siblings.indexOf(path[i]), 1);
21405                 } else this.clear();
21406               } else calcBBox$1(path[i], this.toBBox);
21407             }
21408           },
21409           _initFormat: function _initFormat(format) {
21410             // data format (minX, minY, maxX, maxY accessors)
21411             // uses eval-type function compilation instead of just accepting a toBBox function
21412             // because the algorithms are very sensitive to sorting functions performance,
21413             // so they should be dead simple and without inner calls
21414             var compareArr = ['return a', ' - b', ';'];
21415             this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
21416             this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
21417             this.toBBox = new Function('a', 'return {minX: a' + format[0] + ', minY: a' + format[1] + ', maxX: a' + format[2] + ', maxY: a' + format[3] + '};');
21418           }
21419         };
21420
21421         function findItem$1(item, items, equalsFn) {
21422           if (!equalsFn) return items.indexOf(item);
21423
21424           for (var i = 0; i < items.length; i++) {
21425             if (equalsFn(item, items[i])) return i;
21426           }
21427
21428           return -1;
21429         } // calculate node's bbox from bboxes of its children
21430
21431
21432         function calcBBox$1(node, toBBox) {
21433           distBBox$1(node, 0, node.children.length, toBBox, node);
21434         } // min bounding rectangle of node children from k to p-1
21435
21436
21437         function distBBox$1(node, k, p, toBBox, destNode) {
21438           if (!destNode) destNode = createNode$1(null);
21439           destNode.minX = Infinity;
21440           destNode.minY = Infinity;
21441           destNode.maxX = -Infinity;
21442           destNode.maxY = -Infinity;
21443
21444           for (var i = k, child; i < p; i++) {
21445             child = node.children[i];
21446             extend$2(destNode, node.leaf ? toBBox(child) : child);
21447           }
21448
21449           return destNode;
21450         }
21451
21452         function extend$2(a, b) {
21453           a.minX = Math.min(a.minX, b.minX);
21454           a.minY = Math.min(a.minY, b.minY);
21455           a.maxX = Math.max(a.maxX, b.maxX);
21456           a.maxY = Math.max(a.maxY, b.maxY);
21457           return a;
21458         }
21459
21460         function compareNodeMinX$1(a, b) {
21461           return a.minX - b.minX;
21462         }
21463
21464         function compareNodeMinY$1(a, b) {
21465           return a.minY - b.minY;
21466         }
21467
21468         function bboxArea$1(a) {
21469           return (a.maxX - a.minX) * (a.maxY - a.minY);
21470         }
21471
21472         function bboxMargin$1(a) {
21473           return a.maxX - a.minX + (a.maxY - a.minY);
21474         }
21475
21476         function enlargedArea$1(a, b) {
21477           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));
21478         }
21479
21480         function intersectionArea$1(a, b) {
21481           var minX = Math.max(a.minX, b.minX),
21482               minY = Math.max(a.minY, b.minY),
21483               maxX = Math.min(a.maxX, b.maxX),
21484               maxY = Math.min(a.maxY, b.maxY);
21485           return Math.max(0, maxX - minX) * Math.max(0, maxY - minY);
21486         }
21487
21488         function contains$1(a, b) {
21489           return a.minX <= b.minX && a.minY <= b.minY && b.maxX <= a.maxX && b.maxY <= a.maxY;
21490         }
21491
21492         function intersects$1(a, b) {
21493           return b.minX <= a.maxX && b.minY <= a.maxY && b.maxX >= a.minX && b.maxY >= a.minY;
21494         }
21495
21496         function createNode$1(children) {
21497           return {
21498             children: children,
21499             height: 1,
21500             leaf: true,
21501             minX: Infinity,
21502             minY: Infinity,
21503             maxX: -Infinity,
21504             maxY: -Infinity
21505           };
21506         } // sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
21507         // combines selection algorithm with binary divide & conquer approach
21508
21509
21510         function multiSelect$1(arr, left, right, n, compare) {
21511           var stack = [left, right],
21512               mid;
21513
21514           while (stack.length) {
21515             right = stack.pop();
21516             left = stack.pop();
21517             if (right - left <= n) continue;
21518             mid = left + Math.ceil((right - left) / n / 2) * n;
21519             quickselect$1(arr, mid, left, right, compare);
21520             stack.push(left, mid, mid, right);
21521           }
21522         }
21523
21524         var lineclip_1 = lineclip$2;
21525         lineclip$2.polyline = lineclip$2;
21526         lineclip$2.polygon = polygonclip$1; // Cohen-Sutherland line clippign algorithm, adapted to efficiently
21527         // handle polylines rather than just segments
21528
21529         function lineclip$2(points, bbox, result) {
21530           var len = points.length,
21531               codeA = bitCode$1(points[0], bbox),
21532               part = [],
21533               i,
21534               a,
21535               b,
21536               codeB,
21537               lastCode;
21538           if (!result) result = [];
21539
21540           for (i = 1; i < len; i++) {
21541             a = points[i - 1];
21542             b = points[i];
21543             codeB = lastCode = bitCode$1(b, bbox);
21544
21545             while (true) {
21546               if (!(codeA | codeB)) {
21547                 // accept
21548                 part.push(a);
21549
21550                 if (codeB !== lastCode) {
21551                   // segment went outside
21552                   part.push(b);
21553
21554                   if (i < len - 1) {
21555                     // start a new line
21556                     result.push(part);
21557                     part = [];
21558                   }
21559                 } else if (i === len - 1) {
21560                   part.push(b);
21561                 }
21562
21563                 break;
21564               } else if (codeA & codeB) {
21565                 // trivial reject
21566                 break;
21567               } else if (codeA) {
21568                 // a outside, intersect with clip edge
21569                 a = intersect$1(a, b, codeA, bbox);
21570                 codeA = bitCode$1(a, bbox);
21571               } else {
21572                 // b outside
21573                 b = intersect$1(a, b, codeB, bbox);
21574                 codeB = bitCode$1(b, bbox);
21575               }
21576             }
21577
21578             codeA = lastCode;
21579           }
21580
21581           if (part.length) result.push(part);
21582           return result;
21583         } // Sutherland-Hodgeman polygon clipping algorithm
21584
21585
21586         function polygonclip$1(points, bbox) {
21587           var result, edge, prev, prevInside, i, p, inside; // clip against each side of the clip rectangle
21588
21589           for (edge = 1; edge <= 8; edge *= 2) {
21590             result = [];
21591             prev = points[points.length - 1];
21592             prevInside = !(bitCode$1(prev, bbox) & edge);
21593
21594             for (i = 0; i < points.length; i++) {
21595               p = points[i];
21596               inside = !(bitCode$1(p, bbox) & edge); // if segment goes through the clip window, add an intersection
21597
21598               if (inside !== prevInside) result.push(intersect$1(prev, p, edge, bbox));
21599               if (inside) result.push(p); // add a point if it's inside
21600
21601               prev = p;
21602               prevInside = inside;
21603             }
21604
21605             points = result;
21606             if (!points.length) break;
21607           }
21608
21609           return result;
21610         } // intersect a segment against one of the 4 lines that make up the bbox
21611
21612
21613         function intersect$1(a, b, edge, bbox) {
21614           return edge & 8 ? [a[0] + (b[0] - a[0]) * (bbox[3] - a[1]) / (b[1] - a[1]), bbox[3]] : // top
21615           edge & 4 ? [a[0] + (b[0] - a[0]) * (bbox[1] - a[1]) / (b[1] - a[1]), bbox[1]] : // bottom
21616           edge & 2 ? [bbox[2], a[1] + (b[1] - a[1]) * (bbox[2] - a[0]) / (b[0] - a[0])] : // right
21617           edge & 1 ? [bbox[0], a[1] + (b[1] - a[1]) * (bbox[0] - a[0]) / (b[0] - a[0])] : // left
21618           null;
21619         } // bit code reflects the point position relative to the bbox:
21620         //         left  mid  right
21621         //    top  1001  1000  1010
21622         //    mid  0001  0000  0010
21623         // bottom  0101  0100  0110
21624
21625
21626         function bitCode$1(p, bbox) {
21627           var code = 0;
21628           if (p[0] < bbox[0]) code |= 1; // left
21629           else if (p[0] > bbox[2]) code |= 2; // right
21630
21631           if (p[1] < bbox[1]) code |= 4; // bottom
21632           else if (p[1] > bbox[3]) code |= 8; // top
21633
21634           return code;
21635         }
21636
21637         var rbush = rbush$2.exports;
21638         var lineclip$1 = lineclip_1;
21639         var whichPolygon_1 = whichPolygon;
21640
21641         function whichPolygon(data) {
21642           var bboxes = [];
21643
21644           for (var i = 0; i < data.features.length; i++) {
21645             var feature = data.features[i];
21646             var coords = feature.geometry.coordinates;
21647
21648             if (feature.geometry.type === 'Polygon') {
21649               bboxes.push(treeItem(coords, feature.properties));
21650             } else if (feature.geometry.type === 'MultiPolygon') {
21651               for (var j = 0; j < coords.length; j++) {
21652                 bboxes.push(treeItem(coords[j], feature.properties));
21653               }
21654             }
21655           }
21656
21657           var tree = rbush().load(bboxes);
21658
21659           function query(p, multi) {
21660             var output = [],
21661                 result = tree.search({
21662               minX: p[0],
21663               minY: p[1],
21664               maxX: p[0],
21665               maxY: p[1]
21666             });
21667
21668             for (var i = 0; i < result.length; i++) {
21669               if (insidePolygon(result[i].coords, p)) {
21670                 if (multi) output.push(result[i].props);else return result[i].props;
21671               }
21672             }
21673
21674             return multi && output.length ? output : null;
21675           }
21676
21677           query.tree = tree;
21678
21679           query.bbox = function queryBBox(bbox) {
21680             var output = [];
21681             var result = tree.search({
21682               minX: bbox[0],
21683               minY: bbox[1],
21684               maxX: bbox[2],
21685               maxY: bbox[3]
21686             });
21687
21688             for (var i = 0; i < result.length; i++) {
21689               if (polygonIntersectsBBox(result[i].coords, bbox)) {
21690                 output.push(result[i].props);
21691               }
21692             }
21693
21694             return output;
21695           };
21696
21697           return query;
21698         }
21699
21700         function polygonIntersectsBBox(polygon, bbox) {
21701           var bboxCenter = [(bbox[0] + bbox[2]) / 2, (bbox[1] + bbox[3]) / 2];
21702           if (insidePolygon(polygon, bboxCenter)) return true;
21703
21704           for (var i = 0; i < polygon.length; i++) {
21705             if (lineclip$1(polygon[i], bbox).length > 0) return true;
21706           }
21707
21708           return false;
21709         } // ray casting algorithm for detecting if point is in polygon
21710
21711
21712         function insidePolygon(rings, p) {
21713           var inside = false;
21714
21715           for (var i = 0, len = rings.length; i < len; i++) {
21716             var ring = rings[i];
21717
21718             for (var j = 0, len2 = ring.length, k = len2 - 1; j < len2; k = j++) {
21719               if (rayIntersect(p, ring[j], ring[k])) inside = !inside;
21720             }
21721           }
21722
21723           return inside;
21724         }
21725
21726         function rayIntersect(p, p1, p2) {
21727           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];
21728         }
21729
21730         function treeItem(coords, props) {
21731           var item = {
21732             minX: Infinity,
21733             minY: Infinity,
21734             maxX: -Infinity,
21735             maxY: -Infinity,
21736             coords: coords,
21737             props: props
21738           };
21739
21740           for (var i = 0; i < coords[0].length; i++) {
21741             var p = coords[0][i];
21742             item.minX = Math.min(item.minX, p[0]);
21743             item.minY = Math.min(item.minY, p[1]);
21744             item.maxX = Math.max(item.maxX, p[0]);
21745             item.maxY = Math.max(item.maxY, p[1]);
21746           }
21747
21748           return item;
21749         }
21750
21751         var type = "FeatureCollection";
21752         var features = [{
21753           type: "Feature",
21754           properties: {
21755             wikidata: "Q21",
21756             nameEn: "England",
21757             aliases: ["GB-ENG"],
21758             country: "GB",
21759             groups: ["Q23666", "Q3336843", "154", "150", "UN"],
21760             driveSide: "left",
21761             roadSpeedUnit: "mph",
21762             roadHeightUnit: "ft",
21763             callingCodes: ["44"]
21764           },
21765           geometry: {
21766             type: "MultiPolygon",
21767             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]]]]
21768           }
21769         }, {
21770           type: "Feature",
21771           properties: {
21772             wikidata: "Q22",
21773             nameEn: "Scotland",
21774             aliases: ["GB-SCT"],
21775             country: "GB",
21776             groups: ["Q23666", "Q3336843", "154", "150", "UN"],
21777             driveSide: "left",
21778             roadSpeedUnit: "mph",
21779             roadHeightUnit: "ft",
21780             callingCodes: ["44"]
21781           },
21782           geometry: {
21783             type: "MultiPolygon",
21784             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]]]]
21785           }
21786         }, {
21787           type: "Feature",
21788           properties: {
21789             wikidata: "Q25",
21790             nameEn: "Wales",
21791             aliases: ["GB-WLS"],
21792             country: "GB",
21793             groups: ["Q23666", "Q3336843", "154", "150", "UN"],
21794             driveSide: "left",
21795             roadSpeedUnit: "mph",
21796             roadHeightUnit: "ft",
21797             callingCodes: ["44"]
21798           },
21799           geometry: {
21800             type: "MultiPolygon",
21801             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]]]]
21802           }
21803         }, {
21804           type: "Feature",
21805           properties: {
21806             wikidata: "Q26",
21807             nameEn: "Northern Ireland",
21808             aliases: ["GB-NIR"],
21809             country: "GB",
21810             groups: ["Q22890", "Q3336843", "154", "150", "UN"],
21811             driveSide: "left",
21812             roadSpeedUnit: "mph",
21813             roadHeightUnit: "ft",
21814             callingCodes: ["44"]
21815           },
21816           geometry: {
21817             type: "MultiPolygon",
21818             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]]]]
21819           }
21820         }, {
21821           type: "Feature",
21822           properties: {
21823             wikidata: "Q35",
21824             nameEn: "Denmark",
21825             country: "DK",
21826             groups: ["EU", "154", "150", "UN"],
21827             callingCodes: ["45"]
21828           },
21829           geometry: {
21830             type: "MultiPolygon",
21831             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]]]]
21832           }
21833         }, {
21834           type: "Feature",
21835           properties: {
21836             wikidata: "Q55",
21837             nameEn: "Netherlands",
21838             country: "NL",
21839             groups: ["EU", "155", "150", "UN"],
21840             callingCodes: ["31"]
21841           },
21842           geometry: {
21843             type: "MultiPolygon",
21844             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]]]]
21845           }
21846         }, {
21847           type: "Feature",
21848           properties: {
21849             wikidata: "Q782",
21850             nameEn: "Hawaii",
21851             aliases: ["US-HI"],
21852             country: "US",
21853             groups: ["Q35657", "061", "009", "UN"],
21854             roadSpeedUnit: "mph",
21855             roadHeightUnit: "ft",
21856             callingCodes: ["1"]
21857           },
21858           geometry: {
21859             type: "MultiPolygon",
21860             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]]]]
21861           }
21862         }, {
21863           type: "Feature",
21864           properties: {
21865             wikidata: "Q797",
21866             nameEn: "Alaska",
21867             aliases: ["US-AK"],
21868             country: "US",
21869             groups: ["Q35657", "021", "003", "019", "UN"],
21870             roadSpeedUnit: "mph",
21871             roadHeightUnit: "ft",
21872             callingCodes: ["1"]
21873           },
21874           geometry: {
21875             type: "MultiPolygon",
21876             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]]]]
21877           }
21878         }, {
21879           type: "Feature",
21880           properties: {
21881             wikidata: "Q3492",
21882             nameEn: "Sumatra",
21883             aliases: ["ID-SM"],
21884             country: "ID",
21885             groups: ["035", "142", "UN"],
21886             driveSide: "left",
21887             callingCodes: ["62"]
21888           },
21889           geometry: {
21890             type: "MultiPolygon",
21891             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]]]]
21892           }
21893         }, {
21894           type: "Feature",
21895           properties: {
21896             wikidata: "Q3757",
21897             nameEn: "Java",
21898             aliases: ["ID-JW"],
21899             country: "ID",
21900             groups: ["035", "142", "UN"],
21901             driveSide: "left",
21902             callingCodes: ["62"]
21903           },
21904           geometry: {
21905             type: "MultiPolygon",
21906             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]]]]
21907           }
21908         }, {
21909           type: "Feature",
21910           properties: {
21911             wikidata: "Q3795",
21912             nameEn: "Kalimantan",
21913             aliases: ["ID-KA"],
21914             country: "ID",
21915             groups: ["Q36117", "035", "142", "UN"],
21916             driveSide: "left",
21917             callingCodes: ["62"]
21918           },
21919           geometry: {
21920             type: "MultiPolygon",
21921             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]]]]
21922           }
21923         }, {
21924           type: "Feature",
21925           properties: {
21926             wikidata: "Q3803",
21927             nameEn: "Lesser Sunda Islands",
21928             aliases: ["ID-NU"],
21929             country: "ID",
21930             groups: ["035", "142", "UN"],
21931             driveSide: "left",
21932             callingCodes: ["62"]
21933           },
21934           geometry: {
21935             type: "MultiPolygon",
21936             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]]]]
21937           }
21938         }, {
21939           type: "Feature",
21940           properties: {
21941             wikidata: "Q3812",
21942             nameEn: "Sulawesi",
21943             aliases: ["ID-SL"],
21944             country: "ID",
21945             groups: ["035", "142", "UN"],
21946             driveSide: "left",
21947             callingCodes: ["62"]
21948           },
21949           geometry: {
21950             type: "MultiPolygon",
21951             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]]]]
21952           }
21953         }, {
21954           type: "Feature",
21955           properties: {
21956             wikidata: "Q3827",
21957             nameEn: "Maluku Islands",
21958             aliases: ["ID-ML"],
21959             country: "ID",
21960             groups: ["035", "142", "UN"],
21961             driveSide: "left",
21962             callingCodes: ["62"]
21963           },
21964           geometry: {
21965             type: "MultiPolygon",
21966             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]]]]
21967           }
21968         }, {
21969           type: "Feature",
21970           properties: {
21971             wikidata: "Q3845",
21972             nameEn: "Western New Guinea",
21973             aliases: ["ID-PP"],
21974             country: "ID",
21975             groups: ["035", "142", "UN"],
21976             driveSide: "left",
21977             callingCodes: ["62"]
21978           },
21979           geometry: {
21980             type: "MultiPolygon",
21981             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]]]]
21982           }
21983         }, {
21984           type: "Feature",
21985           properties: {
21986             wikidata: "Q5765",
21987             nameEn: "Balearic Islands",
21988             aliases: ["ES-IB"],
21989             country: "ES",
21990             groups: ["EU", "039", "150", "UN"],
21991             callingCodes: ["34 971"]
21992           },
21993           geometry: {
21994             type: "MultiPolygon",
21995             coordinates: [[[[-2.27707, 35.35051], [5.10072, 39.89531], [3.75438, 42.33445], [-2.27707, 35.35051]]]]
21996           }
21997         }, {
21998           type: "Feature",
21999           properties: {
22000             wikidata: "Q5823",
22001             nameEn: "Ceuta",
22002             aliases: ["ES-CE"],
22003             country: "ES",
22004             groups: ["EA", "EU", "015", "002", "UN"],
22005             level: "subterritory",
22006             callingCodes: ["34"]
22007           },
22008           geometry: {
22009             type: "MultiPolygon",
22010             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]]]]
22011           }
22012         }, {
22013           type: "Feature",
22014           properties: {
22015             wikidata: "Q5831",
22016             nameEn: "Melilla",
22017             aliases: ["ES-ML"],
22018             country: "ES",
22019             groups: ["EA", "EU", "015", "002", "UN"],
22020             level: "subterritory",
22021             callingCodes: ["34"]
22022           },
22023           geometry: {
22024             type: "MultiPolygon",
22025             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]]]]
22026           }
22027         }, {
22028           type: "Feature",
22029           properties: {
22030             wikidata: "Q7835",
22031             nameEn: "Crimea",
22032             country: "RU",
22033             groups: ["151", "150", "UN"],
22034             level: "subterritory",
22035             callingCodes: ["7"]
22036           },
22037           geometry: {
22038             type: "MultiPolygon",
22039             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]]]]
22040           }
22041         }, {
22042           type: "Feature",
22043           properties: {
22044             wikidata: "Q12837",
22045             nameEn: "Iberia",
22046             level: "sharedLandform"
22047           },
22048           geometry: null
22049         }, {
22050           type: "Feature",
22051           properties: {
22052             wikidata: "Q14056",
22053             nameEn: "Jan Mayen",
22054             aliases: ["NO-22"],
22055             country: "NO",
22056             groups: ["SJ", "154", "150", "UN"],
22057             level: "subterritory"
22058           },
22059           geometry: {
22060             type: "MultiPolygon",
22061             coordinates: [[[[-9.18243, 72.23144], [-10.71459, 70.09565], [-5.93364, 70.76368], [-9.18243, 72.23144]]]]
22062           }
22063         }, {
22064           type: "Feature",
22065           properties: {
22066             wikidata: "Q19188",
22067             nameEn: "Mainland China",
22068             country: "CN",
22069             groups: ["030", "142", "UN"],
22070             callingCodes: ["86"]
22071           },
22072           geometry: {
22073             type: "MultiPolygon",
22074             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]]]]
22075           }
22076         }, {
22077           type: "Feature",
22078           properties: {
22079             wikidata: "Q22890",
22080             nameEn: "Ireland",
22081             level: "sharedLandform"
22082           },
22083           geometry: null
22084         }, {
22085           type: "Feature",
22086           properties: {
22087             wikidata: "Q23666",
22088             nameEn: "Great Britain",
22089             country: "GB",
22090             level: "sharedLandform"
22091           },
22092           geometry: null
22093         }, {
22094           type: "Feature",
22095           properties: {
22096             wikidata: "Q23681",
22097             nameEn: "Northern Cyprus",
22098             groups: ["Q644636", "145", "142"],
22099             driveSide: "left",
22100             callingCodes: ["90 392"]
22101           },
22102           geometry: {
22103             type: "MultiPolygon",
22104             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]]]]
22105           }
22106         }, {
22107           type: "Feature",
22108           properties: {
22109             wikidata: "Q25231",
22110             nameEn: "Svalbard",
22111             aliases: ["NO-21"],
22112             country: "NO",
22113             groups: ["SJ", "154", "150", "UN"],
22114             level: "subterritory",
22115             callingCodes: ["47 79"]
22116           },
22117           geometry: {
22118             type: "MultiPolygon",
22119             coordinates: [[[[-7.49892, 77.24208], [32.07813, 72.01005], [36.85549, 84.09565], [-7.49892, 77.24208]]]]
22120           }
22121         }, {
22122           type: "Feature",
22123           properties: {
22124             wikidata: "Q25263",
22125             nameEn: "Azores",
22126             aliases: ["PT-20"],
22127             country: "PT",
22128             groups: ["Q3320166", "Q2914565", "Q105472", "EU", "039", "150", "UN"],
22129             callingCodes: ["351"]
22130           },
22131           geometry: {
22132             type: "MultiPolygon",
22133             coordinates: [[[[-23.12984, 40.26428], [-36.43765, 41.39418], [-22.54767, 33.34416], [-23.12984, 40.26428]]]]
22134           }
22135         }, {
22136           type: "Feature",
22137           properties: {
22138             wikidata: "Q25359",
22139             nameEn: "Navassa Island",
22140             aliases: ["UM-76"],
22141             country: "US",
22142             groups: ["UM", "Q1352230", "029", "003", "419", "019", "UN"],
22143             level: "subterritory",
22144             roadSpeedUnit: "mph",
22145             roadHeightUnit: "ft"
22146           },
22147           geometry: {
22148             type: "MultiPolygon",
22149             coordinates: [[[[-74.7289, 18.71009], [-75.71816, 18.46438], [-74.76465, 18.06252], [-74.7289, 18.71009]]]]
22150           }
22151         }, {
22152           type: "Feature",
22153           properties: {
22154             wikidata: "Q25396",
22155             nameEn: "Bonaire",
22156             aliases: ["BQ-BO", "NL-BQ1"],
22157             country: "NL",
22158             groups: ["Q1451600", "BQ", "029", "003", "419", "019", "UN"],
22159             level: "subterritory",
22160             callingCodes: ["599 7"]
22161           },
22162           geometry: {
22163             type: "MultiPolygon",
22164             coordinates: [[[[-67.89186, 12.4116], [-68.90012, 12.62309], [-68.33524, 11.78151], [-68.01417, 11.77722], [-67.89186, 12.4116]]]]
22165           }
22166         }, {
22167           type: "Feature",
22168           properties: {
22169             wikidata: "Q25528",
22170             nameEn: "Saba",
22171             aliases: ["BQ-SA", "NL-BQ2"],
22172             country: "NL",
22173             groups: ["Q1451600", "BQ", "029", "003", "419", "019", "UN"],
22174             level: "subterritory",
22175             callingCodes: ["599 4"]
22176           },
22177           geometry: {
22178             type: "MultiPolygon",
22179             coordinates: [[[[-63.07669, 17.79659], [-63.81314, 17.95045], [-63.22932, 17.32592], [-63.07669, 17.79659]]]]
22180           }
22181         }, {
22182           type: "Feature",
22183           properties: {
22184             wikidata: "Q26180",
22185             nameEn: "Sint Eustatius",
22186             aliases: ["BQ-SE", "NL-BQ3"],
22187             country: "NL",
22188             groups: ["Q1451600", "BQ", "029", "003", "419", "019", "UN"],
22189             level: "subterritory",
22190             callingCodes: ["599 3"]
22191           },
22192           geometry: {
22193             type: "MultiPolygon",
22194             coordinates: [[[[-63.07669, 17.79659], [-63.34999, 16.94218], [-62.76692, 17.64353], [-63.07669, 17.79659]]]]
22195           }
22196         }, {
22197           type: "Feature",
22198           properties: {
22199             wikidata: "Q26253",
22200             nameEn: "Madeira",
22201             aliases: ["PT-30"],
22202             country: "PT",
22203             groups: ["Q3320166", "Q2914565", "Q105472", "EU", "039", "150", "UN"],
22204             callingCodes: ["351"]
22205           },
22206           geometry: {
22207             type: "MultiPolygon",
22208             coordinates: [[[[-19.30302, 33.65304], [-16.04789, 29.65076], [-11.68307, 33.12333], [-19.30302, 33.65304]]]]
22209           }
22210         }, {
22211           type: "Feature",
22212           properties: {
22213             wikidata: "Q26927",
22214             nameEn: "Lakshadweep",
22215             aliases: ["IN-LD"],
22216             country: "IN",
22217             groups: ["034", "142", "UN"],
22218             driveSide: "left",
22219             callingCodes: ["91"]
22220           },
22221           geometry: {
22222             type: "MultiPolygon",
22223             coordinates: [[[[67.64074, 11.57295], [76.59015, 5.591], [72.67494, 13.58102], [67.64074, 11.57295]]]]
22224           }
22225         }, {
22226           type: "Feature",
22227           properties: {
22228             wikidata: "Q27329",
22229             nameEn: "Asian Russia",
22230             country: "RU",
22231             groups: ["142", "UN"],
22232             callingCodes: ["7"]
22233           },
22234           geometry: {
22235             type: "MultiPolygon",
22236             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]]]]
22237           }
22238         }, {
22239           type: "Feature",
22240           properties: {
22241             wikidata: "Q34366",
22242             nameEn: "Tasmania",
22243             aliases: ["AU-TAS"],
22244             country: "AU",
22245             groups: ["053", "009", "UN"],
22246             driveSide: "left",
22247             callingCodes: ["61"]
22248           },
22249           geometry: {
22250             type: "MultiPolygon",
22251             coordinates: [[[[123.64533, -39.13605], [159.69067, -56.28945], [159.74028, -39.1978], [123.64533, -39.13605]]]]
22252           }
22253         }, {
22254           type: "Feature",
22255           properties: {
22256             wikidata: "Q34497",
22257             nameEn: "Saint Helena",
22258             aliases: ["SH-HL"],
22259             country: "GB",
22260             groups: ["SH", "BOTS", "011", "202", "002", "UN"],
22261             level: "subterritory",
22262             driveSide: "left",
22263             roadSpeedUnit: "mph",
22264             roadHeightUnit: "ft",
22265             callingCodes: ["290"]
22266           },
22267           geometry: {
22268             type: "MultiPolygon",
22269             coordinates: [[[[-8.3824, -13.9131], [-6.17428, -19.07236], [-3.29308, -15.22647], [-8.3824, -13.9131]]]]
22270           }
22271         }, {
22272           type: "Feature",
22273           properties: {
22274             wikidata: "Q35657",
22275             nameEn: "US States",
22276             country: "US",
22277             level: "subcountryGroup"
22278           },
22279           geometry: null
22280         }, {
22281           type: "Feature",
22282           properties: {
22283             wikidata: "Q36117",
22284             nameEn: "Borneo",
22285             level: "sharedLandform"
22286           },
22287           geometry: null
22288         }, {
22289           type: "Feature",
22290           properties: {
22291             wikidata: "Q36678",
22292             nameEn: "West Bank",
22293             country: "PS",
22294             groups: ["145", "142"],
22295             callingCodes: ["970"]
22296           },
22297           geometry: {
22298             type: "MultiPolygon",
22299             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]]]]
22300           }
22301         }, {
22302           type: "Feature",
22303           properties: {
22304             wikidata: "Q37362",
22305             nameEn: "Akrotiri and Dhekelia",
22306             aliases: ["SBA"],
22307             country: "GB"
22308           },
22309           geometry: null
22310         }, {
22311           type: "Feature",
22312           properties: {
22313             wikidata: "Q38095",
22314             nameEn: "Gal\xE1pagos Islands",
22315             aliases: ["EC-W"],
22316             country: "EC",
22317             groups: ["005", "419", "019", "UN"],
22318             callingCodes: ["593"]
22319           },
22320           geometry: {
22321             type: "MultiPolygon",
22322             coordinates: [[[[-93.12365, 2.64343], [-92.46744, -2.52874], [-87.07749, -0.8849], [-93.12365, 2.64343]]]]
22323           }
22324         }, {
22325           type: "Feature",
22326           properties: {
22327             wikidata: "Q39760",
22328             nameEn: "Gaza Strip",
22329             country: "PS",
22330             groups: ["145", "142"],
22331             callingCodes: ["970"]
22332           },
22333           geometry: {
22334             type: "MultiPolygon",
22335             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]]]]
22336           }
22337         }, {
22338           type: "Feature",
22339           properties: {
22340             wikidata: "Q40888",
22341             nameEn: "Andaman and Nicobar Islands",
22342             aliases: ["IN-AN"],
22343             country: "IN",
22344             groups: ["034", "142", "UN"],
22345             driveSide: "left",
22346             callingCodes: ["91"]
22347           },
22348           geometry: {
22349             type: "MultiPolygon",
22350             coordinates: [[[[94.42132, 5.96581], [94.6371, 13.81803], [86.7822, 13.41052], [94.42132, 5.96581]]]]
22351           }
22352         }, {
22353           type: "Feature",
22354           properties: {
22355             wikidata: "Q41684",
22356             nameEn: "Stewart Island",
22357             country: "NZ",
22358             groups: ["053", "009", "UN"],
22359             driveSide: "left",
22360             callingCodes: ["64"]
22361           },
22362           geometry: {
22363             type: "MultiPolygon",
22364             coordinates: [[[[166.59185, -47.61313], [169.70504, -47.56021], [167.52103, -46.41337], [166.59185, -47.61313]]]]
22365           }
22366         }, {
22367           type: "Feature",
22368           properties: {
22369             wikidata: "Q43296",
22370             nameEn: "Wake Island",
22371             aliases: ["WK", "WAK", "WKUM", "872", "UM-79"],
22372             country: "US",
22373             groups: ["UM", "Q1352230", "057", "009", "UN"],
22374             level: "subterritory",
22375             roadSpeedUnit: "mph",
22376             roadHeightUnit: "ft",
22377             callingCodes: ["1"]
22378           },
22379           geometry: {
22380             type: "MultiPolygon",
22381             coordinates: [[[[167.34779, 18.97692], [166.67967, 20.14834], [165.82549, 18.97692], [167.34779, 18.97692]]]]
22382           }
22383         }, {
22384           type: "Feature",
22385           properties: {
22386             wikidata: "Q46275",
22387             nameEn: "New Zealand Subantarctic Islands",
22388             country: "NZ",
22389             groups: ["Q851132", "053", "009", "UN"],
22390             driveSide: "left"
22391           },
22392           geometry: {
22393             type: "MultiPolygon",
22394             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]]]]
22395           }
22396         }, {
22397           type: "Feature",
22398           properties: {
22399             wikidata: "Q46395",
22400             nameEn: "British Overseas Territories",
22401             aliases: ["BOTS", "UKOTS"],
22402             country: "GB",
22403             level: "subcountryGroup"
22404           },
22405           geometry: null
22406         }, {
22407           type: "Feature",
22408           properties: {
22409             wikidata: "Q46772",
22410             nameEn: "Kerguelen Islands",
22411             country: "FR",
22412             groups: ["TF", "Q1451600", "014", "202", "002", "UN"],
22413             level: "subterritory"
22414           },
22415           geometry: {
22416             type: "MultiPolygon",
22417             coordinates: [[[[61.9216, -49.39746], [70.67507, -51.14192], [74.25129, -45.45074], [61.9216, -49.39746]]]]
22418           }
22419         }, {
22420           type: "Feature",
22421           properties: {
22422             wikidata: "Q46879",
22423             nameEn: "Baker Island",
22424             aliases: ["UM-81"],
22425             country: "US",
22426             groups: ["UM", "Q1352230", "061", "009", "UN"],
22427             level: "subterritory",
22428             roadSpeedUnit: "mph",
22429             roadHeightUnit: "ft"
22430           },
22431           geometry: {
22432             type: "MultiPolygon",
22433             coordinates: [[[[-175.33482, -1.40631], [-175.31323, 0.5442], [-177.91421, 0.39582], [-175.33482, -1.40631]]]]
22434           }
22435         }, {
22436           type: "Feature",
22437           properties: {
22438             wikidata: "Q47863",
22439             nameEn: "Midway Atoll",
22440             aliases: ["MI", "MID", "MIUM", "488", "UM-71"],
22441             country: "US",
22442             groups: ["UM", "Q1352230", "061", "009", "UN"],
22443             level: "subterritory",
22444             roadSpeedUnit: "mph",
22445             roadHeightUnit: "ft",
22446             callingCodes: ["1"]
22447           },
22448           geometry: {
22449             type: "MultiPolygon",
22450             coordinates: [[[[-176.29741, 29.09786], [-177.77531, 29.29793], [-177.5224, 27.7635], [-176.29741, 29.09786]]]]
22451           }
22452         }, {
22453           type: "Feature",
22454           properties: {
22455             wikidata: "Q62218",
22456             nameEn: "Jarvis Island",
22457             aliases: ["UM-86"],
22458             country: "US",
22459             groups: ["UM", "Q1352230", "061", "009", "UN"],
22460             level: "subterritory",
22461             roadSpeedUnit: "mph",
22462             roadHeightUnit: "ft"
22463           },
22464           geometry: {
22465             type: "MultiPolygon",
22466             coordinates: [[[[-160.42921, -1.4364], [-159.12443, 0.19975], [-160.38779, 0.30331], [-160.42921, -1.4364]]]]
22467           }
22468         }, {
22469           type: "Feature",
22470           properties: {
22471             wikidata: "Q105472",
22472             nameEn: "Macaronesia",
22473             level: "sharedLandform"
22474           },
22475           geometry: null
22476         }, {
22477           type: "Feature",
22478           properties: {
22479             wikidata: "Q114935",
22480             nameEn: "Kermadec Islands",
22481             country: "NZ",
22482             groups: ["Q851132", "053", "009", "UN"],
22483             driveSide: "left",
22484             callingCodes: ["64"]
22485           },
22486           geometry: {
22487             type: "MultiPolygon",
22488             coordinates: [[[[-174.40891, -29.09438], [-180, -24.21376], [-179.96512, -35.00791], [-174.40891, -29.09438]]]]
22489           }
22490         }, {
22491           type: "Feature",
22492           properties: {
22493             wikidata: "Q115459",
22494             nameEn: "Chatham Islands",
22495             aliases: ["NZ-CIT"],
22496             country: "NZ",
22497             groups: ["Q851132", "053", "009", "UN"],
22498             driveSide: "left",
22499             callingCodes: ["64"]
22500           },
22501           geometry: {
22502             type: "MultiPolygon",
22503             coordinates: [[[[-179.93224, -45.18423], [-172.47015, -45.17912], [-176.30998, -41.38382], [-179.93224, -45.18423]]]]
22504           }
22505         }, {
22506           type: "Feature",
22507           properties: {
22508             wikidata: "Q118863",
22509             nameEn: "North Island",
22510             country: "NZ",
22511             groups: ["053", "009", "UN"],
22512             driveSide: "left",
22513             callingCodes: ["64"]
22514           },
22515           geometry: {
22516             type: "MultiPolygon",
22517             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]]]]
22518           }
22519         }, {
22520           type: "Feature",
22521           properties: {
22522             wikidata: "Q120755",
22523             nameEn: "South Island",
22524             country: "NZ",
22525             groups: ["053", "009", "UN"],
22526             driveSide: "left",
22527             callingCodes: ["64"]
22528           },
22529           geometry: {
22530             type: "MultiPolygon",
22531             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]]]]
22532           }
22533         }, {
22534           type: "Feature",
22535           properties: {
22536             wikidata: "Q123076",
22537             nameEn: "Palmyra Atoll",
22538             aliases: ["UM-95"],
22539             country: "US",
22540             groups: ["UM", "Q1352230", "061", "009", "UN"],
22541             level: "subterritory",
22542             roadSpeedUnit: "mph",
22543             roadHeightUnit: "ft",
22544             callingCodes: ["1"]
22545           },
22546           geometry: {
22547             type: "MultiPolygon",
22548             coordinates: [[[[-161.06795, 5.2462], [-161.0731, 7.1291], [-163.24478, 5.24198], [-161.06795, 5.2462]]]]
22549           }
22550         }, {
22551           type: "Feature",
22552           properties: {
22553             wikidata: "Q130574",
22554             nameEn: "Chafarinas Islands",
22555             country: "ES",
22556             groups: ["EU", "Q191011", "015", "002", "UN"],
22557             level: "subterritory"
22558           },
22559           geometry: {
22560             type: "MultiPolygon",
22561             coordinates: [[[[-2.40316, 35.16893], [-2.43262, 35.20652], [-2.45965, 35.16527], [-2.40316, 35.16893]]]]
22562           }
22563         }, {
22564           type: "Feature",
22565           properties: {
22566             wikidata: "Q130895",
22567             nameEn: "Kingman Reef",
22568             aliases: ["UM-89"],
22569             country: "US",
22570             groups: ["UM", "Q1352230", "061", "009", "UN"],
22571             level: "subterritory",
22572             roadSpeedUnit: "mph",
22573             roadHeightUnit: "ft"
22574           },
22575           geometry: {
22576             type: "MultiPolygon",
22577             coordinates: [[[[-161.0731, 7.1291], [-163.16627, 7.15036], [-163.24478, 5.24198], [-161.0731, 7.1291]]]]
22578           }
22579         }, {
22580           type: "Feature",
22581           properties: {
22582             wikidata: "Q131008",
22583             nameEn: "Johnston Atoll",
22584             aliases: ["JT", "JTN", "JTUM", "396", "UM-67"],
22585             country: "US",
22586             groups: ["UM", "Q1352230", "061", "009", "UN"],
22587             level: "subterritory",
22588             roadSpeedUnit: "mph",
22589             roadHeightUnit: "ft",
22590             callingCodes: ["1"]
22591           },
22592           geometry: {
22593             type: "MultiPolygon",
22594             coordinates: [[[[-170.65691, 16.57199], [-168.87689, 16.01159], [-169.2329, 17.4933], [-170.65691, 16.57199]]]]
22595           }
22596         }, {
22597           type: "Feature",
22598           properties: {
22599             wikidata: "Q131305",
22600             nameEn: "Howland Island",
22601             aliases: ["UM-84"],
22602             country: "US",
22603             groups: ["UM", "Q1352230", "061", "009", "UN"],
22604             level: "subterritory",
22605             roadSpeedUnit: "mph",
22606             roadHeightUnit: "ft"
22607           },
22608           geometry: {
22609             type: "MultiPolygon",
22610             coordinates: [[[[-177.91421, 0.39582], [-175.31323, 0.5442], [-176.74464, 2.28109], [-177.91421, 0.39582]]]]
22611           }
22612         }, {
22613           type: "Feature",
22614           properties: {
22615             wikidata: "Q133888",
22616             nameEn: "Ashmore and Cartier Islands",
22617             country: "AU",
22618             groups: ["053", "009", "UN"],
22619             driveSide: "left",
22620             callingCodes: ["61"]
22621           },
22622           geometry: {
22623             type: "MultiPolygon",
22624             coordinates: [[[[123.7463, -11.1783], [120.6877, -13.59408], [125.29076, -12.33139], [123.7463, -11.1783]]]]
22625           }
22626         }, {
22627           type: "Feature",
22628           properties: {
22629             wikidata: "Q153732",
22630             nameEn: "Mariana Islands",
22631             level: "sharedLandform"
22632           },
22633           geometry: null
22634         }, {
22635           type: "Feature",
22636           properties: {
22637             wikidata: "Q172216",
22638             nameEn: "Coral Sea Islands",
22639             country: "AU",
22640             groups: ["053", "009", "UN"],
22641             driveSide: "left",
22642             callingCodes: ["61"]
22643           },
22644           geometry: {
22645             type: "MultiPolygon",
22646             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]]]]
22647           }
22648         }, {
22649           type: "Feature",
22650           properties: {
22651             wikidata: "Q179313",
22652             nameEn: "Alderney",
22653             country: "GB",
22654             groups: ["GG", "830", "Q185086", "154", "150", "UN"],
22655             level: "subterritory",
22656             driveSide: "left",
22657             roadSpeedUnit: "mph",
22658             roadHeightUnit: "ft",
22659             callingCodes: ["44 01481"]
22660           },
22661           geometry: {
22662             type: "MultiPolygon",
22663             coordinates: [[[[-2.36485, 49.48223], [-2.09454, 49.46288], [-2.02963, 49.91866], [-2.49556, 49.79012], [-2.36485, 49.48223]]]]
22664           }
22665         }, {
22666           type: "Feature",
22667           properties: {
22668             wikidata: "Q185086",
22669             nameEn: "Crown Dependencies",
22670             country: "GB",
22671             level: "subcountryGroup"
22672           },
22673           geometry: null
22674         }, {
22675           type: "Feature",
22676           properties: {
22677             wikidata: "Q190571",
22678             nameEn: "Scattered Islands",
22679             country: "FR",
22680             groups: ["TF", "Q1451600", "014", "202", "002", "UN"],
22681             level: "subterritory"
22682           },
22683           geometry: {
22684             type: "MultiPolygon",
22685             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]]]]
22686           }
22687         }, {
22688           type: "Feature",
22689           properties: {
22690             wikidata: "Q191011",
22691             nameEn: "Plazas de soberan\xEDa",
22692             country: "ES"
22693           },
22694           geometry: null
22695         }, {
22696           type: "Feature",
22697           properties: {
22698             wikidata: "Q191146",
22699             nameEn: "Pe\xF1\xF3n de V\xE9lez de la Gomera",
22700             country: "ES",
22701             groups: ["EU", "Q191011", "015", "002", "UN"],
22702             level: "subterritory"
22703           },
22704           geometry: {
22705             type: "MultiPolygon",
22706             coordinates: [[[[-4.30191, 35.17419], [-4.30112, 35.17058], [-4.29436, 35.17149], [-4.30191, 35.17419]]]]
22707           }
22708         }, {
22709           type: "Feature",
22710           properties: {
22711             wikidata: "Q201698",
22712             nameEn: "Crozet Islands",
22713             country: "FR",
22714             groups: ["TF", "Q1451600", "014", "202", "002", "UN"],
22715             level: "subterritory"
22716           },
22717           geometry: {
22718             type: "MultiPolygon",
22719             coordinates: [[[[55.03425, -43.65017], [46.31615, -46.28749], [54.5587, -47.93013], [55.03425, -43.65017]]]]
22720           }
22721         }, {
22722           type: "Feature",
22723           properties: {
22724             wikidata: "Q578170",
22725             nameEn: "Contiguous United States",
22726             aliases: ["CONUS"],
22727             country: "US",
22728             groups: ["Q35657", "021", "003", "019", "UN"],
22729             roadSpeedUnit: "mph",
22730             roadHeightUnit: "ft",
22731             callingCodes: ["1"]
22732           },
22733           geometry: {
22734             type: "MultiPolygon",
22735             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]]]]
22736           }
22737         }, {
22738           type: "Feature",
22739           properties: {
22740             wikidata: "Q620634",
22741             nameEn: "Bir Tawil",
22742             groups: ["015", "002"],
22743             level: "territory"
22744           },
22745           geometry: {
22746             type: "MultiPolygon",
22747             coordinates: [[[[33.17563, 22.00405], [33.57251, 21.72406], [33.99686, 21.76784], [34.0765, 22.00501], [33.17563, 22.00405]]]]
22748           }
22749         }, {
22750           type: "Feature",
22751           properties: {
22752             wikidata: "Q639185",
22753             nameEn: "Peros Banhos",
22754             country: "GB",
22755             groups: ["IO", "BOTS", "014", "202", "002", "UN"],
22756             level: "subterritory"
22757           },
22758           geometry: {
22759             type: "MultiPolygon",
22760             coordinates: [[[[72.12587, -4.02588], [70.1848, -6.37445], [72.09518, -5.61768], [72.12587, -4.02588]]]]
22761           }
22762         }, {
22763           type: "Feature",
22764           properties: {
22765             wikidata: "Q644636",
22766             nameEn: "Cyprus",
22767             level: "sharedLandform"
22768           },
22769           geometry: null
22770         }, {
22771           type: "Feature",
22772           properties: {
22773             wikidata: "Q851132",
22774             nameEn: "New Zealand Outlying Islands",
22775             country: "NZ",
22776             level: "subcountryGroup"
22777           },
22778           geometry: null
22779         }, {
22780           type: "Feature",
22781           properties: {
22782             wikidata: "Q875134",
22783             nameEn: "European Russia",
22784             country: "RU",
22785             groups: ["151", "150", "UN"],
22786             callingCodes: ["7"]
22787           },
22788           geometry: {
22789             type: "MultiPolygon",
22790             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]]]]
22791           }
22792         }, {
22793           type: "Feature",
22794           properties: {
22795             wikidata: "Q1083368",
22796             nameEn: "Mainland Finland",
22797             country: "FI",
22798             groups: ["EU", "154", "150", "UN"],
22799             callingCodes: ["358"]
22800           },
22801           geometry: {
22802             type: "MultiPolygon",
22803             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]]]]
22804           }
22805         }, {
22806           type: "Feature",
22807           properties: {
22808             wikidata: "Q1184963",
22809             nameEn: "Alhucemas Islands",
22810             country: "ES",
22811             groups: ["EU", "Q191011", "015", "002", "UN"],
22812             level: "subterritory"
22813           },
22814           geometry: {
22815             type: "MultiPolygon",
22816             coordinates: [[[[-3.90602, 35.21494], [-3.88372, 35.20767], [-3.89343, 35.22728], [-3.90602, 35.21494]]]]
22817           }
22818         }, {
22819           type: "Feature",
22820           properties: {
22821             wikidata: "Q1298289",
22822             nameEn: "Egmont Islands",
22823             country: "GB",
22824             groups: ["IO", "BOTS", "014", "202", "002", "UN"],
22825             level: "subterritory"
22826           },
22827           geometry: {
22828             type: "MultiPolygon",
22829             coordinates: [[[[70.1848, -6.37445], [70.67958, -8.2663], [72.17991, -6.68509], [70.1848, -6.37445]]]]
22830           }
22831         }, {
22832           type: "Feature",
22833           properties: {
22834             wikidata: "Q1352230",
22835             nameEn: "US Territories",
22836             country: "US",
22837             level: "subcountryGroup"
22838           },
22839           geometry: null
22840         }, {
22841           type: "Feature",
22842           properties: {
22843             wikidata: "Q1451600",
22844             nameEn: "Overseas Countries and Territories of the EU",
22845             aliases: ["OCT"],
22846             level: "subunion"
22847           },
22848           geometry: null
22849         }, {
22850           type: "Feature",
22851           properties: {
22852             wikidata: "Q1544253",
22853             nameEn: "Great Chagos Bank",
22854             country: "GB",
22855             groups: ["IO", "BOTS", "014", "202", "002", "UN"],
22856             level: "subterritory"
22857           },
22858           geometry: {
22859             type: "MultiPolygon",
22860             coordinates: [[[[70.1848, -6.37445], [72.17991, -6.68509], [73.20573, -5.20727], [70.1848, -6.37445]]]]
22861           }
22862         }, {
22863           type: "Feature",
22864           properties: {
22865             wikidata: "Q1585511",
22866             nameEn: "Salomon Atoll",
22867             country: "GB",
22868             groups: ["IO", "BOTS", "014", "202", "002", "UN"],
22869             level: "subterritory"
22870           },
22871           geometry: {
22872             type: "MultiPolygon",
22873             coordinates: [[[[72.09518, -5.61768], [73.20573, -5.20727], [72.12587, -4.02588], [72.09518, -5.61768]]]]
22874           }
22875         }, {
22876           type: "Feature",
22877           properties: {
22878             wikidata: "Q1681727",
22879             nameEn: "Saint-Paul and Amsterdam",
22880             country: "FR",
22881             groups: ["TF", "Q1451600", "014", "202", "002", "UN"],
22882             level: "subterritory"
22883           },
22884           geometry: {
22885             type: "MultiPolygon",
22886             coordinates: [[[[76.31747, -42.16264], [80.15867, -36.04977], [71.22311, -38.75287], [76.31747, -42.16264]]]]
22887           }
22888         }, {
22889           type: "Feature",
22890           properties: {
22891             wikidata: "Q1901211",
22892             nameEn: "East Malaysia",
22893             country: "MY",
22894             groups: ["Q36117", "035", "142", "UN"],
22895             driveSide: "left",
22896             callingCodes: ["60"]
22897           },
22898           geometry: {
22899             type: "MultiPolygon",
22900             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]]]]
22901           }
22902         }, {
22903           type: "Feature",
22904           properties: {
22905             wikidata: "Q1973345",
22906             nameEn: "Peninsular Malaysia",
22907             country: "MY",
22908             groups: ["035", "142", "UN"],
22909             driveSide: "left",
22910             callingCodes: ["60"]
22911           },
22912           geometry: {
22913             type: "MultiPolygon",
22914             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]]]]
22915           }
22916         }, {
22917           type: "Feature",
22918           properties: {
22919             wikidata: "Q2093907",
22920             nameEn: "Three Kings Islands",
22921             country: "NZ",
22922             groups: ["Q851132", "053", "009", "UN"],
22923             driveSide: "left"
22924           },
22925           geometry: {
22926             type: "MultiPolygon",
22927             coordinates: [[[[174.17679, -32.62487], [170.93268, -32.97889], [171.97383, -34.64644], [174.17679, -32.62487]]]]
22928           }
22929         }, {
22930           type: "Feature",
22931           properties: {
22932             wikidata: "Q2298216",
22933             nameEn: "Solander Islands",
22934             country: "NZ",
22935             groups: ["Q851132", "053", "009", "UN"],
22936             driveSide: "left"
22937           },
22938           geometry: {
22939             type: "MultiPolygon",
22940             coordinates: [[[[167.39068, -46.49187], [166.5534, -46.39484], [166.84561, -46.84889], [167.39068, -46.49187]]]]
22941           }
22942         }, {
22943           type: "Feature",
22944           properties: {
22945             wikidata: "Q2872203",
22946             nameEn: "Mainland Australia",
22947             country: "AU",
22948             groups: ["053", "009", "UN"],
22949             level: "subcountryGroup",
22950             driveSide: "left",
22951             callingCodes: ["61"]
22952           },
22953           geometry: {
22954             type: "MultiPolygon",
22955             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]]]]
22956           }
22957         }, {
22958           type: "Feature",
22959           properties: {
22960             wikidata: "Q2914565",
22961             nameEn: "Autonomous Regions of Portugal",
22962             country: "PT",
22963             level: "subcountryGroup"
22964           },
22965           geometry: null
22966         }, {
22967           type: "Feature",
22968           properties: {
22969             wikidata: "Q2915956",
22970             nameEn: "Mainland Portugal",
22971             country: "PT",
22972             groups: ["Q12837", "EU", "039", "150", "UN"],
22973             level: "subcountryGroup",
22974             callingCodes: ["351"]
22975           },
22976           geometry: {
22977             type: "MultiPolygon",
22978             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]]]]
22979           }
22980         }, {
22981           type: "Feature",
22982           properties: {
22983             wikidata: "Q3311985",
22984             nameEn: "Guernsey",
22985             country: "GB",
22986             groups: ["GG", "830", "Q185086", "154", "150", "UN"],
22987             level: "subterritory",
22988             driveSide: "left",
22989             roadSpeedUnit: "mph",
22990             roadHeightUnit: "ft",
22991             callingCodes: ["44 01481"]
22992           },
22993           geometry: {
22994             type: "MultiPolygon",
22995             coordinates: [[[[-2.49556, 49.79012], [-3.28154, 49.57329], [-2.65349, 49.15373], [-2.36485, 49.48223], [-2.49556, 49.79012]]]]
22996           }
22997         }, {
22998           type: "Feature",
22999           properties: {
23000             wikidata: "Q3320166",
23001             nameEn: "Outermost Regions of the EU",
23002             aliases: ["OMR"],
23003             level: "subunion"
23004           },
23005           geometry: null
23006         }, {
23007           type: "Feature",
23008           properties: {
23009             wikidata: "Q3336843",
23010             nameEn: "Countries of the United Kingdom",
23011             country: "GB",
23012             level: "subcountryGroup"
23013           },
23014           geometry: null
23015         }, {
23016           type: "Feature",
23017           properties: {
23018             wikidata: "Q6736667",
23019             nameEn: "Mainland India",
23020             country: "IN",
23021             groups: ["034", "142", "UN"],
23022             driveSide: "left",
23023             callingCodes: ["91"]
23024           },
23025           geometry: {
23026             type: "MultiPolygon",
23027             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]]]]
23028           }
23029         }, {
23030           type: "Feature",
23031           properties: {
23032             wikidata: "Q9143535",
23033             nameEn: "Akrotiri",
23034             country: "GB",
23035             groups: ["Q644636", "Q37362", "BOTS", "145", "142", "UN"],
23036             level: "subterritory",
23037             driveSide: "left",
23038             callingCodes: ["357"]
23039           },
23040           geometry: {
23041             type: "MultiPolygon",
23042             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]]]]
23043           }
23044         }, {
23045           type: "Feature",
23046           properties: {
23047             wikidata: "Q9206745",
23048             nameEn: "Dhekelia",
23049             country: "GB",
23050             groups: ["Q644636", "Q37362", "BOTS", "145", "142", "UN"],
23051             level: "subterritory",
23052             driveSide: "left",
23053             callingCodes: ["357"]
23054           },
23055           geometry: {
23056             type: "MultiPolygon",
23057             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]]]]
23058           }
23059         }, {
23060           type: "Feature",
23061           properties: {
23062             wikidata: "Q16390686",
23063             nameEn: "Peninsular Spain",
23064             country: "ES",
23065             groups: ["Q12837", "EU", "039", "150", "UN"],
23066             callingCodes: ["34"]
23067           },
23068           geometry: {
23069             type: "MultiPolygon",
23070             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]]]]
23071           }
23072         }, {
23073           type: "Feature",
23074           properties: {
23075             wikidata: "Q98059339",
23076             nameEn: "Mainland Norway",
23077             country: "NO",
23078             groups: ["154", "150", "UN"],
23079             callingCodes: ["47"]
23080           },
23081           geometry: {
23082             type: "MultiPolygon",
23083             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]]]]
23084           }
23085         }, {
23086           type: "Feature",
23087           properties: {
23088             wikidata: "Q98543636",
23089             nameEn: "Mainland Ecuador",
23090             country: "EC",
23091             groups: ["005", "419", "019", "UN"],
23092             callingCodes: ["593"]
23093           },
23094           geometry: {
23095             type: "MultiPolygon",
23096             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]]]]
23097           }
23098         }, {
23099           type: "Feature",
23100           properties: {
23101             m49: "001",
23102             wikidata: "Q2",
23103             nameEn: "World",
23104             aliases: ["Earth", "Planet"],
23105             level: "world"
23106           },
23107           geometry: null
23108         }, {
23109           type: "Feature",
23110           properties: {
23111             m49: "002",
23112             wikidata: "Q15",
23113             nameEn: "Africa",
23114             level: "region"
23115           },
23116           geometry: null
23117         }, {
23118           type: "Feature",
23119           properties: {
23120             m49: "003",
23121             wikidata: "Q49",
23122             nameEn: "North America",
23123             level: "subregion"
23124           },
23125           geometry: null
23126         }, {
23127           type: "Feature",
23128           properties: {
23129             m49: "005",
23130             wikidata: "Q18",
23131             nameEn: "South America",
23132             level: "intermediateRegion"
23133           },
23134           geometry: null
23135         }, {
23136           type: "Feature",
23137           properties: {
23138             m49: "009",
23139             wikidata: "Q538",
23140             nameEn: "Oceania",
23141             level: "region"
23142           },
23143           geometry: null
23144         }, {
23145           type: "Feature",
23146           properties: {
23147             m49: "011",
23148             wikidata: "Q4412",
23149             nameEn: "Western Africa",
23150             level: "intermediateRegion"
23151           },
23152           geometry: null
23153         }, {
23154           type: "Feature",
23155           properties: {
23156             m49: "013",
23157             wikidata: "Q27611",
23158             nameEn: "Central America",
23159             level: "intermediateRegion"
23160           },
23161           geometry: null
23162         }, {
23163           type: "Feature",
23164           properties: {
23165             m49: "014",
23166             wikidata: "Q27407",
23167             nameEn: "Eastern Africa",
23168             level: "intermediateRegion"
23169           },
23170           geometry: null
23171         }, {
23172           type: "Feature",
23173           properties: {
23174             m49: "015",
23175             wikidata: "Q27381",
23176             nameEn: "Northern Africa",
23177             level: "subregion"
23178           },
23179           geometry: null
23180         }, {
23181           type: "Feature",
23182           properties: {
23183             m49: "017",
23184             wikidata: "Q27433",
23185             nameEn: "Middle Africa",
23186             level: "intermediateRegion"
23187           },
23188           geometry: null
23189         }, {
23190           type: "Feature",
23191           properties: {
23192             m49: "018",
23193             wikidata: "Q27394",
23194             nameEn: "Southern Africa",
23195             level: "intermediateRegion"
23196           },
23197           geometry: null
23198         }, {
23199           type: "Feature",
23200           properties: {
23201             m49: "019",
23202             wikidata: "Q828",
23203             nameEn: "Americas",
23204             level: "region"
23205           },
23206           geometry: null
23207         }, {
23208           type: "Feature",
23209           properties: {
23210             m49: "021",
23211             wikidata: "Q2017699",
23212             nameEn: "Northern America",
23213             level: "subregion"
23214           },
23215           geometry: null
23216         }, {
23217           type: "Feature",
23218           properties: {
23219             m49: "029",
23220             wikidata: "Q664609",
23221             nameEn: "Caribbean",
23222             level: "intermediateRegion"
23223           },
23224           geometry: null
23225         }, {
23226           type: "Feature",
23227           properties: {
23228             m49: "030",
23229             wikidata: "Q27231",
23230             nameEn: "Eastern Asia",
23231             level: "subregion"
23232           },
23233           geometry: null
23234         }, {
23235           type: "Feature",
23236           properties: {
23237             m49: "034",
23238             wikidata: "Q771405",
23239             nameEn: "Southern Asia",
23240             level: "subregion"
23241           },
23242           geometry: null
23243         }, {
23244           type: "Feature",
23245           properties: {
23246             m49: "035",
23247             wikidata: "Q11708",
23248             nameEn: "South-eastern Asia",
23249             level: "subregion"
23250           },
23251           geometry: null
23252         }, {
23253           type: "Feature",
23254           properties: {
23255             m49: "039",
23256             wikidata: "Q27449",
23257             nameEn: "Southern Europe",
23258             level: "subregion"
23259           },
23260           geometry: null
23261         }, {
23262           type: "Feature",
23263           properties: {
23264             m49: "053",
23265             wikidata: "Q45256",
23266             nameEn: "Australia and New Zealand",
23267             aliases: ["Australasia"],
23268             level: "subregion"
23269           },
23270           geometry: null
23271         }, {
23272           type: "Feature",
23273           properties: {
23274             m49: "054",
23275             wikidata: "Q37394",
23276             nameEn: "Melanesia",
23277             level: "subregion"
23278           },
23279           geometry: null
23280         }, {
23281           type: "Feature",
23282           properties: {
23283             m49: "057",
23284             wikidata: "Q3359409",
23285             nameEn: "Micronesia",
23286             level: "subregion"
23287           },
23288           geometry: null
23289         }, {
23290           type: "Feature",
23291           properties: {
23292             m49: "061",
23293             wikidata: "Q35942",
23294             nameEn: "Polynesia",
23295             level: "subregion"
23296           },
23297           geometry: null
23298         }, {
23299           type: "Feature",
23300           properties: {
23301             m49: "142",
23302             wikidata: "Q48",
23303             nameEn: "Asia",
23304             level: "region"
23305           },
23306           geometry: null
23307         }, {
23308           type: "Feature",
23309           properties: {
23310             m49: "143",
23311             wikidata: "Q27275",
23312             nameEn: "Central Asia",
23313             level: "subregion"
23314           },
23315           geometry: null
23316         }, {
23317           type: "Feature",
23318           properties: {
23319             m49: "145",
23320             wikidata: "Q27293",
23321             nameEn: "Western Asia",
23322             level: "subregion"
23323           },
23324           geometry: null
23325         }, {
23326           type: "Feature",
23327           properties: {
23328             m49: "150",
23329             wikidata: "Q46",
23330             nameEn: "Europe",
23331             level: "region"
23332           },
23333           geometry: null
23334         }, {
23335           type: "Feature",
23336           properties: {
23337             m49: "151",
23338             wikidata: "Q27468",
23339             nameEn: "Eastern Europe",
23340             level: "subregion"
23341           },
23342           geometry: null
23343         }, {
23344           type: "Feature",
23345           properties: {
23346             m49: "154",
23347             wikidata: "Q27479",
23348             nameEn: "Northern Europe",
23349             level: "subregion"
23350           },
23351           geometry: null
23352         }, {
23353           type: "Feature",
23354           properties: {
23355             m49: "155",
23356             wikidata: "Q27496",
23357             nameEn: "Western Europe",
23358             level: "subregion"
23359           },
23360           geometry: null
23361         }, {
23362           type: "Feature",
23363           properties: {
23364             m49: "202",
23365             wikidata: "Q132959",
23366             nameEn: "Sub-Saharan Africa",
23367             level: "subregion"
23368           },
23369           geometry: null
23370         }, {
23371           type: "Feature",
23372           properties: {
23373             m49: "419",
23374             wikidata: "Q72829598",
23375             nameEn: "Latin America and the Caribbean",
23376             level: "subregion"
23377           },
23378           geometry: null
23379         }, {
23380           type: "Feature",
23381           properties: {
23382             m49: "680",
23383             wikidata: "Q3405693",
23384             nameEn: "Sark",
23385             country: "GB",
23386             groups: ["GG", "830", "Q185086", "154", "150", "UN"],
23387             level: "subterritory",
23388             driveSide: "left",
23389             roadSpeedUnit: "mph",
23390             roadHeightUnit: "ft",
23391             callingCodes: ["44 01481"]
23392           },
23393           geometry: {
23394             type: "MultiPolygon",
23395             coordinates: [[[[-2.36485, 49.48223], [-2.65349, 49.15373], [-2.09454, 49.46288], [-2.36485, 49.48223]]]]
23396           }
23397         }, {
23398           type: "Feature",
23399           properties: {
23400             m49: "830",
23401             wikidata: "Q42314",
23402             nameEn: "Channel Islands",
23403             level: "intermediateRegion"
23404           },
23405           geometry: null
23406         }, {
23407           type: "Feature",
23408           properties: {
23409             iso1A2: "AC",
23410             iso1A3: "ASC",
23411             wikidata: "Q46197",
23412             nameEn: "Ascension Island",
23413             aliases: ["SH-AC"],
23414             country: "GB",
23415             groups: ["SH", "BOTS", "011", "202", "002", "UN"],
23416             isoStatus: "excRes",
23417             driveSide: "left",
23418             roadSpeedUnit: "mph",
23419             roadHeightUnit: "ft",
23420             callingCodes: ["247"]
23421           },
23422           geometry: {
23423             type: "MultiPolygon",
23424             coordinates: [[[[-14.82771, -8.70814], [-13.33271, -8.07391], [-14.91926, -6.63386], [-14.82771, -8.70814]]]]
23425           }
23426         }, {
23427           type: "Feature",
23428           properties: {
23429             iso1A2: "AD",
23430             iso1A3: "AND",
23431             iso1N3: "020",
23432             wikidata: "Q228",
23433             nameEn: "Andorra",
23434             groups: ["Q12837", "039", "150", "UN"],
23435             callingCodes: ["376"]
23436           },
23437           geometry: {
23438             type: "MultiPolygon",
23439             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]]]]
23440           }
23441         }, {
23442           type: "Feature",
23443           properties: {
23444             iso1A2: "AE",
23445             iso1A3: "ARE",
23446             iso1N3: "784",
23447             wikidata: "Q878",
23448             nameEn: "United Arab Emirates",
23449             groups: ["145", "142", "UN"],
23450             callingCodes: ["971"]
23451           },
23452           geometry: {
23453             type: "MultiPolygon",
23454             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]]]]
23455           }
23456         }, {
23457           type: "Feature",
23458           properties: {
23459             iso1A2: "AF",
23460             iso1A3: "AFG",
23461             iso1N3: "004",
23462             wikidata: "Q889",
23463             nameEn: "Afghanistan",
23464             groups: ["034", "142", "UN"],
23465             callingCodes: ["93"]
23466           },
23467           geometry: {
23468             type: "MultiPolygon",
23469             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]]]]
23470           }
23471         }, {
23472           type: "Feature",
23473           properties: {
23474             iso1A2: "AG",
23475             iso1A3: "ATG",
23476             iso1N3: "028",
23477             wikidata: "Q781",
23478             nameEn: "Antigua and Barbuda",
23479             groups: ["029", "003", "419", "019", "UN"],
23480             driveSide: "left",
23481             roadSpeedUnit: "mph",
23482             callingCodes: ["1 268"]
23483           },
23484           geometry: {
23485             type: "MultiPolygon",
23486             coordinates: [[[[-61.66959, 18.6782], [-62.58307, 16.68909], [-62.1023, 16.97277], [-61.23098, 16.62484], [-61.66959, 18.6782]]]]
23487           }
23488         }, {
23489           type: "Feature",
23490           properties: {
23491             iso1A2: "AI",
23492             iso1A3: "AIA",
23493             iso1N3: "660",
23494             wikidata: "Q25228",
23495             nameEn: "Anguilla",
23496             country: "GB",
23497             groups: ["BOTS", "029", "003", "419", "019", "UN"],
23498             driveSide: "left",
23499             roadSpeedUnit: "mph",
23500             callingCodes: ["1 264"]
23501           },
23502           geometry: {
23503             type: "MultiPolygon",
23504             coordinates: [[[[-63.79029, 19.11219], [-63.35989, 18.06012], [-62.62718, 18.26185], [-63.79029, 19.11219]]]]
23505           }
23506         }, {
23507           type: "Feature",
23508           properties: {
23509             iso1A2: "AL",
23510             iso1A3: "ALB",
23511             iso1N3: "008",
23512             wikidata: "Q222",
23513             nameEn: "Albania",
23514             groups: ["039", "150", "UN"],
23515             callingCodes: ["355"]
23516           },
23517           geometry: {
23518             type: "MultiPolygon",
23519             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]]]]
23520           }
23521         }, {
23522           type: "Feature",
23523           properties: {
23524             iso1A2: "AM",
23525             iso1A3: "ARM",
23526             iso1N3: "051",
23527             wikidata: "Q399",
23528             nameEn: "Armenia",
23529             groups: ["145", "142", "UN"],
23530             callingCodes: ["374"]
23531           },
23532           geometry: {
23533             type: "MultiPolygon",
23534             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]]]]
23535           }
23536         }, {
23537           type: "Feature",
23538           properties: {
23539             iso1A2: "AO",
23540             iso1A3: "AGO",
23541             iso1N3: "024",
23542             wikidata: "Q916",
23543             nameEn: "Angola",
23544             groups: ["017", "202", "002", "UN"],
23545             callingCodes: ["244"]
23546           },
23547           geometry: {
23548             type: "MultiPolygon",
23549             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]]]]
23550           }
23551         }, {
23552           type: "Feature",
23553           properties: {
23554             iso1A2: "AQ",
23555             iso1A3: "ATA",
23556             iso1N3: "010",
23557             wikidata: "Q51",
23558             nameEn: "Antarctica",
23559             level: "region",
23560             callingCodes: ["672"]
23561           },
23562           geometry: {
23563             type: "MultiPolygon",
23564             coordinates: [[[[180, -60], [-180, -60], [-180, -90], [180, -90], [180, -60]]]]
23565           }
23566         }, {
23567           type: "Feature",
23568           properties: {
23569             iso1A2: "AR",
23570             iso1A3: "ARG",
23571             iso1N3: "032",
23572             wikidata: "Q414",
23573             nameEn: "Argentina",
23574             aliases: ["RA"],
23575             groups: ["005", "419", "019", "UN"],
23576             callingCodes: ["54"]
23577           },
23578           geometry: {
23579             type: "MultiPolygon",
23580             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]]]]
23581           }
23582         }, {
23583           type: "Feature",
23584           properties: {
23585             iso1A2: "AS",
23586             iso1A3: "ASM",
23587             iso1N3: "016",
23588             wikidata: "Q16641",
23589             nameEn: "American Samoa",
23590             aliases: ["US-AS"],
23591             country: "US",
23592             groups: ["Q1352230", "061", "009", "UN"],
23593             roadSpeedUnit: "mph",
23594             roadHeightUnit: "ft",
23595             callingCodes: ["1 684"]
23596           },
23597           geometry: {
23598             type: "MultiPolygon",
23599             coordinates: [[[[-171.39864, -10.21587], [-170.99605, -15.1275], [-166.32598, -15.26169], [-171.39864, -10.21587]]]]
23600           }
23601         }, {
23602           type: "Feature",
23603           properties: {
23604             iso1A2: "AT",
23605             iso1A3: "AUT",
23606             iso1N3: "040",
23607             wikidata: "Q40",
23608             nameEn: "Austria",
23609             groups: ["EU", "155", "150", "UN"],
23610             callingCodes: ["43"]
23611           },
23612           geometry: {
23613             type: "MultiPolygon",
23614             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]]]]
23615           }
23616         }, {
23617           type: "Feature",
23618           properties: {
23619             iso1A2: "AU",
23620             iso1A3: "AUS",
23621             iso1N3: "036",
23622             wikidata: "Q408",
23623             nameEn: "Australia"
23624           },
23625           geometry: null
23626         }, {
23627           type: "Feature",
23628           properties: {
23629             iso1A2: "AW",
23630             iso1A3: "ABW",
23631             iso1N3: "533",
23632             wikidata: "Q21203",
23633             nameEn: "Aruba",
23634             aliases: ["NL-AW"],
23635             country: "NL",
23636             groups: ["Q1451600", "029", "003", "419", "019", "UN"],
23637             callingCodes: ["297"]
23638           },
23639           geometry: {
23640             type: "MultiPolygon",
23641             coordinates: [[[[-70.00823, 12.98375], [-70.35625, 12.58277], [-69.60231, 12.17], [-70.00823, 12.98375]]]]
23642           }
23643         }, {
23644           type: "Feature",
23645           properties: {
23646             iso1A2: "AX",
23647             iso1A3: "ALA",
23648             iso1N3: "248",
23649             wikidata: "Q5689",
23650             nameEn: "\xC5land Islands",
23651             country: "FI",
23652             groups: ["EU", "154", "150", "UN"],
23653             callingCodes: ["358 18", "358 457"]
23654           },
23655           geometry: {
23656             type: "MultiPolygon",
23657             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]]]]
23658           }
23659         }, {
23660           type: "Feature",
23661           properties: {
23662             iso1A2: "AZ",
23663             iso1A3: "AZE",
23664             iso1N3: "031",
23665             wikidata: "Q227",
23666             nameEn: "Azerbaijan",
23667             groups: ["145", "142", "UN"],
23668             callingCodes: ["994"]
23669           },
23670           geometry: {
23671             type: "MultiPolygon",
23672             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]]]]
23673           }
23674         }, {
23675           type: "Feature",
23676           properties: {
23677             iso1A2: "BA",
23678             iso1A3: "BIH",
23679             iso1N3: "070",
23680             wikidata: "Q225",
23681             nameEn: "Bosnia and Herzegovina",
23682             groups: ["039", "150", "UN"],
23683             callingCodes: ["387"]
23684           },
23685           geometry: {
23686             type: "MultiPolygon",
23687             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]]]]
23688           }
23689         }, {
23690           type: "Feature",
23691           properties: {
23692             iso1A2: "BB",
23693             iso1A3: "BRB",
23694             iso1N3: "052",
23695             wikidata: "Q244",
23696             nameEn: "Barbados",
23697             groups: ["029", "003", "419", "019", "UN"],
23698             driveSide: "left",
23699             callingCodes: ["1 246"]
23700           },
23701           geometry: {
23702             type: "MultiPolygon",
23703             coordinates: [[[[-58.56442, 13.24471], [-59.80731, 13.87556], [-59.82929, 12.70644], [-58.56442, 13.24471]]]]
23704           }
23705         }, {
23706           type: "Feature",
23707           properties: {
23708             iso1A2: "BD",
23709             iso1A3: "BGD",
23710             iso1N3: "050",
23711             wikidata: "Q902",
23712             nameEn: "Bangladesh",
23713             groups: ["034", "142", "UN"],
23714             driveSide: "left",
23715             callingCodes: ["880"]
23716           },
23717           geometry: {
23718             type: "MultiPolygon",
23719             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]]]]
23720           }
23721         }, {
23722           type: "Feature",
23723           properties: {
23724             iso1A2: "BE",
23725             iso1A3: "BEL",
23726             iso1N3: "056",
23727             wikidata: "Q31",
23728             nameEn: "Belgium",
23729             groups: ["EU", "155", "150", "UN"],
23730             callingCodes: ["32"]
23731           },
23732           geometry: {
23733             type: "MultiPolygon",
23734             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]]]]
23735           }
23736         }, {
23737           type: "Feature",
23738           properties: {
23739             iso1A2: "BF",
23740             iso1A3: "BFA",
23741             iso1N3: "854",
23742             wikidata: "Q965",
23743             nameEn: "Burkina Faso",
23744             groups: ["011", "202", "002", "UN"],
23745             callingCodes: ["226"]
23746           },
23747           geometry: {
23748             type: "MultiPolygon",
23749             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]]]]
23750           }
23751         }, {
23752           type: "Feature",
23753           properties: {
23754             iso1A2: "BG",
23755             iso1A3: "BGR",
23756             iso1N3: "100",
23757             wikidata: "Q219",
23758             nameEn: "Bulgaria",
23759             groups: ["EU", "151", "150", "UN"],
23760             callingCodes: ["359"]
23761           },
23762           geometry: {
23763             type: "MultiPolygon",
23764             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]]]]
23765           }
23766         }, {
23767           type: "Feature",
23768           properties: {
23769             iso1A2: "BH",
23770             iso1A3: "BHR",
23771             iso1N3: "048",
23772             wikidata: "Q398",
23773             nameEn: "Bahrain",
23774             groups: ["145", "142", "UN"],
23775             callingCodes: ["973"]
23776           },
23777           geometry: {
23778             type: "MultiPolygon",
23779             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]]]]
23780           }
23781         }, {
23782           type: "Feature",
23783           properties: {
23784             iso1A2: "BI",
23785             iso1A3: "BDI",
23786             iso1N3: "108",
23787             wikidata: "Q967",
23788             nameEn: "Burundi",
23789             groups: ["014", "202", "002", "UN"],
23790             callingCodes: ["257"]
23791           },
23792           geometry: {
23793             type: "MultiPolygon",
23794             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]]]]
23795           }
23796         }, {
23797           type: "Feature",
23798           properties: {
23799             iso1A2: "BJ",
23800             iso1A3: "BEN",
23801             iso1N3: "204",
23802             wikidata: "Q962",
23803             nameEn: "Benin",
23804             aliases: ["DY"],
23805             groups: ["011", "202", "002", "UN"],
23806             callingCodes: ["229"]
23807           },
23808           geometry: {
23809             type: "MultiPolygon",
23810             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]]]]
23811           }
23812         }, {
23813           type: "Feature",
23814           properties: {
23815             iso1A2: "BL",
23816             iso1A3: "BLM",
23817             iso1N3: "652",
23818             wikidata: "Q25362",
23819             nameEn: "Saint-Barth\xE9lemy",
23820             country: "FR",
23821             groups: ["Q1451600", "029", "003", "419", "019", "UN"],
23822             callingCodes: ["590"]
23823           },
23824           geometry: {
23825             type: "MultiPolygon",
23826             coordinates: [[[[-62.62718, 18.26185], [-63.1055, 17.86651], [-62.34423, 17.49165], [-62.62718, 18.26185]]]]
23827           }
23828         }, {
23829           type: "Feature",
23830           properties: {
23831             iso1A2: "BM",
23832             iso1A3: "BMU",
23833             iso1N3: "060",
23834             wikidata: "Q23635",
23835             nameEn: "Bermuda",
23836             country: "GB",
23837             groups: ["BOTS", "021", "003", "019", "UN"],
23838             driveSide: "left",
23839             callingCodes: ["1 441"]
23840           },
23841           geometry: {
23842             type: "MultiPolygon",
23843             coordinates: [[[[-63.20987, 32.6953], [-65.31453, 32.68437], [-65.63955, 31.43417], [-63.20987, 32.6953]]]]
23844           }
23845         }, {
23846           type: "Feature",
23847           properties: {
23848             iso1A2: "BN",
23849             iso1A3: "BRN",
23850             iso1N3: "096",
23851             wikidata: "Q921",
23852             nameEn: "Brunei",
23853             groups: ["Q36117", "035", "142", "UN"],
23854             driveSide: "left",
23855             callingCodes: ["673"]
23856           },
23857           geometry: {
23858             type: "MultiPolygon",
23859             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]]]]
23860           }
23861         }, {
23862           type: "Feature",
23863           properties: {
23864             iso1A2: "BO",
23865             iso1A3: "BOL",
23866             iso1N3: "068",
23867             wikidata: "Q750",
23868             nameEn: "Bolivia",
23869             groups: ["005", "419", "019", "UN"],
23870             callingCodes: ["591"]
23871           },
23872           geometry: {
23873             type: "MultiPolygon",
23874             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]]]]
23875           }
23876         }, {
23877           type: "Feature",
23878           properties: {
23879             iso1A2: "BQ",
23880             iso1A3: "BES",
23881             iso1N3: "535",
23882             wikidata: "Q27561",
23883             nameEn: "Caribbean Netherlands",
23884             country: "NL"
23885           },
23886           geometry: null
23887         }, {
23888           type: "Feature",
23889           properties: {
23890             iso1A2: "BR",
23891             iso1A3: "BRA",
23892             iso1N3: "076",
23893             wikidata: "Q155",
23894             nameEn: "Brazil",
23895             groups: ["005", "419", "019", "UN"],
23896             callingCodes: ["55"]
23897           },
23898           geometry: {
23899             type: "MultiPolygon",
23900             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]]]]
23901           }
23902         }, {
23903           type: "Feature",
23904           properties: {
23905             iso1A2: "BS",
23906             iso1A3: "BHS",
23907             iso1N3: "044",
23908             wikidata: "Q778",
23909             nameEn: "The Bahamas",
23910             groups: ["029", "003", "419", "019", "UN"],
23911             driveSide: "left",
23912             roadSpeedUnit: "mph",
23913             callingCodes: ["1 242"]
23914           },
23915           geometry: {
23916             type: "MultiPolygon",
23917             coordinates: [[[[-72.98446, 20.4801], [-71.70065, 25.7637], [-78.91214, 27.76553], [-80.65727, 23.71953], [-72.98446, 20.4801]]]]
23918           }
23919         }, {
23920           type: "Feature",
23921           properties: {
23922             iso1A2: "BT",
23923             iso1A3: "BTN",
23924             iso1N3: "064",
23925             wikidata: "Q917",
23926             nameEn: "Bhutan",
23927             groups: ["034", "142", "UN"],
23928             driveSide: "left",
23929             callingCodes: ["975"]
23930           },
23931           geometry: {
23932             type: "MultiPolygon",
23933             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]]]]
23934           }
23935         }, {
23936           type: "Feature",
23937           properties: {
23938             iso1A2: "BV",
23939             iso1A3: "BVT",
23940             iso1N3: "074",
23941             wikidata: "Q23408",
23942             nameEn: "Bouvet Island",
23943             country: "NO",
23944             groups: ["005", "419", "019", "UN"]
23945           },
23946           geometry: {
23947             type: "MultiPolygon",
23948             coordinates: [[[[4.54042, -54.0949], [2.28941, -54.13089], [3.35353, -55.17558], [4.54042, -54.0949]]]]
23949           }
23950         }, {
23951           type: "Feature",
23952           properties: {
23953             iso1A2: "BW",
23954             iso1A3: "BWA",
23955             iso1N3: "072",
23956             wikidata: "Q963",
23957             nameEn: "Botswana",
23958             groups: ["018", "202", "002", "UN"],
23959             driveSide: "left",
23960             callingCodes: ["267"]
23961           },
23962           geometry: {
23963             type: "MultiPolygon",
23964             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]]]]
23965           }
23966         }, {
23967           type: "Feature",
23968           properties: {
23969             iso1A2: "BY",
23970             iso1A3: "BLR",
23971             iso1N3: "112",
23972             wikidata: "Q184",
23973             nameEn: "Belarus",
23974             groups: ["151", "150", "UN"],
23975             callingCodes: ["375"]
23976           },
23977           geometry: {
23978             type: "MultiPolygon",
23979             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]]]]
23980           }
23981         }, {
23982           type: "Feature",
23983           properties: {
23984             iso1A2: "BZ",
23985             iso1A3: "BLZ",
23986             iso1N3: "084",
23987             wikidata: "Q242",
23988             nameEn: "Belize",
23989             groups: ["013", "003", "419", "019", "UN"],
23990             roadSpeedUnit: "mph",
23991             callingCodes: ["501"]
23992           },
23993           geometry: {
23994             type: "MultiPolygon",
23995             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]]]]
23996           }
23997         }, {
23998           type: "Feature",
23999           properties: {
24000             iso1A2: "CA",
24001             iso1A3: "CAN",
24002             iso1N3: "124",
24003             wikidata: "Q16",
24004             nameEn: "Canada",
24005             groups: ["021", "003", "019", "UN"],
24006             callingCodes: ["1"]
24007           },
24008           geometry: {
24009             type: "MultiPolygon",
24010             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]]]]
24011           }
24012         }, {
24013           type: "Feature",
24014           properties: {
24015             iso1A2: "CC",
24016             iso1A3: "CCK",
24017             iso1N3: "166",
24018             wikidata: "Q36004",
24019             nameEn: "Cocos (Keeling) Islands",
24020             country: "AU",
24021             groups: ["053", "009", "UN"],
24022             driveSide: "left",
24023             callingCodes: ["61"]
24024           },
24025           geometry: {
24026             type: "MultiPolygon",
24027             coordinates: [[[[96.61846, -10.82438], [96.02343, -12.68334], [97.93979, -12.33309], [96.61846, -10.82438]]]]
24028           }
24029         }, {
24030           type: "Feature",
24031           properties: {
24032             iso1A2: "CD",
24033             iso1A3: "COD",
24034             iso1N3: "180",
24035             wikidata: "Q974",
24036             nameEn: "Democratic Republic of the Congo",
24037             aliases: ["ZR"],
24038             groups: ["017", "202", "002", "UN"],
24039             callingCodes: ["243"]
24040           },
24041           geometry: {
24042             type: "MultiPolygon",
24043             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]]]]
24044           }
24045         }, {
24046           type: "Feature",
24047           properties: {
24048             iso1A2: "CF",
24049             iso1A3: "CAF",
24050             iso1N3: "140",
24051             wikidata: "Q929",
24052             nameEn: "Central African Republic",
24053             groups: ["017", "202", "002", "UN"],
24054             callingCodes: ["236"]
24055           },
24056           geometry: {
24057             type: "MultiPolygon",
24058             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]]]]
24059           }
24060         }, {
24061           type: "Feature",
24062           properties: {
24063             iso1A2: "CG",
24064             iso1A3: "COG",
24065             iso1N3: "178",
24066             wikidata: "Q971",
24067             nameEn: "Republic of the Congo",
24068             groups: ["017", "202", "002", "UN"],
24069             callingCodes: ["242"]
24070           },
24071           geometry: {
24072             type: "MultiPolygon",
24073             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]]]]
24074           }
24075         }, {
24076           type: "Feature",
24077           properties: {
24078             iso1A2: "CH",
24079             iso1A3: "CHE",
24080             iso1N3: "756",
24081             wikidata: "Q39",
24082             nameEn: "Switzerland",
24083             groups: ["155", "150", "UN"],
24084             callingCodes: ["41"]
24085           },
24086           geometry: {
24087             type: "MultiPolygon",
24088             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]]]]
24089           }
24090         }, {
24091           type: "Feature",
24092           properties: {
24093             iso1A2: "CI",
24094             iso1A3: "CIV",
24095             iso1N3: "384",
24096             wikidata: "Q1008",
24097             nameEn: "C\xF4te d'Ivoire",
24098             groups: ["011", "202", "002", "UN"],
24099             callingCodes: ["225"]
24100           },
24101           geometry: {
24102             type: "MultiPolygon",
24103             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]]]]
24104           }
24105         }, {
24106           type: "Feature",
24107           properties: {
24108             iso1A2: "CK",
24109             iso1A3: "COK",
24110             iso1N3: "184",
24111             wikidata: "Q26988",
24112             nameEn: "Cook Islands",
24113             country: "NZ",
24114             groups: ["061", "009", "UN"],
24115             driveSide: "left",
24116             callingCodes: ["682"]
24117           },
24118           geometry: {
24119             type: "MultiPolygon",
24120             coordinates: [[[[-168.15106, -10.26955], [-156.45576, -31.75456], [-156.48634, -15.52824], [-156.50903, -7.4975], [-168.15106, -10.26955]]]]
24121           }
24122         }, {
24123           type: "Feature",
24124           properties: {
24125             iso1A2: "CL",
24126             iso1A3: "CHL",
24127             iso1N3: "152",
24128             wikidata: "Q298",
24129             nameEn: "Chile",
24130             groups: ["005", "419", "019", "UN"],
24131             callingCodes: ["56"]
24132           },
24133           geometry: {
24134             type: "MultiPolygon",
24135             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]]]]
24136           }
24137         }, {
24138           type: "Feature",
24139           properties: {
24140             iso1A2: "CM",
24141             iso1A3: "CMR",
24142             iso1N3: "120",
24143             wikidata: "Q1009",
24144             nameEn: "Cameroon",
24145             groups: ["017", "202", "002", "UN"],
24146             callingCodes: ["237"]
24147           },
24148           geometry: {
24149             type: "MultiPolygon",
24150             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]]]]
24151           }
24152         }, {
24153           type: "Feature",
24154           properties: {
24155             iso1A2: "CN",
24156             iso1A3: "CHN",
24157             iso1N3: "156",
24158             wikidata: "Q148",
24159             nameEn: "People's Republic of China"
24160           },
24161           geometry: null
24162         }, {
24163           type: "Feature",
24164           properties: {
24165             iso1A2: "CO",
24166             iso1A3: "COL",
24167             iso1N3: "170",
24168             wikidata: "Q739",
24169             nameEn: "Colombia",
24170             groups: ["005", "419", "019", "UN"],
24171             callingCodes: ["57"]
24172           },
24173           geometry: {
24174             type: "MultiPolygon",
24175             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]]]]
24176           }
24177         }, {
24178           type: "Feature",
24179           properties: {
24180             iso1A2: "CP",
24181             iso1A3: "CPT",
24182             wikidata: "Q161258",
24183             nameEn: "Clipperton Island",
24184             country: "FR",
24185             groups: ["013", "003", "019", "UN"],
24186             isoStatus: "excRes"
24187           },
24188           geometry: {
24189             type: "MultiPolygon",
24190             coordinates: [[[[-110.36279, 9.79626], [-108.755, 9.84085], [-109.04145, 11.13245], [-110.36279, 9.79626]]]]
24191           }
24192         }, {
24193           type: "Feature",
24194           properties: {
24195             iso1A2: "CR",
24196             iso1A3: "CRI",
24197             iso1N3: "188",
24198             wikidata: "Q800",
24199             nameEn: "Costa Rica",
24200             groups: ["013", "003", "419", "019", "UN"],
24201             callingCodes: ["506"]
24202           },
24203           geometry: {
24204             type: "MultiPolygon",
24205             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]]]]
24206           }
24207         }, {
24208           type: "Feature",
24209           properties: {
24210             iso1A2: "CU",
24211             iso1A3: "CUB",
24212             iso1N3: "192",
24213             wikidata: "Q241",
24214             nameEn: "Cuba",
24215             groups: ["029", "003", "419", "019", "UN"],
24216             callingCodes: ["53"]
24217           },
24218           geometry: {
24219             type: "MultiPolygon",
24220             coordinates: [[[[-73.62304, 20.6935], [-82.02215, 24.23074], [-85.77883, 21.92705], [-74.81171, 18.82201], [-73.62304, 20.6935]]]]
24221           }
24222         }, {
24223           type: "Feature",
24224           properties: {
24225             iso1A2: "CV",
24226             iso1A3: "CPV",
24227             iso1N3: "132",
24228             wikidata: "Q1011",
24229             nameEn: "Cape Verde",
24230             groups: ["Q105472", "011", "202", "002", "UN"],
24231             callingCodes: ["238"]
24232           },
24233           geometry: {
24234             type: "MultiPolygon",
24235             coordinates: [[[[-28.81604, 14.57305], [-20.39702, 14.12816], [-23.37101, 19.134], [-28.81604, 14.57305]]]]
24236           }
24237         }, {
24238           type: "Feature",
24239           properties: {
24240             iso1A2: "CW",
24241             iso1A3: "CUW",
24242             iso1N3: "531",
24243             wikidata: "Q25279",
24244             nameEn: "Cura\xE7ao",
24245             aliases: ["NL-CW"],
24246             country: "NL",
24247             groups: ["Q1451600", "029", "003", "419", "019", "UN"],
24248             callingCodes: ["599"]
24249           },
24250           geometry: {
24251             type: "MultiPolygon",
24252             coordinates: [[[[-68.90012, 12.62309], [-69.59009, 12.46019], [-68.99639, 11.79035], [-68.33524, 11.78151], [-68.90012, 12.62309]]]]
24253           }
24254         }, {
24255           type: "Feature",
24256           properties: {
24257             iso1A2: "CX",
24258             iso1A3: "CXR",
24259             iso1N3: "162",
24260             wikidata: "Q31063",
24261             nameEn: "Christmas Island",
24262             country: "AU",
24263             groups: ["053", "009", "UN"],
24264             driveSide: "left",
24265             callingCodes: ["61"]
24266           },
24267           geometry: {
24268             type: "MultiPolygon",
24269             coordinates: [[[[105.66835, -9.31927], [104.67494, -11.2566], [106.66176, -11.14349], [105.66835, -9.31927]]]]
24270           }
24271         }, {
24272           type: "Feature",
24273           properties: {
24274             iso1A2: "CY",
24275             iso1A3: "CYP",
24276             iso1N3: "196",
24277             wikidata: "Q229",
24278             nameEn: "Republic of Cyprus",
24279             groups: ["Q644636", "EU", "145", "142", "UN"],
24280             driveSide: "left",
24281             callingCodes: ["357"]
24282           },
24283           geometry: {
24284             type: "MultiPolygon",
24285             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]]]]
24286           }
24287         }, {
24288           type: "Feature",
24289           properties: {
24290             iso1A2: "CZ",
24291             iso1A3: "CZE",
24292             iso1N3: "203",
24293             wikidata: "Q213",
24294             nameEn: "Czechia",
24295             groups: ["EU", "151", "150", "UN"],
24296             callingCodes: ["420"]
24297           },
24298           geometry: {
24299             type: "MultiPolygon",
24300             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]]]]
24301           }
24302         }, {
24303           type: "Feature",
24304           properties: {
24305             iso1A2: "DE",
24306             iso1A3: "DEU",
24307             iso1N3: "276",
24308             wikidata: "Q183",
24309             nameEn: "Germany",
24310             groups: ["EU", "155", "150", "UN"],
24311             callingCodes: ["49"]
24312           },
24313           geometry: {
24314             type: "MultiPolygon",
24315             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]]]]
24316           }
24317         }, {
24318           type: "Feature",
24319           properties: {
24320             iso1A2: "DG",
24321             iso1A3: "DGA",
24322             wikidata: "Q184851",
24323             nameEn: "Diego Garcia",
24324             country: "GB",
24325             groups: ["IO", "BOTS", "014", "202", "002", "UN"],
24326             isoStatus: "excRes",
24327             callingCodes: ["246"]
24328           },
24329           geometry: {
24330             type: "MultiPolygon",
24331             coordinates: [[[[73.14823, -7.76302], [73.09982, -6.07324], [71.43792, -7.73904], [73.14823, -7.76302]]]]
24332           }
24333         }, {
24334           type: "Feature",
24335           properties: {
24336             iso1A2: "DJ",
24337             iso1A3: "DJI",
24338             iso1N3: "262",
24339             wikidata: "Q977",
24340             nameEn: "Djibouti",
24341             groups: ["014", "202", "002", "UN"],
24342             callingCodes: ["253"]
24343           },
24344           geometry: {
24345             type: "MultiPolygon",
24346             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]]]]
24347           }
24348         }, {
24349           type: "Feature",
24350           properties: {
24351             iso1A2: "DK",
24352             iso1A3: "DNK",
24353             iso1N3: "208",
24354             wikidata: "Q756617",
24355             nameEn: "Kingdom of Denmark"
24356           },
24357           geometry: null
24358         }, {
24359           type: "Feature",
24360           properties: {
24361             iso1A2: "DM",
24362             iso1A3: "DMA",
24363             iso1N3: "212",
24364             wikidata: "Q784",
24365             nameEn: "Dominica",
24366             groups: ["029", "003", "419", "019", "UN"],
24367             driveSide: "left",
24368             roadSpeedUnit: "mph",
24369             callingCodes: ["1 767"]
24370           },
24371           geometry: {
24372             type: "MultiPolygon",
24373             coordinates: [[[[-61.32485, 14.91445], [-60.86656, 15.82603], [-61.95646, 15.5094], [-61.32485, 14.91445]]]]
24374           }
24375         }, {
24376           type: "Feature",
24377           properties: {
24378             iso1A2: "DO",
24379             iso1A3: "DOM",
24380             iso1N3: "214",
24381             wikidata: "Q786",
24382             nameEn: "Dominican Republic",
24383             groups: ["029", "003", "419", "019", "UN"],
24384             callingCodes: ["1 809", "1 829", "1 849"]
24385           },
24386           geometry: {
24387             type: "MultiPolygon",
24388             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]]]]
24389           }
24390         }, {
24391           type: "Feature",
24392           properties: {
24393             iso1A2: "DZ",
24394             iso1A3: "DZA",
24395             iso1N3: "012",
24396             wikidata: "Q262",
24397             nameEn: "Algeria",
24398             groups: ["015", "002", "UN"],
24399             callingCodes: ["213"]
24400           },
24401           geometry: {
24402             type: "MultiPolygon",
24403             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]]]]
24404           }
24405         }, {
24406           type: "Feature",
24407           properties: {
24408             iso1A2: "EA",
24409             wikidata: "Q28868874",
24410             nameEn: "Ceuta, Melilla",
24411             country: "ES",
24412             level: "territory",
24413             isoStatus: "excRes"
24414           },
24415           geometry: null
24416         }, {
24417           type: "Feature",
24418           properties: {
24419             iso1A2: "EC",
24420             iso1A3: "ECU",
24421             iso1N3: "218",
24422             wikidata: "Q736",
24423             nameEn: "Ecuador"
24424           },
24425           geometry: null
24426         }, {
24427           type: "Feature",
24428           properties: {
24429             iso1A2: "EE",
24430             iso1A3: "EST",
24431             iso1N3: "233",
24432             wikidata: "Q191",
24433             nameEn: "Estonia",
24434             aliases: ["EW"],
24435             groups: ["EU", "154", "150", "UN"],
24436             callingCodes: ["372"]
24437           },
24438           geometry: {
24439             type: "MultiPolygon",
24440             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]]]]
24441           }
24442         }, {
24443           type: "Feature",
24444           properties: {
24445             iso1A2: "EG",
24446             iso1A3: "EGY",
24447             iso1N3: "818",
24448             wikidata: "Q79",
24449             nameEn: "Egypt",
24450             groups: ["015", "002", "UN"],
24451             callingCodes: ["20"]
24452           },
24453           geometry: {
24454             type: "MultiPolygon",
24455             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]]]]
24456           }
24457         }, {
24458           type: "Feature",
24459           properties: {
24460             iso1A2: "EH",
24461             iso1A3: "ESH",
24462             iso1N3: "732",
24463             wikidata: "Q6250",
24464             nameEn: "Western Sahara",
24465             groups: ["015", "002"],
24466             callingCodes: ["212"]
24467           },
24468           geometry: {
24469             type: "MultiPolygon",
24470             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]]]]
24471           }
24472         }, {
24473           type: "Feature",
24474           properties: {
24475             iso1A2: "ER",
24476             iso1A3: "ERI",
24477             iso1N3: "232",
24478             wikidata: "Q986",
24479             nameEn: "Eritrea",
24480             groups: ["014", "202", "002", "UN"],
24481             callingCodes: ["291"]
24482           },
24483           geometry: {
24484             type: "MultiPolygon",
24485             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]]]]
24486           }
24487         }, {
24488           type: "Feature",
24489           properties: {
24490             iso1A2: "ES",
24491             iso1A3: "ESP",
24492             iso1N3: "724",
24493             wikidata: "Q29",
24494             nameEn: "Spain"
24495           },
24496           geometry: null
24497         }, {
24498           type: "Feature",
24499           properties: {
24500             iso1A2: "ET",
24501             iso1A3: "ETH",
24502             iso1N3: "231",
24503             wikidata: "Q115",
24504             nameEn: "Ethiopia",
24505             groups: ["014", "202", "002", "UN"],
24506             callingCodes: ["251"]
24507           },
24508           geometry: {
24509             type: "MultiPolygon",
24510             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]]]]
24511           }
24512         }, {
24513           type: "Feature",
24514           properties: {
24515             iso1A2: "EU",
24516             iso1A3: "EUE",
24517             wikidata: "Q458",
24518             nameEn: "European Union",
24519             level: "union",
24520             isoStatus: "excRes"
24521           },
24522           geometry: null
24523         }, {
24524           type: "Feature",
24525           properties: {
24526             iso1A2: "FI",
24527             iso1A3: "FIN",
24528             iso1N3: "246",
24529             wikidata: "Q33",
24530             nameEn: "Finland",
24531             aliases: ["SF"]
24532           },
24533           geometry: null
24534         }, {
24535           type: "Feature",
24536           properties: {
24537             iso1A2: "FJ",
24538             iso1A3: "FJI",
24539             iso1N3: "242",
24540             wikidata: "Q712",
24541             nameEn: "Fiji",
24542             groups: ["054", "009", "UN"],
24543             driveSide: "left",
24544             callingCodes: ["679"]
24545           },
24546           geometry: {
24547             type: "MultiPolygon",
24548             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]]]]
24549           }
24550         }, {
24551           type: "Feature",
24552           properties: {
24553             iso1A2: "FK",
24554             iso1A3: "FLK",
24555             iso1N3: "238",
24556             wikidata: "Q9648",
24557             nameEn: "Falkland Islands",
24558             country: "GB",
24559             groups: ["BOTS", "005", "419", "019", "UN"],
24560             driveSide: "left",
24561             roadSpeedUnit: "mph",
24562             roadHeightUnit: "ft",
24563             callingCodes: ["500"]
24564           },
24565           geometry: {
24566             type: "MultiPolygon",
24567             coordinates: [[[[-63.67376, -55.11859], [-54.56126, -51.26248], [-61.26735, -50.63919], [-63.67376, -55.11859]]]]
24568           }
24569         }, {
24570           type: "Feature",
24571           properties: {
24572             iso1A2: "FM",
24573             iso1A3: "FSM",
24574             iso1N3: "583",
24575             wikidata: "Q702",
24576             nameEn: "Federated States of Micronesia",
24577             groups: ["057", "009", "UN"],
24578             roadSpeedUnit: "mph",
24579             roadHeightUnit: "ft",
24580             callingCodes: ["691"]
24581           },
24582           geometry: {
24583             type: "MultiPolygon",
24584             coordinates: [[[[138.20583, 13.3783], [136.27107, 6.73747], [156.88247, -1.39237], [165.19726, 6.22546], [138.20583, 13.3783]]]]
24585           }
24586         }, {
24587           type: "Feature",
24588           properties: {
24589             iso1A2: "FO",
24590             iso1A3: "FRO",
24591             iso1N3: "234",
24592             wikidata: "Q4628",
24593             nameEn: "Faroe Islands",
24594             country: "DK",
24595             groups: ["154", "150", "UN"],
24596             callingCodes: ["298"]
24597           },
24598           geometry: {
24599             type: "MultiPolygon",
24600             coordinates: [[[[-8.51774, 62.35338], [-6.51083, 60.95272], [-5.70102, 62.77194], [-8.51774, 62.35338]]]]
24601           }
24602         }, {
24603           type: "Feature",
24604           properties: {
24605             iso1A2: "FR",
24606             iso1A3: "FRA",
24607             iso1N3: "250",
24608             wikidata: "Q142",
24609             nameEn: "France"
24610           },
24611           geometry: null
24612         }, {
24613           type: "Feature",
24614           properties: {
24615             iso1A2: "FX",
24616             iso1A3: "FXX",
24617             iso1N3: "249",
24618             wikidata: "Q212429",
24619             nameEn: "Metropolitan France",
24620             country: "FR",
24621             groups: ["EU", "155", "150", "UN"],
24622             isoStatus: "excRes",
24623             callingCodes: ["33"]
24624           },
24625           geometry: {
24626             type: "MultiPolygon",
24627             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]]]]
24628           }
24629         }, {
24630           type: "Feature",
24631           properties: {
24632             iso1A2: "GA",
24633             iso1A3: "GAB",
24634             iso1N3: "266",
24635             wikidata: "Q1000",
24636             nameEn: "Gabon",
24637             groups: ["017", "202", "002", "UN"],
24638             callingCodes: ["241"]
24639           },
24640           geometry: {
24641             type: "MultiPolygon",
24642             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]]]]
24643           }
24644         }, {
24645           type: "Feature",
24646           properties: {
24647             iso1A2: "GB",
24648             iso1A3: "GBR",
24649             iso1N3: "826",
24650             wikidata: "Q145",
24651             ccTLD: ".uk",
24652             nameEn: "United Kingdom",
24653             aliases: ["UK"]
24654           },
24655           geometry: null
24656         }, {
24657           type: "Feature",
24658           properties: {
24659             iso1A2: "GD",
24660             iso1A3: "GRD",
24661             iso1N3: "308",
24662             wikidata: "Q769",
24663             nameEn: "Grenada",
24664             aliases: ["WG"],
24665             groups: ["029", "003", "419", "019", "UN"],
24666             driveSide: "left",
24667             roadSpeedUnit: "mph",
24668             callingCodes: ["1 473"]
24669           },
24670           geometry: {
24671             type: "MultiPolygon",
24672             coordinates: [[[[-62.64026, 12.69984], [-61.77886, 11.36496], [-59.94058, 12.34011], [-62.64026, 12.69984]]]]
24673           }
24674         }, {
24675           type: "Feature",
24676           properties: {
24677             iso1A2: "GE",
24678             iso1A3: "GEO",
24679             iso1N3: "268",
24680             wikidata: "Q230",
24681             nameEn: "Georgia",
24682             groups: ["145", "142", "UN"],
24683             callingCodes: ["995"]
24684           },
24685           geometry: {
24686             type: "MultiPolygon",
24687             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]]]]
24688           }
24689         }, {
24690           type: "Feature",
24691           properties: {
24692             iso1A2: "GF",
24693             iso1A3: "GUF",
24694             iso1N3: "254",
24695             wikidata: "Q3769",
24696             nameEn: "French Guiana",
24697             country: "FR",
24698             groups: ["Q3320166", "EU", "005", "419", "019", "UN"],
24699             callingCodes: ["594"]
24700           },
24701           geometry: {
24702             type: "MultiPolygon",
24703             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]]]]
24704           }
24705         }, {
24706           type: "Feature",
24707           properties: {
24708             iso1A2: "GG",
24709             iso1A3: "GGY",
24710             iso1N3: "831",
24711             wikidata: "Q25230",
24712             nameEn: "Bailiwick of Guernsey",
24713             country: "GB"
24714           },
24715           geometry: null
24716         }, {
24717           type: "Feature",
24718           properties: {
24719             iso1A2: "GH",
24720             iso1A3: "GHA",
24721             iso1N3: "288",
24722             wikidata: "Q117",
24723             nameEn: "Ghana",
24724             groups: ["011", "202", "002", "UN"],
24725             callingCodes: ["233"]
24726           },
24727           geometry: {
24728             type: "MultiPolygon",
24729             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]]]]
24730           }
24731         }, {
24732           type: "Feature",
24733           properties: {
24734             iso1A2: "GI",
24735             iso1A3: "GIB",
24736             iso1N3: "292",
24737             wikidata: "Q1410",
24738             nameEn: "Gibraltar",
24739             country: "GB",
24740             groups: ["Q12837", "BOTS", "039", "150", "UN"],
24741             callingCodes: ["350"]
24742           },
24743           geometry: {
24744             type: "MultiPolygon",
24745             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]]]]
24746           }
24747         }, {
24748           type: "Feature",
24749           properties: {
24750             iso1A2: "GL",
24751             iso1A3: "GRL",
24752             iso1N3: "304",
24753             wikidata: "Q223",
24754             nameEn: "Greenland",
24755             country: "DK",
24756             groups: ["Q1451600", "021", "003", "019", "UN"],
24757             callingCodes: ["299"]
24758           },
24759           geometry: {
24760             type: "MultiPolygon",
24761             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]]]]
24762           }
24763         }, {
24764           type: "Feature",
24765           properties: {
24766             iso1A2: "GM",
24767             iso1A3: "GMB",
24768             iso1N3: "270",
24769             wikidata: "Q1005",
24770             nameEn: "The Gambia",
24771             groups: ["011", "202", "002", "UN"],
24772             callingCodes: ["220"]
24773           },
24774           geometry: {
24775             type: "MultiPolygon",
24776             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]]]]
24777           }
24778         }, {
24779           type: "Feature",
24780           properties: {
24781             iso1A2: "GN",
24782             iso1A3: "GIN",
24783             iso1N3: "324",
24784             wikidata: "Q1006",
24785             nameEn: "Guinea",
24786             groups: ["011", "202", "002", "UN"],
24787             callingCodes: ["224"]
24788           },
24789           geometry: {
24790             type: "MultiPolygon",
24791             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]]]]
24792           }
24793         }, {
24794           type: "Feature",
24795           properties: {
24796             iso1A2: "GP",
24797             iso1A3: "GLP",
24798             iso1N3: "312",
24799             wikidata: "Q17012",
24800             nameEn: "Guadeloupe",
24801             country: "FR",
24802             groups: ["Q3320166", "EU", "029", "003", "419", "019", "UN"],
24803             callingCodes: ["590"]
24804           },
24805           geometry: {
24806             type: "MultiPolygon",
24807             coordinates: [[[[-60.03183, 16.1129], [-61.60296, 16.73066], [-63.00549, 15.26166], [-60.03183, 16.1129]]]]
24808           }
24809         }, {
24810           type: "Feature",
24811           properties: {
24812             iso1A2: "GQ",
24813             iso1A3: "GNQ",
24814             iso1N3: "226",
24815             wikidata: "Q983",
24816             nameEn: "Equatorial Guinea",
24817             groups: ["017", "202", "002", "UN"],
24818             callingCodes: ["240"]
24819           },
24820           geometry: {
24821             type: "MultiPolygon",
24822             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]]]]
24823           }
24824         }, {
24825           type: "Feature",
24826           properties: {
24827             iso1A2: "GR",
24828             iso1A3: "GRC",
24829             iso1N3: "300",
24830             wikidata: "Q41",
24831             nameEn: "Greece",
24832             aliases: ["EL"],
24833             groups: ["EU", "039", "150", "UN"],
24834             callingCodes: ["30"]
24835           },
24836           geometry: {
24837             type: "MultiPolygon",
24838             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]]]]
24839           }
24840         }, {
24841           type: "Feature",
24842           properties: {
24843             iso1A2: "GS",
24844             iso1A3: "SGS",
24845             iso1N3: "239",
24846             wikidata: "Q35086",
24847             nameEn: "South Georgia and South Sandwich Islands",
24848             country: "GB",
24849             groups: ["BOTS", "005", "419", "019", "UN"],
24850             driveSide: "left",
24851             roadSpeedUnit: "mph",
24852             roadHeightUnit: "ft",
24853             callingCodes: ["500"]
24854           },
24855           geometry: {
24856             type: "MultiPolygon",
24857             coordinates: [[[[-35.26394, -43.68272], [-53.39656, -59.87088], [-22.31757, -59.85974], [-35.26394, -43.68272]]]]
24858           }
24859         }, {
24860           type: "Feature",
24861           properties: {
24862             iso1A2: "GT",
24863             iso1A3: "GTM",
24864             iso1N3: "320",
24865             wikidata: "Q774",
24866             nameEn: "Guatemala",
24867             groups: ["013", "003", "419", "019", "UN"],
24868             callingCodes: ["502"]
24869           },
24870           geometry: {
24871             type: "MultiPolygon",
24872             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]]]]
24873           }
24874         }, {
24875           type: "Feature",
24876           properties: {
24877             iso1A2: "GU",
24878             iso1A3: "GUM",
24879             iso1N3: "316",
24880             wikidata: "Q16635",
24881             nameEn: "Guam",
24882             aliases: ["US-GU"],
24883             country: "US",
24884             groups: ["Q1352230", "Q153732", "057", "009", "UN"],
24885             roadSpeedUnit: "mph",
24886             roadHeightUnit: "ft",
24887             callingCodes: ["1 671"]
24888           },
24889           geometry: {
24890             type: "MultiPolygon",
24891             coordinates: [[[[146.25931, 13.85876], [143.82485, 13.92273], [144.61642, 12.82462], [146.25931, 13.85876]]]]
24892           }
24893         }, {
24894           type: "Feature",
24895           properties: {
24896             iso1A2: "GW",
24897             iso1A3: "GNB",
24898             iso1N3: "624",
24899             wikidata: "Q1007",
24900             nameEn: "Guinea-Bissau",
24901             groups: ["011", "202", "002", "UN"],
24902             callingCodes: ["245"]
24903           },
24904           geometry: {
24905             type: "MultiPolygon",
24906             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]]]]
24907           }
24908         }, {
24909           type: "Feature",
24910           properties: {
24911             iso1A2: "GY",
24912             iso1A3: "GUY",
24913             iso1N3: "328",
24914             wikidata: "Q734",
24915             nameEn: "Guyana",
24916             groups: ["005", "419", "019", "UN"],
24917             driveSide: "left",
24918             callingCodes: ["592"]
24919           },
24920           geometry: {
24921             type: "MultiPolygon",
24922             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]]]]
24923           }
24924         }, {
24925           type: "Feature",
24926           properties: {
24927             iso1A2: "HK",
24928             iso1A3: "HKG",
24929             iso1N3: "344",
24930             wikidata: "Q8646",
24931             nameEn: "Hong Kong",
24932             country: "CN",
24933             groups: ["030", "142", "UN"],
24934             driveSide: "left",
24935             callingCodes: ["852"]
24936           },
24937           geometry: {
24938             type: "MultiPolygon",
24939             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]]]]
24940           }
24941         }, {
24942           type: "Feature",
24943           properties: {
24944             iso1A2: "HM",
24945             iso1A3: "HMD",
24946             iso1N3: "334",
24947             wikidata: "Q131198",
24948             nameEn: "Heard Island and McDonald Islands",
24949             country: "AU",
24950             groups: ["053", "009", "UN"],
24951             driveSide: "left"
24952           },
24953           geometry: {
24954             type: "MultiPolygon",
24955             coordinates: [[[[71.08716, -53.87687], [75.44182, -53.99822], [72.87012, -51.48322], [71.08716, -53.87687]]]]
24956           }
24957         }, {
24958           type: "Feature",
24959           properties: {
24960             iso1A2: "HN",
24961             iso1A3: "HND",
24962             iso1N3: "340",
24963             wikidata: "Q783",
24964             nameEn: "Honduras",
24965             groups: ["013", "003", "419", "019", "UN"],
24966             callingCodes: ["504"]
24967           },
24968           geometry: {
24969             type: "MultiPolygon",
24970             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]]]]
24971           }
24972         }, {
24973           type: "Feature",
24974           properties: {
24975             iso1A2: "HR",
24976             iso1A3: "HRV",
24977             iso1N3: "191",
24978             wikidata: "Q224",
24979             nameEn: "Croatia",
24980             groups: ["EU", "039", "150", "UN"],
24981             callingCodes: ["385"]
24982           },
24983           geometry: {
24984             type: "MultiPolygon",
24985             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]]]]
24986           }
24987         }, {
24988           type: "Feature",
24989           properties: {
24990             iso1A2: "HT",
24991             iso1A3: "HTI",
24992             iso1N3: "332",
24993             wikidata: "Q790",
24994             nameEn: "Haiti",
24995             aliases: ["RH"],
24996             groups: ["029", "003", "419", "019", "UN"],
24997             callingCodes: ["509"]
24998           },
24999           geometry: {
25000             type: "MultiPolygon",
25001             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]]]]
25002           }
25003         }, {
25004           type: "Feature",
25005           properties: {
25006             iso1A2: "HU",
25007             iso1A3: "HUN",
25008             iso1N3: "348",
25009             wikidata: "Q28",
25010             nameEn: "Hungary",
25011             groups: ["EU", "151", "150", "UN"],
25012             callingCodes: ["36"]
25013           },
25014           geometry: {
25015             type: "MultiPolygon",
25016             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]]]]
25017           }
25018         }, {
25019           type: "Feature",
25020           properties: {
25021             iso1A2: "IC",
25022             wikidata: "Q5813",
25023             nameEn: "Canary Islands",
25024             country: "ES",
25025             groups: ["Q3320166", "Q105472", "EU", "039", "150", "UN"],
25026             isoStatus: "excRes",
25027             callingCodes: ["34"]
25028           },
25029           geometry: {
25030             type: "MultiPolygon",
25031             coordinates: [[[[-12.00985, 30.24121], [-25.3475, 27.87574], [-14.43883, 27.02969], [-12.00985, 30.24121]]]]
25032           }
25033         }, {
25034           type: "Feature",
25035           properties: {
25036             iso1A2: "ID",
25037             iso1A3: "IDN",
25038             iso1N3: "360",
25039             wikidata: "Q252",
25040             nameEn: "Indonesia",
25041             aliases: ["RI"]
25042           },
25043           geometry: null
25044         }, {
25045           type: "Feature",
25046           properties: {
25047             iso1A2: "IE",
25048             iso1A3: "IRL",
25049             iso1N3: "372",
25050             wikidata: "Q27",
25051             nameEn: "Republic of Ireland",
25052             groups: ["EU", "Q22890", "154", "150", "UN"],
25053             driveSide: "left",
25054             callingCodes: ["353"]
25055           },
25056           geometry: {
25057             type: "MultiPolygon",
25058             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]]]]
25059           }
25060         }, {
25061           type: "Feature",
25062           properties: {
25063             iso1A2: "IL",
25064             iso1A3: "ISR",
25065             iso1N3: "376",
25066             wikidata: "Q801",
25067             nameEn: "Israel",
25068             groups: ["145", "142", "UN"],
25069             callingCodes: ["972"]
25070           },
25071           geometry: {
25072             type: "MultiPolygon",
25073             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]]]]
25074           }
25075         }, {
25076           type: "Feature",
25077           properties: {
25078             iso1A2: "IM",
25079             iso1A3: "IMN",
25080             iso1N3: "833",
25081             wikidata: "Q9676",
25082             nameEn: "Isle of Man",
25083             country: "GB",
25084             groups: ["Q185086", "154", "150", "UN"],
25085             driveSide: "left",
25086             roadSpeedUnit: "mph",
25087             roadHeightUnit: "ft",
25088             callingCodes: ["44 01624", "44 07624", "44 07524", "44 07924"]
25089           },
25090           geometry: {
25091             type: "MultiPolygon",
25092             coordinates: [[[[-3.98763, 54.07351], [-4.1819, 54.57861], [-5.6384, 53.81157], [-3.98763, 54.07351]]]]
25093           }
25094         }, {
25095           type: "Feature",
25096           properties: {
25097             iso1A2: "IN",
25098             iso1A3: "IND",
25099             iso1N3: "356",
25100             wikidata: "Q668",
25101             nameEn: "India"
25102           },
25103           geometry: null
25104         }, {
25105           type: "Feature",
25106           properties: {
25107             iso1A2: "IO",
25108             iso1A3: "IOT",
25109             iso1N3: "086",
25110             wikidata: "Q43448",
25111             nameEn: "British Indian Ocean Territory",
25112             country: "GB"
25113           },
25114           geometry: null
25115         }, {
25116           type: "Feature",
25117           properties: {
25118             iso1A2: "IQ",
25119             iso1A3: "IRQ",
25120             iso1N3: "368",
25121             wikidata: "Q796",
25122             nameEn: "Iraq",
25123             groups: ["145", "142", "UN"],
25124             callingCodes: ["964"]
25125           },
25126           geometry: {
25127             type: "MultiPolygon",
25128             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]]]]
25129           }
25130         }, {
25131           type: "Feature",
25132           properties: {
25133             iso1A2: "IR",
25134             iso1A3: "IRN",
25135             iso1N3: "364",
25136             wikidata: "Q794",
25137             nameEn: "Iran",
25138             groups: ["034", "142", "UN"],
25139             callingCodes: ["98"]
25140           },
25141           geometry: {
25142             type: "MultiPolygon",
25143             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]]]]
25144           }
25145         }, {
25146           type: "Feature",
25147           properties: {
25148             iso1A2: "IS",
25149             iso1A3: "ISL",
25150             iso1N3: "352",
25151             wikidata: "Q189",
25152             nameEn: "Iceland",
25153             groups: ["154", "150", "UN"],
25154             callingCodes: ["354"]
25155           },
25156           geometry: {
25157             type: "MultiPolygon",
25158             coordinates: [[[[-33.15676, 62.62995], [-8.25539, 63.0423], [-15.70914, 69.67442], [-33.15676, 62.62995]]]]
25159           }
25160         }, {
25161           type: "Feature",
25162           properties: {
25163             iso1A2: "IT",
25164             iso1A3: "ITA",
25165             iso1N3: "380",
25166             wikidata: "Q38",
25167             nameEn: "Italy",
25168             groups: ["EU", "039", "150", "UN"],
25169             callingCodes: ["39"]
25170           },
25171           geometry: {
25172             type: "MultiPolygon",
25173             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]]]]
25174           }
25175         }, {
25176           type: "Feature",
25177           properties: {
25178             iso1A2: "JE",
25179             iso1A3: "JEY",
25180             iso1N3: "832",
25181             wikidata: "Q785",
25182             nameEn: "Bailiwick of Jersey",
25183             country: "GB",
25184             groups: ["830", "Q185086", "154", "150", "UN"],
25185             driveSide: "left",
25186             roadSpeedUnit: "mph",
25187             roadHeightUnit: "ft",
25188             callingCodes: ["44 01534"]
25189           },
25190           geometry: {
25191             type: "MultiPolygon",
25192             coordinates: [[[[-2.00491, 48.86706], [-1.83944, 49.23037], [-2.09454, 49.46288], [-2.65349, 49.15373], [-2.00491, 48.86706]]]]
25193           }
25194         }, {
25195           type: "Feature",
25196           properties: {
25197             iso1A2: "JM",
25198             iso1A3: "JAM",
25199             iso1N3: "388",
25200             wikidata: "Q766",
25201             nameEn: "Jamaica",
25202             aliases: ["JA"],
25203             groups: ["029", "003", "419", "019", "UN"],
25204             driveSide: "left",
25205             callingCodes: ["1 876", "1 658"]
25206           },
25207           geometry: {
25208             type: "MultiPolygon",
25209             coordinates: [[[[-74.09729, 17.36817], [-78.9741, 19.59515], [-78.34606, 16.57862], [-74.09729, 17.36817]]]]
25210           }
25211         }, {
25212           type: "Feature",
25213           properties: {
25214             iso1A2: "JO",
25215             iso1A3: "JOR",
25216             iso1N3: "400",
25217             wikidata: "Q810",
25218             nameEn: "Jordan",
25219             groups: ["145", "142", "UN"],
25220             callingCodes: ["962"]
25221           },
25222           geometry: {
25223             type: "MultiPolygon",
25224             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]]]]
25225           }
25226         }, {
25227           type: "Feature",
25228           properties: {
25229             iso1A2: "JP",
25230             iso1A3: "JPN",
25231             iso1N3: "392",
25232             wikidata: "Q17",
25233             nameEn: "Japan",
25234             groups: ["030", "142", "UN"],
25235             driveSide: "left",
25236             callingCodes: ["81"]
25237           },
25238           geometry: {
25239             type: "MultiPolygon",
25240             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]]]]
25241           }
25242         }, {
25243           type: "Feature",
25244           properties: {
25245             iso1A2: "KE",
25246             iso1A3: "KEN",
25247             iso1N3: "404",
25248             wikidata: "Q114",
25249             nameEn: "Kenya",
25250             groups: ["014", "202", "002", "UN"],
25251             driveSide: "left",
25252             callingCodes: ["254"]
25253           },
25254           geometry: {
25255             type: "MultiPolygon",
25256             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]]]]
25257           }
25258         }, {
25259           type: "Feature",
25260           properties: {
25261             iso1A2: "KG",
25262             iso1A3: "KGZ",
25263             iso1N3: "417",
25264             wikidata: "Q813",
25265             nameEn: "Kyrgyzstan",
25266             groups: ["143", "142", "UN"],
25267             callingCodes: ["996"]
25268           },
25269           geometry: {
25270             type: "MultiPolygon",
25271             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]]]]
25272           }
25273         }, {
25274           type: "Feature",
25275           properties: {
25276             iso1A2: "KH",
25277             iso1A3: "KHM",
25278             iso1N3: "116",
25279             wikidata: "Q424",
25280             nameEn: "Cambodia",
25281             groups: ["035", "142", "UN"],
25282             callingCodes: ["855"]
25283           },
25284           geometry: {
25285             type: "MultiPolygon",
25286             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]]]]
25287           }
25288         }, {
25289           type: "Feature",
25290           properties: {
25291             iso1A2: "KI",
25292             iso1A3: "KIR",
25293             iso1N3: "296",
25294             wikidata: "Q710",
25295             nameEn: "Kiribati",
25296             groups: ["057", "009", "UN"],
25297             driveSide: "left",
25298             callingCodes: ["686"]
25299           },
25300           geometry: {
25301             type: "MultiPolygon",
25302             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]]]]
25303           }
25304         }, {
25305           type: "Feature",
25306           properties: {
25307             iso1A2: "KM",
25308             iso1A3: "COM",
25309             iso1N3: "174",
25310             wikidata: "Q970",
25311             nameEn: "Comoros",
25312             groups: ["014", "202", "002", "UN"],
25313             callingCodes: ["269"]
25314           },
25315           geometry: {
25316             type: "MultiPolygon",
25317             coordinates: [[[[42.63904, -10.02522], [43.28731, -13.97126], [45.4971, -11.75965], [42.63904, -10.02522]]]]
25318           }
25319         }, {
25320           type: "Feature",
25321           properties: {
25322             iso1A2: "KN",
25323             iso1A3: "KNA",
25324             iso1N3: "659",
25325             wikidata: "Q763",
25326             nameEn: "St. Kitts and Nevis",
25327             groups: ["029", "003", "419", "019", "UN"],
25328             driveSide: "left",
25329             roadSpeedUnit: "mph",
25330             callingCodes: ["1 869"]
25331           },
25332           geometry: {
25333             type: "MultiPolygon",
25334             coordinates: [[[[-62.29333, 17.43155], [-62.76692, 17.64353], [-63.09677, 17.21372], [-62.63813, 16.65446], [-62.29333, 17.43155]]]]
25335           }
25336         }, {
25337           type: "Feature",
25338           properties: {
25339             iso1A2: "KP",
25340             iso1A3: "PRK",
25341             iso1N3: "408",
25342             wikidata: "Q423",
25343             nameEn: "North Korea",
25344             groups: ["030", "142", "UN"],
25345             callingCodes: ["850"]
25346           },
25347           geometry: {
25348             type: "MultiPolygon",
25349             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]]]]
25350           }
25351         }, {
25352           type: "Feature",
25353           properties: {
25354             iso1A2: "KR",
25355             iso1A3: "KOR",
25356             iso1N3: "410",
25357             wikidata: "Q884",
25358             nameEn: "South Korea",
25359             groups: ["030", "142", "UN"],
25360             callingCodes: ["82"]
25361           },
25362           geometry: {
25363             type: "MultiPolygon",
25364             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]]]]
25365           }
25366         }, {
25367           type: "Feature",
25368           properties: {
25369             iso1A2: "KW",
25370             iso1A3: "KWT",
25371             iso1N3: "414",
25372             wikidata: "Q817",
25373             nameEn: "Kuwait",
25374             groups: ["145", "142", "UN"],
25375             callingCodes: ["965"]
25376           },
25377           geometry: {
25378             type: "MultiPolygon",
25379             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]]]]
25380           }
25381         }, {
25382           type: "Feature",
25383           properties: {
25384             iso1A2: "KY",
25385             iso1A3: "CYM",
25386             iso1N3: "136",
25387             wikidata: "Q5785",
25388             nameEn: "Cayman Islands",
25389             country: "GB",
25390             groups: ["BOTS", "029", "003", "419", "019", "UN"],
25391             driveSide: "left",
25392             roadSpeedUnit: "mph",
25393             roadHeightUnit: "ft",
25394             callingCodes: ["1 345"]
25395           },
25396           geometry: {
25397             type: "MultiPolygon",
25398             coordinates: [[[[-82.11509, 19.60401], [-80.36068, 18.11751], [-79.32727, 20.06742], [-82.11509, 19.60401]]]]
25399           }
25400         }, {
25401           type: "Feature",
25402           properties: {
25403             iso1A2: "KZ",
25404             iso1A3: "KAZ",
25405             iso1N3: "398",
25406             wikidata: "Q232",
25407             nameEn: "Kazakhstan",
25408             groups: ["143", "142", "UN"],
25409             callingCodes: ["7"]
25410           },
25411           geometry: {
25412             type: "MultiPolygon",
25413             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]]]]
25414           }
25415         }, {
25416           type: "Feature",
25417           properties: {
25418             iso1A2: "LA",
25419             iso1A3: "LAO",
25420             iso1N3: "418",
25421             wikidata: "Q819",
25422             nameEn: "Laos",
25423             groups: ["035", "142", "UN"],
25424             callingCodes: ["856"]
25425           },
25426           geometry: {
25427             type: "MultiPolygon",
25428             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]]]]
25429           }
25430         }, {
25431           type: "Feature",
25432           properties: {
25433             iso1A2: "LB",
25434             iso1A3: "LBN",
25435             iso1N3: "422",
25436             wikidata: "Q822",
25437             nameEn: "Lebanon",
25438             aliases: ["RL"],
25439             groups: ["145", "142", "UN"],
25440             callingCodes: ["961"]
25441           },
25442           geometry: {
25443             type: "MultiPolygon",
25444             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]]]]
25445           }
25446         }, {
25447           type: "Feature",
25448           properties: {
25449             iso1A2: "LC",
25450             iso1A3: "LCA",
25451             iso1N3: "662",
25452             wikidata: "Q760",
25453             nameEn: "St. Lucia",
25454             aliases: ["WL"],
25455             groups: ["029", "003", "419", "019", "UN"],
25456             driveSide: "left",
25457             roadSpeedUnit: "mph",
25458             callingCodes: ["1 758"]
25459           },
25460           geometry: {
25461             type: "MultiPolygon",
25462             coordinates: [[[[-59.95997, 14.20285], [-61.69315, 14.26451], [-59.94058, 12.34011], [-59.95997, 14.20285]]]]
25463           }
25464         }, {
25465           type: "Feature",
25466           properties: {
25467             iso1A2: "LI",
25468             iso1A3: "LIE",
25469             iso1N3: "438",
25470             wikidata: "Q347",
25471             nameEn: "Liechtenstein",
25472             aliases: ["FL"],
25473             groups: ["155", "150", "UN"],
25474             callingCodes: ["423"]
25475           },
25476           geometry: {
25477             type: "MultiPolygon",
25478             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]]]]
25479           }
25480         }, {
25481           type: "Feature",
25482           properties: {
25483             iso1A2: "LK",
25484             iso1A3: "LKA",
25485             iso1N3: "144",
25486             wikidata: "Q854",
25487             nameEn: "Sri Lanka",
25488             groups: ["034", "142", "UN"],
25489             driveSide: "left",
25490             callingCodes: ["94"]
25491           },
25492           geometry: {
25493             type: "MultiPolygon",
25494             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]]]]
25495           }
25496         }, {
25497           type: "Feature",
25498           properties: {
25499             iso1A2: "LR",
25500             iso1A3: "LBR",
25501             iso1N3: "430",
25502             wikidata: "Q1014",
25503             nameEn: "Liberia",
25504             groups: ["011", "202", "002", "UN"],
25505             callingCodes: ["231"]
25506           },
25507           geometry: {
25508             type: "MultiPolygon",
25509             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]]]]
25510           }
25511         }, {
25512           type: "Feature",
25513           properties: {
25514             iso1A2: "LS",
25515             iso1A3: "LSO",
25516             iso1N3: "426",
25517             wikidata: "Q1013",
25518             nameEn: "Lesotho",
25519             groups: ["018", "202", "002", "UN"],
25520             driveSide: "left",
25521             callingCodes: ["266"]
25522           },
25523           geometry: {
25524             type: "MultiPolygon",
25525             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]]]]
25526           }
25527         }, {
25528           type: "Feature",
25529           properties: {
25530             iso1A2: "LT",
25531             iso1A3: "LTU",
25532             iso1N3: "440",
25533             wikidata: "Q37",
25534             nameEn: "Lithuania",
25535             groups: ["EU", "154", "150", "UN"],
25536             callingCodes: ["370"]
25537           },
25538           geometry: {
25539             type: "MultiPolygon",
25540             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]]]]
25541           }
25542         }, {
25543           type: "Feature",
25544           properties: {
25545             iso1A2: "LU",
25546             iso1A3: "LUX",
25547             iso1N3: "442",
25548             wikidata: "Q32",
25549             nameEn: "Luxembourg",
25550             groups: ["EU", "155", "150", "UN"],
25551             callingCodes: ["352"]
25552           },
25553           geometry: {
25554             type: "MultiPolygon",
25555             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]]]]
25556           }
25557         }, {
25558           type: "Feature",
25559           properties: {
25560             iso1A2: "LV",
25561             iso1A3: "LVA",
25562             iso1N3: "428",
25563             wikidata: "Q211",
25564             nameEn: "Latvia",
25565             groups: ["EU", "154", "150", "UN"],
25566             callingCodes: ["371"]
25567           },
25568           geometry: {
25569             type: "MultiPolygon",
25570             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]]]]
25571           }
25572         }, {
25573           type: "Feature",
25574           properties: {
25575             iso1A2: "LY",
25576             iso1A3: "LBY",
25577             iso1N3: "434",
25578             wikidata: "Q1016",
25579             nameEn: "Libya",
25580             groups: ["015", "002", "UN"],
25581             callingCodes: ["218"]
25582           },
25583           geometry: {
25584             type: "MultiPolygon",
25585             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]]]]
25586           }
25587         }, {
25588           type: "Feature",
25589           properties: {
25590             iso1A2: "MA",
25591             iso1A3: "MAR",
25592             iso1N3: "504",
25593             wikidata: "Q1028",
25594             nameEn: "Morocco",
25595             groups: ["015", "002", "UN"],
25596             callingCodes: ["212"]
25597           },
25598           geometry: {
25599             type: "MultiPolygon",
25600             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]]]]
25601           }
25602         }, {
25603           type: "Feature",
25604           properties: {
25605             iso1A2: "MC",
25606             iso1A3: "MCO",
25607             iso1N3: "492",
25608             wikidata: "Q235",
25609             nameEn: "Monaco",
25610             groups: ["155", "150", "UN"],
25611             callingCodes: ["377"]
25612           },
25613           geometry: {
25614             type: "MultiPolygon",
25615             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]]]]
25616           }
25617         }, {
25618           type: "Feature",
25619           properties: {
25620             iso1A2: "MD",
25621             iso1A3: "MDA",
25622             iso1N3: "498",
25623             wikidata: "Q217",
25624             nameEn: "Moldova",
25625             groups: ["151", "150", "UN"],
25626             callingCodes: ["373"]
25627           },
25628           geometry: {
25629             type: "MultiPolygon",
25630             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]]]]
25631           }
25632         }, {
25633           type: "Feature",
25634           properties: {
25635             iso1A2: "ME",
25636             iso1A3: "MNE",
25637             iso1N3: "499",
25638             wikidata: "Q236",
25639             nameEn: "Montenegro",
25640             groups: ["039", "150", "UN"],
25641             callingCodes: ["382"]
25642           },
25643           geometry: {
25644             type: "MultiPolygon",
25645             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]]]]
25646           }
25647         }, {
25648           type: "Feature",
25649           properties: {
25650             iso1A2: "MF",
25651             iso1A3: "MAF",
25652             iso1N3: "663",
25653             wikidata: "Q126125",
25654             nameEn: "Saint-Martin",
25655             country: "FR",
25656             groups: ["Q3320166", "EU", "029", "003", "419", "019", "UN"],
25657             callingCodes: ["590"]
25658           },
25659           geometry: {
25660             type: "MultiPolygon",
25661             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]]]]
25662           }
25663         }, {
25664           type: "Feature",
25665           properties: {
25666             iso1A2: "MG",
25667             iso1A3: "MDG",
25668             iso1N3: "450",
25669             wikidata: "Q1019",
25670             nameEn: "Madagascar",
25671             aliases: ["RM"],
25672             groups: ["014", "202", "002", "UN"],
25673             callingCodes: ["261"]
25674           },
25675           geometry: {
25676             type: "MultiPolygon",
25677             coordinates: [[[[51.93891, -10.85085], [45.84651, -12.77177], [42.14681, -19.63341], [45.80092, -33.00974], [51.93891, -10.85085]]]]
25678           }
25679         }, {
25680           type: "Feature",
25681           properties: {
25682             iso1A2: "MH",
25683             iso1A3: "MHL",
25684             iso1N3: "584",
25685             wikidata: "Q709",
25686             nameEn: "Marshall Islands",
25687             groups: ["057", "009", "UN"],
25688             roadSpeedUnit: "mph",
25689             callingCodes: ["692"]
25690           },
25691           geometry: {
25692             type: "MultiPolygon",
25693             coordinates: [[[[169, 3.9], [173.53711, 5.70687], [169.29099, 15.77133], [159.04653, 10.59067], [169, 3.9]]]]
25694           }
25695         }, {
25696           type: "Feature",
25697           properties: {
25698             iso1A2: "MK",
25699             iso1A3: "MKD",
25700             iso1N3: "807",
25701             wikidata: "Q221",
25702             nameEn: "North Macedonia",
25703             groups: ["039", "150", "UN"],
25704             callingCodes: ["389"]
25705           },
25706           geometry: {
25707             type: "MultiPolygon",
25708             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]]]]
25709           }
25710         }, {
25711           type: "Feature",
25712           properties: {
25713             iso1A2: "ML",
25714             iso1A3: "MLI",
25715             iso1N3: "466",
25716             wikidata: "Q912",
25717             nameEn: "Mali",
25718             groups: ["011", "202", "002", "UN"],
25719             callingCodes: ["223"]
25720           },
25721           geometry: {
25722             type: "MultiPolygon",
25723             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]]]]
25724           }
25725         }, {
25726           type: "Feature",
25727           properties: {
25728             iso1A2: "MM",
25729             iso1A3: "MMR",
25730             iso1N3: "104",
25731             wikidata: "Q836",
25732             nameEn: "Myanmar",
25733             aliases: ["Burma", "BU"],
25734             groups: ["035", "142", "UN"],
25735             callingCodes: ["95"]
25736           },
25737           geometry: {
25738             type: "MultiPolygon",
25739             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]]]]
25740           }
25741         }, {
25742           type: "Feature",
25743           properties: {
25744             iso1A2: "MN",
25745             iso1A3: "MNG",
25746             iso1N3: "496",
25747             wikidata: "Q711",
25748             nameEn: "Mongolia",
25749             groups: ["030", "142", "UN"],
25750             callingCodes: ["976"]
25751           },
25752           geometry: {
25753             type: "MultiPolygon",
25754             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]]]]
25755           }
25756         }, {
25757           type: "Feature",
25758           properties: {
25759             iso1A2: "MO",
25760             iso1A3: "MAC",
25761             iso1N3: "446",
25762             wikidata: "Q14773",
25763             nameEn: "Macau",
25764             aliases: ["Macao"],
25765             country: "CN",
25766             groups: ["030", "142", "UN"],
25767             driveSide: "left",
25768             callingCodes: ["853"]
25769           },
25770           geometry: {
25771             type: "MultiPolygon",
25772             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]]]]
25773           }
25774         }, {
25775           type: "Feature",
25776           properties: {
25777             iso1A2: "MP",
25778             iso1A3: "MNP",
25779             iso1N3: "580",
25780             wikidata: "Q16644",
25781             nameEn: "Northern Mariana Islands",
25782             aliases: ["US-MP"],
25783             country: "US",
25784             groups: ["Q1352230", "Q153732", "057", "009", "UN"],
25785             roadSpeedUnit: "mph",
25786             callingCodes: ["1 670"]
25787           },
25788           geometry: {
25789             type: "MultiPolygon",
25790             coordinates: [[[[135.52896, 14.32623], [152.19114, 13.63487], [145.05972, 21.28731], [135.52896, 14.32623]]]]
25791           }
25792         }, {
25793           type: "Feature",
25794           properties: {
25795             iso1A2: "MQ",
25796             iso1A3: "MTQ",
25797             iso1N3: "474",
25798             wikidata: "Q17054",
25799             nameEn: "Martinique",
25800             country: "FR",
25801             groups: ["Q3320166", "EU", "029", "003", "419", "019", "UN"],
25802             callingCodes: ["596"]
25803           },
25804           geometry: {
25805             type: "MultiPolygon",
25806             coordinates: [[[[-59.95997, 14.20285], [-61.07821, 15.25109], [-61.69315, 14.26451], [-59.95997, 14.20285]]]]
25807           }
25808         }, {
25809           type: "Feature",
25810           properties: {
25811             iso1A2: "MR",
25812             iso1A3: "MRT",
25813             iso1N3: "478",
25814             wikidata: "Q1025",
25815             nameEn: "Mauritania",
25816             groups: ["011", "202", "002", "UN"],
25817             callingCodes: ["222"]
25818           },
25819           geometry: {
25820             type: "MultiPolygon",
25821             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]]]]
25822           }
25823         }, {
25824           type: "Feature",
25825           properties: {
25826             iso1A2: "MS",
25827             iso1A3: "MSR",
25828             iso1N3: "500",
25829             wikidata: "Q13353",
25830             nameEn: "Montserrat",
25831             country: "GB",
25832             groups: ["BOTS", "029", "003", "419", "019", "UN"],
25833             driveSide: "left",
25834             roadSpeedUnit: "mph",
25835             roadHeightUnit: "ft",
25836             callingCodes: ["1 664"]
25837           },
25838           geometry: {
25839             type: "MultiPolygon",
25840             coordinates: [[[[-61.91508, 16.51165], [-62.1023, 16.97277], [-62.58307, 16.68909], [-61.91508, 16.51165]]]]
25841           }
25842         }, {
25843           type: "Feature",
25844           properties: {
25845             iso1A2: "MT",
25846             iso1A3: "MLT",
25847             iso1N3: "470",
25848             wikidata: "Q233",
25849             nameEn: "Malta",
25850             groups: ["EU", "039", "150", "UN"],
25851             driveSide: "left",
25852             callingCodes: ["356"]
25853           },
25854           geometry: {
25855             type: "MultiPolygon",
25856             coordinates: [[[[15.70991, 35.79901], [14.07544, 36.41525], [13.27636, 35.20764], [15.70991, 35.79901]]]]
25857           }
25858         }, {
25859           type: "Feature",
25860           properties: {
25861             iso1A2: "MU",
25862             iso1A3: "MUS",
25863             iso1N3: "480",
25864             wikidata: "Q1027",
25865             nameEn: "Mauritius",
25866             groups: ["014", "202", "002", "UN"],
25867             driveSide: "left",
25868             callingCodes: ["230"]
25869           },
25870           geometry: {
25871             type: "MultiPolygon",
25872             coordinates: [[[[56.09755, -9.55401], [57.50644, -31.92637], [68.4673, -19.15185], [56.09755, -9.55401]]]]
25873           }
25874         }, {
25875           type: "Feature",
25876           properties: {
25877             iso1A2: "MV",
25878             iso1A3: "MDV",
25879             iso1N3: "462",
25880             wikidata: "Q826",
25881             nameEn: "Maldives",
25882             groups: ["034", "142", "UN"],
25883             driveSide: "left",
25884             callingCodes: ["960"]
25885           },
25886           geometry: {
25887             type: "MultiPolygon",
25888             coordinates: [[[[71.9161, 8.55531], [72.57428, -3.7623], [76.59015, 5.591], [71.9161, 8.55531]]]]
25889           }
25890         }, {
25891           type: "Feature",
25892           properties: {
25893             iso1A2: "MW",
25894             iso1A3: "MWI",
25895             iso1N3: "454",
25896             wikidata: "Q1020",
25897             nameEn: "Malawi",
25898             groups: ["014", "202", "002", "UN"],
25899             driveSide: "left",
25900             callingCodes: ["265"]
25901           },
25902           geometry: {
25903             type: "MultiPolygon",
25904             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]]]]
25905           }
25906         }, {
25907           type: "Feature",
25908           properties: {
25909             iso1A2: "MX",
25910             iso1A3: "MEX",
25911             iso1N3: "484",
25912             wikidata: "Q96",
25913             nameEn: "Mexico",
25914             groups: ["013", "003", "419", "019", "UN"],
25915             callingCodes: ["52"]
25916           },
25917           geometry: {
25918             type: "MultiPolygon",
25919             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]]]]
25920           }
25921         }, {
25922           type: "Feature",
25923           properties: {
25924             iso1A2: "MY",
25925             iso1A3: "MYS",
25926             iso1N3: "458",
25927             wikidata: "Q833",
25928             nameEn: "Malaysia"
25929           },
25930           geometry: null
25931         }, {
25932           type: "Feature",
25933           properties: {
25934             iso1A2: "MZ",
25935             iso1A3: "MOZ",
25936             iso1N3: "508",
25937             wikidata: "Q1029",
25938             nameEn: "Mozambique",
25939             groups: ["014", "202", "002", "UN"],
25940             driveSide: "left",
25941             callingCodes: ["258"]
25942           },
25943           geometry: {
25944             type: "MultiPolygon",
25945             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]]]]
25946           }
25947         }, {
25948           type: "Feature",
25949           properties: {
25950             iso1A2: "NA",
25951             iso1A3: "NAM",
25952             iso1N3: "516",
25953             wikidata: "Q1030",
25954             nameEn: "Namibia",
25955             groups: ["018", "202", "002", "UN"],
25956             driveSide: "left",
25957             callingCodes: ["264"]
25958           },
25959           geometry: {
25960             type: "MultiPolygon",
25961             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]]]]
25962           }
25963         }, {
25964           type: "Feature",
25965           properties: {
25966             iso1A2: "NC",
25967             iso1A3: "NCL",
25968             iso1N3: "540",
25969             wikidata: "Q33788",
25970             nameEn: "New Caledonia",
25971             country: "FR",
25972             groups: ["Q1451600", "054", "009", "UN"],
25973             callingCodes: ["687"]
25974           },
25975           geometry: {
25976             type: "MultiPolygon",
25977             coordinates: [[[[159.77159, -28.41151], [174.245, -23.1974], [156.73836, -14.50464], [159.77159, -28.41151]]]]
25978           }
25979         }, {
25980           type: "Feature",
25981           properties: {
25982             iso1A2: "NE",
25983             iso1A3: "NER",
25984             iso1N3: "562",
25985             wikidata: "Q1032",
25986             nameEn: "Niger",
25987             aliases: ["RN"],
25988             groups: ["011", "202", "002", "UN"],
25989             callingCodes: ["227"]
25990           },
25991           geometry: {
25992             type: "MultiPolygon",
25993             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]]]]
25994           }
25995         }, {
25996           type: "Feature",
25997           properties: {
25998             iso1A2: "NF",
25999             iso1A3: "NFK",
26000             iso1N3: "574",
26001             wikidata: "Q31057",
26002             nameEn: "Norfolk Island",
26003             country: "AU",
26004             groups: ["053", "009", "UN"],
26005             driveSide: "left",
26006             callingCodes: ["672 3"]
26007           },
26008           geometry: {
26009             type: "MultiPolygon",
26010             coordinates: [[[[169.82316, -28.16667], [166.29505, -28.29175], [167.94076, -30.60745], [169.82316, -28.16667]]]]
26011           }
26012         }, {
26013           type: "Feature",
26014           properties: {
26015             iso1A2: "NG",
26016             iso1A3: "NGA",
26017             iso1N3: "566",
26018             wikidata: "Q1033",
26019             nameEn: "Nigeria",
26020             groups: ["011", "202", "002", "UN"],
26021             callingCodes: ["234"]
26022           },
26023           geometry: {
26024             type: "MultiPolygon",
26025             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]]]]
26026           }
26027         }, {
26028           type: "Feature",
26029           properties: {
26030             iso1A2: "NI",
26031             iso1A3: "NIC",
26032             iso1N3: "558",
26033             wikidata: "Q811",
26034             nameEn: "Nicaragua",
26035             groups: ["013", "003", "419", "019", "UN"],
26036             callingCodes: ["505"]
26037           },
26038           geometry: {
26039             type: "MultiPolygon",
26040             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]]]]
26041           }
26042         }, {
26043           type: "Feature",
26044           properties: {
26045             iso1A2: "NL",
26046             iso1A3: "NLD",
26047             iso1N3: "528",
26048             wikidata: "Q29999",
26049             nameEn: "Kingdom of the Netherlands"
26050           },
26051           geometry: null
26052         }, {
26053           type: "Feature",
26054           properties: {
26055             iso1A2: "NO",
26056             iso1A3: "NOR",
26057             iso1N3: "578",
26058             wikidata: "Q20",
26059             nameEn: "Norway"
26060           },
26061           geometry: null
26062         }, {
26063           type: "Feature",
26064           properties: {
26065             iso1A2: "NP",
26066             iso1A3: "NPL",
26067             iso1N3: "524",
26068             wikidata: "Q837",
26069             nameEn: "Nepal",
26070             groups: ["034", "142", "UN"],
26071             driveSide: "left",
26072             callingCodes: ["977"]
26073           },
26074           geometry: {
26075             type: "MultiPolygon",
26076             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]]]]
26077           }
26078         }, {
26079           type: "Feature",
26080           properties: {
26081             iso1A2: "NR",
26082             iso1A3: "NRU",
26083             iso1N3: "520",
26084             wikidata: "Q697",
26085             nameEn: "Nauru",
26086             groups: ["057", "009", "UN"],
26087             driveSide: "left",
26088             callingCodes: ["674"]
26089           },
26090           geometry: {
26091             type: "MultiPolygon",
26092             coordinates: [[[[166.95155, 0.14829], [166.21778, -0.7977], [167.60042, -0.88259], [166.95155, 0.14829]]]]
26093           }
26094         }, {
26095           type: "Feature",
26096           properties: {
26097             iso1A2: "NU",
26098             iso1A3: "NIU",
26099             iso1N3: "570",
26100             wikidata: "Q34020",
26101             nameEn: "Niue",
26102             country: "NZ",
26103             groups: ["061", "009", "UN"],
26104             driveSide: "left",
26105             callingCodes: ["683"]
26106           },
26107           geometry: {
26108             type: "MultiPolygon",
26109             coordinates: [[[[-170.83899, -18.53439], [-170.82274, -20.44429], [-168.63096, -18.60489], [-170.83899, -18.53439]]]]
26110           }
26111         }, {
26112           type: "Feature",
26113           properties: {
26114             iso1A2: "NZ",
26115             iso1A3: "NZL",
26116             iso1N3: "554",
26117             wikidata: "Q664",
26118             nameEn: "New Zealand"
26119           },
26120           geometry: null
26121         }, {
26122           type: "Feature",
26123           properties: {
26124             iso1A2: "OM",
26125             iso1A3: "OMN",
26126             iso1N3: "512",
26127             wikidata: "Q842",
26128             nameEn: "Oman",
26129             groups: ["145", "142", "UN"],
26130             callingCodes: ["968"]
26131           },
26132           geometry: {
26133             type: "MultiPolygon",
26134             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]]]]
26135           }
26136         }, {
26137           type: "Feature",
26138           properties: {
26139             iso1A2: "PA",
26140             iso1A3: "PAN",
26141             iso1N3: "591",
26142             wikidata: "Q804",
26143             nameEn: "Panama",
26144             groups: ["013", "003", "419", "019", "UN"],
26145             callingCodes: ["507"]
26146           },
26147           geometry: {
26148             type: "MultiPolygon",
26149             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]]]]
26150           }
26151         }, {
26152           type: "Feature",
26153           properties: {
26154             iso1A2: "PE",
26155             iso1A3: "PER",
26156             iso1N3: "604",
26157             wikidata: "Q419",
26158             nameEn: "Peru",
26159             groups: ["005", "419", "019", "UN"],
26160             callingCodes: ["51"]
26161           },
26162           geometry: {
26163             type: "MultiPolygon",
26164             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]]]]
26165           }
26166         }, {
26167           type: "Feature",
26168           properties: {
26169             iso1A2: "PF",
26170             iso1A3: "PYF",
26171             iso1N3: "258",
26172             wikidata: "Q30971",
26173             nameEn: "French Polynesia",
26174             country: "FR",
26175             groups: ["Q1451600", "061", "009", "UN"],
26176             callingCodes: ["689"]
26177           },
26178           geometry: {
26179             type: "MultiPolygon",
26180             coordinates: [[[[-135.59706, -4.70473], [-156.48634, -15.52824], [-156.45576, -31.75456], [-133.59543, -28.4709], [-135.59706, -4.70473]]]]
26181           }
26182         }, {
26183           type: "Feature",
26184           properties: {
26185             iso1A2: "PG",
26186             iso1A3: "PNG",
26187             iso1N3: "598",
26188             wikidata: "Q691",
26189             nameEn: "Papua New Guinea",
26190             groups: ["054", "009", "UN"],
26191             driveSide: "left",
26192             callingCodes: ["675"]
26193           },
26194           geometry: {
26195             type: "MultiPolygon",
26196             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]]]]
26197           }
26198         }, {
26199           type: "Feature",
26200           properties: {
26201             iso1A2: "PH",
26202             iso1A3: "PHL",
26203             iso1N3: "608",
26204             wikidata: "Q928",
26205             nameEn: "Philippines",
26206             aliases: ["PI", "RP"],
26207             groups: ["035", "142", "UN"],
26208             callingCodes: ["63"]
26209           },
26210           geometry: {
26211             type: "MultiPolygon",
26212             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]]]]
26213           }
26214         }, {
26215           type: "Feature",
26216           properties: {
26217             iso1A2: "PK",
26218             iso1A3: "PAK",
26219             iso1N3: "586",
26220             wikidata: "Q843",
26221             nameEn: "Pakistan",
26222             groups: ["034", "142", "UN"],
26223             driveSide: "left",
26224             callingCodes: ["92"]
26225           },
26226           geometry: {
26227             type: "MultiPolygon",
26228             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]]]]
26229           }
26230         }, {
26231           type: "Feature",
26232           properties: {
26233             iso1A2: "PL",
26234             iso1A3: "POL",
26235             iso1N3: "616",
26236             wikidata: "Q36",
26237             nameEn: "Poland",
26238             groups: ["EU", "151", "150", "UN"],
26239             callingCodes: ["48"]
26240           },
26241           geometry: {
26242             type: "MultiPolygon",
26243             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]]]]
26244           }
26245         }, {
26246           type: "Feature",
26247           properties: {
26248             iso1A2: "PM",
26249             iso1A3: "SPM",
26250             iso1N3: "666",
26251             wikidata: "Q34617",
26252             nameEn: "Saint Pierre and Miquelon",
26253             country: "FR",
26254             groups: ["Q1451600", "021", "003", "019", "UN"],
26255             callingCodes: ["508"]
26256           },
26257           geometry: {
26258             type: "MultiPolygon",
26259             coordinates: [[[[-56.72993, 46.65575], [-55.90758, 46.6223], [-56.27503, 47.39728], [-56.72993, 46.65575]]]]
26260           }
26261         }, {
26262           type: "Feature",
26263           properties: {
26264             iso1A2: "PN",
26265             iso1A3: "PCN",
26266             iso1N3: "612",
26267             wikidata: "Q35672",
26268             nameEn: "Pitcairn Islands",
26269             country: "GB",
26270             groups: ["BOTS", "061", "009", "UN"],
26271             driveSide: "left",
26272             callingCodes: ["64"]
26273           },
26274           geometry: {
26275             type: "MultiPolygon",
26276             coordinates: [[[[-133.59543, -28.4709], [-122.0366, -24.55017], [-133.61511, -21.93325], [-133.59543, -28.4709]]]]
26277           }
26278         }, {
26279           type: "Feature",
26280           properties: {
26281             iso1A2: "PR",
26282             iso1A3: "PRI",
26283             iso1N3: "630",
26284             wikidata: "Q1183",
26285             nameEn: "Puerto Rico",
26286             aliases: ["US-PR"],
26287             country: "US",
26288             groups: ["Q1352230", "029", "003", "419", "019", "UN"],
26289             roadSpeedUnit: "mph",
26290             callingCodes: ["1 787", "1 939"]
26291           },
26292           geometry: {
26293             type: "MultiPolygon",
26294             coordinates: [[[[-65.27974, 17.56928], [-65.02435, 18.73231], [-67.99519, 18.97186], [-68.23894, 17.84663], [-65.27974, 17.56928]]]]
26295           }
26296         }, {
26297           type: "Feature",
26298           properties: {
26299             iso1A2: "PS",
26300             iso1A3: "PSE",
26301             iso1N3: "275",
26302             wikidata: "Q219060",
26303             nameEn: "Palestine"
26304           },
26305           geometry: null
26306         }, {
26307           type: "Feature",
26308           properties: {
26309             iso1A2: "PT",
26310             iso1A3: "PRT",
26311             iso1N3: "620",
26312             wikidata: "Q45",
26313             nameEn: "Portugal"
26314           },
26315           geometry: null
26316         }, {
26317           type: "Feature",
26318           properties: {
26319             iso1A2: "PW",
26320             iso1A3: "PLW",
26321             iso1N3: "585",
26322             wikidata: "Q695",
26323             nameEn: "Palau",
26324             groups: ["057", "009", "UN"],
26325             roadSpeedUnit: "mph",
26326             callingCodes: ["680"]
26327           },
26328           geometry: {
26329             type: "MultiPolygon",
26330             coordinates: [[[[128.97621, 3.08804], [136.39296, 1.54187], [136.04605, 12.45908], [128.97621, 3.08804]]]]
26331           }
26332         }, {
26333           type: "Feature",
26334           properties: {
26335             iso1A2: "PY",
26336             iso1A3: "PRY",
26337             iso1N3: "600",
26338             wikidata: "Q733",
26339             nameEn: "Paraguay",
26340             groups: ["005", "419", "019", "UN"],
26341             callingCodes: ["595"]
26342           },
26343           geometry: {
26344             type: "MultiPolygon",
26345             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]]]]
26346           }
26347         }, {
26348           type: "Feature",
26349           properties: {
26350             iso1A2: "QA",
26351             iso1A3: "QAT",
26352             iso1N3: "634",
26353             wikidata: "Q846",
26354             nameEn: "Qatar",
26355             groups: ["145", "142", "UN"],
26356             callingCodes: ["974"]
26357           },
26358           geometry: {
26359             type: "MultiPolygon",
26360             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]]]]
26361           }
26362         }, {
26363           type: "Feature",
26364           properties: {
26365             iso1A2: "RE",
26366             iso1A3: "REU",
26367             iso1N3: "638",
26368             wikidata: "Q17070",
26369             nameEn: "R\xE9union",
26370             country: "FR",
26371             groups: ["Q3320166", "EU", "014", "202", "002", "UN"],
26372             callingCodes: ["262"]
26373           },
26374           geometry: {
26375             type: "MultiPolygon",
26376             coordinates: [[[[53.37984, -21.23941], [56.73473, -21.9174], [56.62373, -20.2711], [53.37984, -21.23941]]]]
26377           }
26378         }, {
26379           type: "Feature",
26380           properties: {
26381             iso1A2: "RO",
26382             iso1A3: "ROU",
26383             iso1N3: "642",
26384             wikidata: "Q218",
26385             nameEn: "Romania",
26386             groups: ["EU", "151", "150", "UN"],
26387             callingCodes: ["40"]
26388           },
26389           geometry: {
26390             type: "MultiPolygon",
26391             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]]]]
26392           }
26393         }, {
26394           type: "Feature",
26395           properties: {
26396             iso1A2: "RS",
26397             iso1A3: "SRB",
26398             iso1N3: "688",
26399             wikidata: "Q403",
26400             nameEn: "Serbia",
26401             groups: ["039", "150", "UN"],
26402             callingCodes: ["381"]
26403           },
26404           geometry: {
26405             type: "MultiPolygon",
26406             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]]]]
26407           }
26408         }, {
26409           type: "Feature",
26410           properties: {
26411             iso1A2: "RU",
26412             iso1A3: "RUS",
26413             iso1N3: "643",
26414             wikidata: "Q159",
26415             nameEn: "Russia"
26416           },
26417           geometry: null
26418         }, {
26419           type: "Feature",
26420           properties: {
26421             iso1A2: "RW",
26422             iso1A3: "RWA",
26423             iso1N3: "646",
26424             wikidata: "Q1037",
26425             nameEn: "Rwanda",
26426             groups: ["014", "202", "002", "UN"],
26427             callingCodes: ["250"]
26428           },
26429           geometry: {
26430             type: "MultiPolygon",
26431             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]]]]
26432           }
26433         }, {
26434           type: "Feature",
26435           properties: {
26436             iso1A2: "SA",
26437             iso1A3: "SAU",
26438             iso1N3: "682",
26439             wikidata: "Q851",
26440             nameEn: "Saudi Arabia",
26441             groups: ["145", "142", "UN"],
26442             callingCodes: ["966"]
26443           },
26444           geometry: {
26445             type: "MultiPolygon",
26446             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]]]]
26447           }
26448         }, {
26449           type: "Feature",
26450           properties: {
26451             iso1A2: "SB",
26452             iso1A3: "SLB",
26453             iso1N3: "090",
26454             wikidata: "Q685",
26455             nameEn: "Solomon Islands",
26456             groups: ["054", "009", "UN"],
26457             driveSide: "left",
26458             callingCodes: ["677"]
26459           },
26460           geometry: {
26461             type: "MultiPolygon",
26462             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]]]]
26463           }
26464         }, {
26465           type: "Feature",
26466           properties: {
26467             iso1A2: "SC",
26468             iso1A3: "SYC",
26469             iso1N3: "690",
26470             wikidata: "Q1042",
26471             nameEn: "Seychelles",
26472             groups: ["014", "202", "002", "UN"],
26473             driveSide: "left",
26474             callingCodes: ["248"]
26475           },
26476           geometry: {
26477             type: "MultiPolygon",
26478             coordinates: [[[[43.75112, -10.38913], [54.83239, -10.93575], [66.3222, 5.65313], [43.75112, -10.38913]]]]
26479           }
26480         }, {
26481           type: "Feature",
26482           properties: {
26483             iso1A2: "SD",
26484             iso1A3: "SDN",
26485             iso1N3: "729",
26486             wikidata: "Q1049",
26487             nameEn: "Sudan",
26488             groups: ["015", "002", "UN"],
26489             callingCodes: ["249"]
26490           },
26491           geometry: {
26492             type: "MultiPolygon",
26493             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]]]]
26494           }
26495         }, {
26496           type: "Feature",
26497           properties: {
26498             iso1A2: "SE",
26499             iso1A3: "SWE",
26500             iso1N3: "752",
26501             wikidata: "Q34",
26502             nameEn: "Sweden",
26503             groups: ["EU", "154", "150", "UN"],
26504             callingCodes: ["46"]
26505           },
26506           geometry: {
26507             type: "MultiPolygon",
26508             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]]]]
26509           }
26510         }, {
26511           type: "Feature",
26512           properties: {
26513             iso1A2: "SG",
26514             iso1A3: "SGP",
26515             iso1N3: "702",
26516             wikidata: "Q334",
26517             nameEn: "Singapore",
26518             groups: ["035", "142", "UN"],
26519             driveSide: "left",
26520             callingCodes: ["65"]
26521           },
26522           geometry: {
26523             type: "MultiPolygon",
26524             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]]]]
26525           }
26526         }, {
26527           type: "Feature",
26528           properties: {
26529             iso1A2: "SH",
26530             iso1A3: "SHN",
26531             iso1N3: "654",
26532             wikidata: "Q192184",
26533             nameEn: "Saint Helena, Ascension and Tristan da Cunha",
26534             country: "GB"
26535           },
26536           geometry: null
26537         }, {
26538           type: "Feature",
26539           properties: {
26540             iso1A2: "SI",
26541             iso1A3: "SVN",
26542             iso1N3: "705",
26543             wikidata: "Q215",
26544             nameEn: "Slovenia",
26545             groups: ["EU", "039", "150", "UN"],
26546             callingCodes: ["386"]
26547           },
26548           geometry: {
26549             type: "MultiPolygon",
26550             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]]]]
26551           }
26552         }, {
26553           type: "Feature",
26554           properties: {
26555             iso1A2: "SJ",
26556             iso1A3: "SJM",
26557             iso1N3: "744",
26558             wikidata: "Q842829",
26559             nameEn: "Svalbard and Jan Mayen",
26560             country: "NO"
26561           },
26562           geometry: null
26563         }, {
26564           type: "Feature",
26565           properties: {
26566             iso1A2: "SK",
26567             iso1A3: "SVK",
26568             iso1N3: "703",
26569             wikidata: "Q214",
26570             nameEn: "Slovakia",
26571             groups: ["EU", "151", "150", "UN"],
26572             callingCodes: ["421"]
26573           },
26574           geometry: {
26575             type: "MultiPolygon",
26576             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]]]]
26577           }
26578         }, {
26579           type: "Feature",
26580           properties: {
26581             iso1A2: "SL",
26582             iso1A3: "SLE",
26583             iso1N3: "694",
26584             wikidata: "Q1044",
26585             nameEn: "Sierra Leone",
26586             groups: ["011", "202", "002", "UN"],
26587             callingCodes: ["232"]
26588           },
26589           geometry: {
26590             type: "MultiPolygon",
26591             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]]]]
26592           }
26593         }, {
26594           type: "Feature",
26595           properties: {
26596             iso1A2: "SM",
26597             iso1A3: "SMR",
26598             iso1N3: "674",
26599             wikidata: "Q238",
26600             nameEn: "San Marino",
26601             groups: ["039", "150", "UN"],
26602             callingCodes: ["378"]
26603           },
26604           geometry: {
26605             type: "MultiPolygon",
26606             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]]]]
26607           }
26608         }, {
26609           type: "Feature",
26610           properties: {
26611             iso1A2: "SN",
26612             iso1A3: "SEN",
26613             iso1N3: "686",
26614             wikidata: "Q1041",
26615             nameEn: "Senegal",
26616             groups: ["011", "202", "002", "UN"],
26617             callingCodes: ["221"]
26618           },
26619           geometry: {
26620             type: "MultiPolygon",
26621             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]]]]
26622           }
26623         }, {
26624           type: "Feature",
26625           properties: {
26626             iso1A2: "SO",
26627             iso1A3: "SOM",
26628             iso1N3: "706",
26629             wikidata: "Q1045",
26630             nameEn: "Somalia",
26631             groups: ["014", "202", "002", "UN"],
26632             callingCodes: ["252"]
26633           },
26634           geometry: {
26635             type: "MultiPolygon",
26636             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]]]]
26637           }
26638         }, {
26639           type: "Feature",
26640           properties: {
26641             iso1A2: "SR",
26642             iso1A3: "SUR",
26643             iso1N3: "740",
26644             wikidata: "Q730",
26645             nameEn: "Suriname",
26646             groups: ["005", "419", "019", "UN"],
26647             driveSide: "left",
26648             callingCodes: ["597"]
26649           },
26650           geometry: {
26651             type: "MultiPolygon",
26652             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]]]]
26653           }
26654         }, {
26655           type: "Feature",
26656           properties: {
26657             iso1A2: "SS",
26658             iso1A3: "SSD",
26659             iso1N3: "728",
26660             wikidata: "Q958",
26661             nameEn: "South Sudan",
26662             groups: ["014", "202", "002", "UN"],
26663             callingCodes: ["211"]
26664           },
26665           geometry: {
26666             type: "MultiPolygon",
26667             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]]]]
26668           }
26669         }, {
26670           type: "Feature",
26671           properties: {
26672             iso1A2: "ST",
26673             iso1A3: "STP",
26674             iso1N3: "678",
26675             wikidata: "Q1039",
26676             nameEn: "S\xE3o Tom\xE9 and Principe",
26677             groups: ["017", "202", "002", "UN"],
26678             callingCodes: ["239"]
26679           },
26680           geometry: {
26681             type: "MultiPolygon",
26682             coordinates: [[[[4.34149, 1.91417], [6.6507, -0.28606], [7.9035, 1.92304], [4.34149, 1.91417]]]]
26683           }
26684         }, {
26685           type: "Feature",
26686           properties: {
26687             iso1A2: "SV",
26688             iso1A3: "SLV",
26689             iso1N3: "222",
26690             wikidata: "Q792",
26691             nameEn: "El Salvador",
26692             groups: ["013", "003", "419", "019", "UN"],
26693             callingCodes: ["503"]
26694           },
26695           geometry: {
26696             type: "MultiPolygon",
26697             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]]]]
26698           }
26699         }, {
26700           type: "Feature",
26701           properties: {
26702             iso1A2: "SX",
26703             iso1A3: "SXM",
26704             iso1N3: "534",
26705             wikidata: "Q26273",
26706             nameEn: "Sint Maarten",
26707             aliases: ["NL-SX"],
26708             country: "NL",
26709             groups: ["Q1451600", "029", "003", "419", "019", "UN"],
26710             callingCodes: ["1 721"]
26711           },
26712           geometry: {
26713             type: "MultiPolygon",
26714             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]]]]
26715           }
26716         }, {
26717           type: "Feature",
26718           properties: {
26719             iso1A2: "SY",
26720             iso1A3: "SYR",
26721             iso1N3: "760",
26722             wikidata: "Q858",
26723             nameEn: "Syria",
26724             groups: ["145", "142", "UN"],
26725             callingCodes: ["963"]
26726           },
26727           geometry: {
26728             type: "MultiPolygon",
26729             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]]]]
26730           }
26731         }, {
26732           type: "Feature",
26733           properties: {
26734             iso1A2: "SZ",
26735             iso1A3: "SWZ",
26736             iso1N3: "748",
26737             wikidata: "Q1050",
26738             nameEn: "Eswatini",
26739             aliases: ["Swaziland"],
26740             groups: ["018", "202", "002", "UN"],
26741             driveSide: "left",
26742             callingCodes: ["268"]
26743           },
26744           geometry: {
26745             type: "MultiPolygon",
26746             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]]]]
26747           }
26748         }, {
26749           type: "Feature",
26750           properties: {
26751             iso1A2: "TA",
26752             iso1A3: "TAA",
26753             wikidata: "Q220982",
26754             nameEn: "Tristan da Cunha",
26755             aliases: ["SH-TA"],
26756             country: "GB",
26757             groups: ["SH", "BOTS", "011", "202", "002", "UN"],
26758             isoStatus: "excRes",
26759             driveSide: "left",
26760             roadSpeedUnit: "mph",
26761             roadHeightUnit: "ft",
26762             callingCodes: ["290 8", "44 20"]
26763           },
26764           geometry: {
26765             type: "MultiPolygon",
26766             coordinates: [[[[-13.38232, -34.07258], [-16.67337, -41.9188], [-5.88482, -41.4829], [-13.38232, -34.07258]]]]
26767           }
26768         }, {
26769           type: "Feature",
26770           properties: {
26771             iso1A2: "TC",
26772             iso1A3: "TCA",
26773             iso1N3: "796",
26774             wikidata: "Q18221",
26775             nameEn: "Turks and Caicos Islands",
26776             country: "GB",
26777             groups: ["BOTS", "029", "003", "419", "019", "UN"],
26778             driveSide: "left",
26779             roadSpeedUnit: "mph",
26780             roadHeightUnit: "ft",
26781             callingCodes: ["1 649"]
26782           },
26783           geometry: {
26784             type: "MultiPolygon",
26785             coordinates: [[[[-71.70065, 25.7637], [-72.98446, 20.4801], [-69.80718, 21.35956], [-71.70065, 25.7637]]]]
26786           }
26787         }, {
26788           type: "Feature",
26789           properties: {
26790             iso1A2: "TD",
26791             iso1A3: "TCD",
26792             iso1N3: "148",
26793             wikidata: "Q657",
26794             nameEn: "Chad",
26795             groups: ["017", "202", "002", "UN"],
26796             callingCodes: ["235"]
26797           },
26798           geometry: {
26799             type: "MultiPolygon",
26800             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]]]]
26801           }
26802         }, {
26803           type: "Feature",
26804           properties: {
26805             iso1A2: "TF",
26806             iso1A3: "ATF",
26807             iso1N3: "260",
26808             wikidata: "Q129003",
26809             nameEn: "French Southern Territories",
26810             country: "FR"
26811           },
26812           geometry: null
26813         }, {
26814           type: "Feature",
26815           properties: {
26816             iso1A2: "TG",
26817             iso1A3: "TGO",
26818             iso1N3: "768",
26819             wikidata: "Q945",
26820             nameEn: "Togo",
26821             groups: ["011", "202", "002", "UN"],
26822             callingCodes: ["228"]
26823           },
26824           geometry: {
26825             type: "MultiPolygon",
26826             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]]]]
26827           }
26828         }, {
26829           type: "Feature",
26830           properties: {
26831             iso1A2: "TH",
26832             iso1A3: "THA",
26833             iso1N3: "764",
26834             wikidata: "Q869",
26835             nameEn: "Thailand",
26836             groups: ["035", "142", "UN"],
26837             driveSide: "left",
26838             callingCodes: ["66"]
26839           },
26840           geometry: {
26841             type: "MultiPolygon",
26842             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]]]]
26843           }
26844         }, {
26845           type: "Feature",
26846           properties: {
26847             iso1A2: "TJ",
26848             iso1A3: "TJK",
26849             iso1N3: "762",
26850             wikidata: "Q863",
26851             nameEn: "Tajikistan",
26852             groups: ["143", "142", "UN"],
26853             callingCodes: ["992"]
26854           },
26855           geometry: {
26856             type: "MultiPolygon",
26857             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]]]]
26858           }
26859         }, {
26860           type: "Feature",
26861           properties: {
26862             iso1A2: "TK",
26863             iso1A3: "TKL",
26864             iso1N3: "772",
26865             wikidata: "Q36823",
26866             nameEn: "Tokelau",
26867             country: "NZ",
26868             groups: ["061", "009", "UN"],
26869             driveSide: "left",
26870             callingCodes: ["690"]
26871           },
26872           geometry: {
26873             type: "MultiPolygon",
26874             coordinates: [[[[-168.251, -9.44289], [-174.18635, -7.80441], [-174.17993, -10.13616], [-168.251, -9.44289]]]]
26875           }
26876         }, {
26877           type: "Feature",
26878           properties: {
26879             iso1A2: "TL",
26880             iso1A3: "TLS",
26881             iso1N3: "626",
26882             wikidata: "Q574",
26883             nameEn: "East Timor",
26884             aliases: ["Timor-Leste", "TP"],
26885             groups: ["035", "142", "UN"],
26886             driveSide: "left",
26887             callingCodes: ["670"]
26888           },
26889           geometry: {
26890             type: "MultiPolygon",
26891             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]]]]
26892           }
26893         }, {
26894           type: "Feature",
26895           properties: {
26896             iso1A2: "TM",
26897             iso1A3: "TKM",
26898             iso1N3: "795",
26899             wikidata: "Q874",
26900             nameEn: "Turkmenistan",
26901             groups: ["143", "142", "UN"],
26902             callingCodes: ["993"]
26903           },
26904           geometry: {
26905             type: "MultiPolygon",
26906             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]]]]
26907           }
26908         }, {
26909           type: "Feature",
26910           properties: {
26911             iso1A2: "TN",
26912             iso1A3: "TUN",
26913             iso1N3: "788",
26914             wikidata: "Q948",
26915             nameEn: "Tunisia",
26916             groups: ["015", "002", "UN"],
26917             callingCodes: ["216"]
26918           },
26919           geometry: {
26920             type: "MultiPolygon",
26921             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]]]]
26922           }
26923         }, {
26924           type: "Feature",
26925           properties: {
26926             iso1A2: "TO",
26927             iso1A3: "TON",
26928             iso1N3: "776",
26929             wikidata: "Q678",
26930             nameEn: "Tonga",
26931             groups: ["061", "009", "UN"],
26932             driveSide: "left",
26933             callingCodes: ["676"]
26934           },
26935           geometry: {
26936             type: "MultiPolygon",
26937             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]]]]
26938           }
26939         }, {
26940           type: "Feature",
26941           properties: {
26942             iso1A2: "TR",
26943             iso1A3: "TUR",
26944             iso1N3: "792",
26945             wikidata: "Q43",
26946             nameEn: "Turkey",
26947             groups: ["145", "142", "UN"],
26948             callingCodes: ["90"]
26949           },
26950           geometry: {
26951             type: "MultiPolygon",
26952             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]]]]
26953           }
26954         }, {
26955           type: "Feature",
26956           properties: {
26957             iso1A2: "TT",
26958             iso1A3: "TTO",
26959             iso1N3: "780",
26960             wikidata: "Q754",
26961             nameEn: "Trinidad and Tobago",
26962             groups: ["029", "003", "419", "019", "UN"],
26963             driveSide: "left",
26964             callingCodes: ["1 868"]
26965           },
26966           geometry: {
26967             type: "MultiPolygon",
26968             coordinates: [[[[-61.62505, 11.18974], [-62.08693, 10.04435], [-60.89962, 9.81445], [-60.07172, 11.77667], [-61.62505, 11.18974]]]]
26969           }
26970         }, {
26971           type: "Feature",
26972           properties: {
26973             iso1A2: "TV",
26974             iso1A3: "TUV",
26975             iso1N3: "798",
26976             wikidata: "Q672",
26977             nameEn: "Tuvalu",
26978             groups: ["061", "009", "UN"],
26979             driveSide: "left",
26980             callingCodes: ["688"]
26981           },
26982           geometry: {
26983             type: "MultiPolygon",
26984             coordinates: [[[[174, -5], [174, -11.5], [179.99999, -11.5], [179.99999, -5], [174, -5]]]]
26985           }
26986         }, {
26987           type: "Feature",
26988           properties: {
26989             iso1A2: "TW",
26990             iso1A3: "TWN",
26991             iso1N3: "158",
26992             wikidata: "Q865",
26993             nameEn: "Taiwan",
26994             aliases: ["RC"],
26995             groups: ["030", "142"],
26996             callingCodes: ["886"]
26997           },
26998           geometry: {
26999             type: "MultiPolygon",
27000             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]]]]
27001           }
27002         }, {
27003           type: "Feature",
27004           properties: {
27005             iso1A2: "TZ",
27006             iso1A3: "TZA",
27007             iso1N3: "834",
27008             wikidata: "Q924",
27009             nameEn: "Tanzania",
27010             groups: ["014", "202", "002", "UN"],
27011             driveSide: "left",
27012             callingCodes: ["255"]
27013           },
27014           geometry: {
27015             type: "MultiPolygon",
27016             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]]]]
27017           }
27018         }, {
27019           type: "Feature",
27020           properties: {
27021             iso1A2: "UA",
27022             iso1A3: "UKR",
27023             iso1N3: "804",
27024             wikidata: "Q212",
27025             nameEn: "Ukraine",
27026             groups: ["151", "150", "UN"],
27027             callingCodes: ["380"]
27028           },
27029           geometry: {
27030             type: "MultiPolygon",
27031             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]]]]
27032           }
27033         }, {
27034           type: "Feature",
27035           properties: {
27036             iso1A2: "UG",
27037             iso1A3: "UGA",
27038             iso1N3: "800",
27039             wikidata: "Q1036",
27040             nameEn: "Uganda",
27041             groups: ["014", "202", "002", "UN"],
27042             driveSide: "left",
27043             callingCodes: ["256"]
27044           },
27045           geometry: {
27046             type: "MultiPolygon",
27047             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]]]]
27048           }
27049         }, {
27050           type: "Feature",
27051           properties: {
27052             iso1A2: "UM",
27053             iso1A3: "UMI",
27054             iso1N3: "581",
27055             wikidata: "Q16645",
27056             nameEn: "United States Minor Outlying Islands",
27057             country: "US"
27058           },
27059           geometry: null
27060         }, {
27061           type: "Feature",
27062           properties: {
27063             iso1A2: "UN",
27064             wikidata: "Q1065",
27065             nameEn: "United Nations",
27066             level: "unitedNations",
27067             isoStatus: "excRes"
27068           },
27069           geometry: null
27070         }, {
27071           type: "Feature",
27072           properties: {
27073             iso1A2: "US",
27074             iso1A3: "USA",
27075             iso1N3: "840",
27076             wikidata: "Q30",
27077             nameEn: "United States of America"
27078           },
27079           geometry: null
27080         }, {
27081           type: "Feature",
27082           properties: {
27083             iso1A2: "UY",
27084             iso1A3: "URY",
27085             iso1N3: "858",
27086             wikidata: "Q77",
27087             nameEn: "Uruguay",
27088             groups: ["005", "419", "019", "UN"],
27089             callingCodes: ["598"]
27090           },
27091           geometry: {
27092             type: "MultiPolygon",
27093             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]]]]
27094           }
27095         }, {
27096           type: "Feature",
27097           properties: {
27098             iso1A2: "UZ",
27099             iso1A3: "UZB",
27100             iso1N3: "860",
27101             wikidata: "Q265",
27102             nameEn: "Uzbekistan",
27103             groups: ["143", "142", "UN"],
27104             callingCodes: ["998"]
27105           },
27106           geometry: {
27107             type: "MultiPolygon",
27108             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]]]]
27109           }
27110         }, {
27111           type: "Feature",
27112           properties: {
27113             iso1A2: "VA",
27114             iso1A3: "VAT",
27115             iso1N3: "336",
27116             wikidata: "Q237",
27117             nameEn: "Vatican City",
27118             aliases: ["Holy See"],
27119             groups: ["039", "150"],
27120             callingCodes: ["379", "39 06"]
27121           },
27122           geometry: {
27123             type: "MultiPolygon",
27124             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]]]]
27125           }
27126         }, {
27127           type: "Feature",
27128           properties: {
27129             iso1A2: "VC",
27130             iso1A3: "VCT",
27131             iso1N3: "670",
27132             wikidata: "Q757",
27133             nameEn: "St. Vincent and the Grenadines",
27134             aliases: ["WV"],
27135             groups: ["029", "003", "419", "019", "UN"],
27136             driveSide: "left",
27137             roadSpeedUnit: "mph",
27138             callingCodes: ["1 784"]
27139           },
27140           geometry: {
27141             type: "MultiPolygon",
27142             coordinates: [[[[-62.64026, 12.69984], [-59.94058, 12.34011], [-61.69315, 14.26451], [-62.64026, 12.69984]]]]
27143           }
27144         }, {
27145           type: "Feature",
27146           properties: {
27147             iso1A2: "VE",
27148             iso1A3: "VEN",
27149             iso1N3: "862",
27150             wikidata: "Q717",
27151             nameEn: "Venezuela",
27152             aliases: ["YV"],
27153             groups: ["005", "419", "019", "UN"],
27154             callingCodes: ["58"]
27155           },
27156           geometry: {
27157             type: "MultiPolygon",
27158             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]]]]
27159           }
27160         }, {
27161           type: "Feature",
27162           properties: {
27163             iso1A2: "VG",
27164             iso1A3: "VGB",
27165             iso1N3: "092",
27166             wikidata: "Q25305",
27167             nameEn: "British Virgin Islands",
27168             country: "GB",
27169             groups: ["BOTS", "029", "003", "419", "019", "UN"],
27170             driveSide: "left",
27171             roadSpeedUnit: "mph",
27172             roadHeightUnit: "ft",
27173             callingCodes: ["1 284"]
27174           },
27175           geometry: {
27176             type: "MultiPolygon",
27177             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]]]]
27178           }
27179         }, {
27180           type: "Feature",
27181           properties: {
27182             iso1A2: "VI",
27183             iso1A3: "VIR",
27184             iso1N3: "850",
27185             wikidata: "Q11703",
27186             nameEn: "United States Virgin Islands",
27187             aliases: ["US-VI"],
27188             country: "US",
27189             groups: ["Q1352230", "029", "003", "419", "019", "UN"],
27190             driveSide: "left",
27191             roadSpeedUnit: "mph",
27192             roadHeightUnit: "ft",
27193             callingCodes: ["1 340"]
27194           },
27195           geometry: {
27196             type: "MultiPolygon",
27197             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]]]]
27198           }
27199         }, {
27200           type: "Feature",
27201           properties: {
27202             iso1A2: "VN",
27203             iso1A3: "VNM",
27204             iso1N3: "704",
27205             wikidata: "Q881",
27206             nameEn: "Vietnam",
27207             groups: ["035", "142", "UN"],
27208             callingCodes: ["84"]
27209           },
27210           geometry: {
27211             type: "MultiPolygon",
27212             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]]]]
27213           }
27214         }, {
27215           type: "Feature",
27216           properties: {
27217             iso1A2: "VU",
27218             iso1A3: "VUT",
27219             iso1N3: "548",
27220             wikidata: "Q686",
27221             nameEn: "Vanuatu",
27222             groups: ["054", "009", "UN"],
27223             callingCodes: ["678"]
27224           },
27225           geometry: {
27226             type: "MultiPolygon",
27227             coordinates: [[[[156.73836, -14.50464], [174.245, -23.1974], [172.71443, -12.01327], [156.73836, -14.50464]]]]
27228           }
27229         }, {
27230           type: "Feature",
27231           properties: {
27232             iso1A2: "WF",
27233             iso1A3: "WLF",
27234             iso1N3: "876",
27235             wikidata: "Q35555",
27236             nameEn: "Wallis and Futuna",
27237             country: "FR",
27238             groups: ["Q1451600", "061", "009", "UN"],
27239             callingCodes: ["681"]
27240           },
27241           geometry: {
27242             type: "MultiPolygon",
27243             coordinates: [[[[-178.66551, -14.32452], [-176.76826, -14.95183], [-175.59809, -12.61507], [-178.66551, -14.32452]]]]
27244           }
27245         }, {
27246           type: "Feature",
27247           properties: {
27248             iso1A2: "WS",
27249             iso1A3: "WSM",
27250             iso1N3: "882",
27251             wikidata: "Q683",
27252             nameEn: "Samoa",
27253             groups: ["061", "009", "UN"],
27254             driveSide: "left",
27255             callingCodes: ["685"]
27256           },
27257           geometry: {
27258             type: "MultiPolygon",
27259             coordinates: [[[[-173.74402, -14.26669], [-170.99605, -15.1275], [-171.39864, -10.21587], [-173.74402, -14.26669]]]]
27260           }
27261         }, {
27262           type: "Feature",
27263           properties: {
27264             iso1A2: "XK",
27265             iso1A3: "XKX",
27266             wikidata: "Q1246",
27267             nameEn: "Kosovo",
27268             aliases: ["KV"],
27269             groups: ["039", "150"],
27270             isoStatus: "usrAssn",
27271             callingCodes: ["383"]
27272           },
27273           geometry: {
27274             type: "MultiPolygon",
27275             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]]]]
27276           }
27277         }, {
27278           type: "Feature",
27279           properties: {
27280             iso1A2: "YE",
27281             iso1A3: "YEM",
27282             iso1N3: "887",
27283             wikidata: "Q805",
27284             nameEn: "Yemen",
27285             groups: ["145", "142", "UN"],
27286             callingCodes: ["967"]
27287           },
27288           geometry: {
27289             type: "MultiPolygon",
27290             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]]]]
27291           }
27292         }, {
27293           type: "Feature",
27294           properties: {
27295             iso1A2: "YT",
27296             iso1A3: "MYT",
27297             iso1N3: "175",
27298             wikidata: "Q17063",
27299             nameEn: "Mayotte",
27300             country: "FR",
27301             groups: ["Q3320166", "EU", "014", "202", "002", "UN"],
27302             callingCodes: ["262"]
27303           },
27304           geometry: {
27305             type: "MultiPolygon",
27306             coordinates: [[[[43.28731, -13.97126], [45.54824, -13.22353], [45.4971, -11.75965], [43.28731, -13.97126]]]]
27307           }
27308         }, {
27309           type: "Feature",
27310           properties: {
27311             iso1A2: "ZA",
27312             iso1A3: "ZAF",
27313             iso1N3: "710",
27314             wikidata: "Q258",
27315             nameEn: "South Africa",
27316             groups: ["018", "202", "002", "UN"],
27317             driveSide: "left",
27318             callingCodes: ["27"]
27319           },
27320           geometry: {
27321             type: "MultiPolygon",
27322             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]]]]
27323           }
27324         }, {
27325           type: "Feature",
27326           properties: {
27327             iso1A2: "ZM",
27328             iso1A3: "ZMB",
27329             iso1N3: "894",
27330             wikidata: "Q953",
27331             nameEn: "Zambia",
27332             groups: ["014", "202", "002", "UN"],
27333             driveSide: "left",
27334             callingCodes: ["260"]
27335           },
27336           geometry: {
27337             type: "MultiPolygon",
27338             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]]]]
27339           }
27340         }, {
27341           type: "Feature",
27342           properties: {
27343             iso1A2: "ZW",
27344             iso1A3: "ZWE",
27345             iso1N3: "716",
27346             wikidata: "Q954",
27347             nameEn: "Zimbabwe",
27348             groups: ["014", "202", "002", "UN"],
27349             driveSide: "left",
27350             callingCodes: ["263"]
27351           },
27352           geometry: {
27353             type: "MultiPolygon",
27354             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]]]]
27355           }
27356         }];
27357         var borders_default = {
27358           type: type,
27359           features: features
27360         }; // src/country-coder.ts
27361
27362         var borders = borders_default;
27363         var whichPolygonGetter = {};
27364         var featuresByCode = {};
27365         var idFilterRegex = /(?=(?!^(and|the|of|el|la|de)$))(\b(and|the|of|el|la|de)\b)|[-_ .,'()&[\]/]/gi;
27366
27367         function canonicalID(id) {
27368           var s = id || "";
27369
27370           if (s.charAt(0) === ".") {
27371             return s.toUpperCase();
27372           } else {
27373             return s.replace(idFilterRegex, "").toUpperCase();
27374           }
27375         }
27376
27377         var levels = ["subterritory", "territory", "subcountryGroup", "country", "sharedLandform", "intermediateRegion", "subregion", "region", "subunion", "union", "unitedNations", "world"];
27378         loadDerivedDataAndCaches(borders);
27379
27380         function loadDerivedDataAndCaches(borders2) {
27381           var identifierProps = ["iso1A2", "iso1A3", "m49", "wikidata", "emojiFlag", "ccTLD", "nameEn"];
27382           var geometryFeatures = [];
27383
27384           for (var i in borders2.features) {
27385             var feature2 = borders2.features[i];
27386             feature2.properties.id = feature2.properties.iso1A2 || feature2.properties.m49 || feature2.properties.wikidata;
27387             loadM49(feature2);
27388             loadTLD(feature2);
27389             loadIsoStatus(feature2);
27390             loadLevel(feature2);
27391             loadGroups(feature2);
27392             loadFlag(feature2);
27393             cacheFeatureByIDs(feature2);
27394             if (feature2.geometry) geometryFeatures.push(feature2);
27395           }
27396
27397           for (var _i in borders2.features) {
27398             var _feature = borders2.features[_i];
27399             _feature.properties.groups = _feature.properties.groups.map(function (groupID) {
27400               return featuresByCode[groupID].properties.id;
27401             });
27402             loadMembersForGroupsOf(_feature);
27403           }
27404
27405           for (var _i2 in borders2.features) {
27406             var _feature2 = borders2.features[_i2];
27407             loadRoadSpeedUnit(_feature2);
27408             loadRoadHeightUnit(_feature2);
27409             loadDriveSide(_feature2);
27410             loadCallingCodes(_feature2);
27411             loadGroupGroups(_feature2);
27412           }
27413
27414           for (var _i3 in borders2.features) {
27415             var _feature3 = borders2.features[_i3];
27416
27417             _feature3.properties.groups.sort(function (groupID1, groupID2) {
27418               return levels.indexOf(featuresByCode[groupID1].properties.level) - levels.indexOf(featuresByCode[groupID2].properties.level);
27419             });
27420
27421             if (_feature3.properties.members) _feature3.properties.members.sort(function (id1, id2) {
27422               var diff = levels.indexOf(featuresByCode[id1].properties.level) - levels.indexOf(featuresByCode[id2].properties.level);
27423
27424               if (diff === 0) {
27425                 return borders2.features.indexOf(featuresByCode[id1]) - borders2.features.indexOf(featuresByCode[id2]);
27426               }
27427
27428               return diff;
27429             });
27430           }
27431
27432           var geometryOnlyCollection = {
27433             type: "FeatureCollection",
27434             features: geometryFeatures
27435           };
27436           whichPolygonGetter = whichPolygon_1(geometryOnlyCollection);
27437
27438           function loadGroups(feature2) {
27439             var props = feature2.properties;
27440
27441             if (!props.groups) {
27442               props.groups = [];
27443             }
27444
27445             if (feature2.geometry && props.country) {
27446               props.groups.push(props.country);
27447             }
27448
27449             if (props.m49 !== "001") {
27450               props.groups.push("001");
27451             }
27452           }
27453
27454           function loadM49(feature2) {
27455             var props = feature2.properties;
27456
27457             if (!props.m49 && props.iso1N3) {
27458               props.m49 = props.iso1N3;
27459             }
27460           }
27461
27462           function loadTLD(feature2) {
27463             var props = feature2.properties;
27464             if (props.level === "unitedNations") return;
27465
27466             if (!props.ccTLD && props.iso1A2) {
27467               props.ccTLD = "." + props.iso1A2.toLowerCase();
27468             }
27469           }
27470
27471           function loadIsoStatus(feature2) {
27472             var props = feature2.properties;
27473
27474             if (!props.isoStatus && props.iso1A2) {
27475               props.isoStatus = "official";
27476             }
27477           }
27478
27479           function loadLevel(feature2) {
27480             var props = feature2.properties;
27481             if (props.level) return;
27482
27483             if (!props.country) {
27484               props.level = "country";
27485             } else if (!props.iso1A2 || props.isoStatus === "official") {
27486               props.level = "territory";
27487             } else {
27488               props.level = "subterritory";
27489             }
27490           }
27491
27492           function loadGroupGroups(feature2) {
27493             var props = feature2.properties;
27494             if (feature2.geometry || !props.members) return;
27495             var featureLevelIndex = levels.indexOf(props.level);
27496             var sharedGroups = [];
27497
27498             var _loop = function _loop(_i4) {
27499               var memberID = props.members[_i4];
27500               var member = featuresByCode[memberID];
27501               var memberGroups = member.properties.groups.filter(function (groupID) {
27502                 return groupID !== feature2.properties.id && featureLevelIndex < levels.indexOf(featuresByCode[groupID].properties.level);
27503               });
27504
27505               if (_i4 === "0") {
27506                 sharedGroups = memberGroups;
27507               } else {
27508                 sharedGroups = sharedGroups.filter(function (groupID) {
27509                   return memberGroups.indexOf(groupID) !== -1;
27510                 });
27511               }
27512             };
27513
27514             for (var _i4 in props.members) {
27515               _loop(_i4);
27516             }
27517
27518             props.groups = props.groups.concat(sharedGroups.filter(function (groupID) {
27519               return props.groups.indexOf(groupID) === -1;
27520             }));
27521
27522             for (var j in sharedGroups) {
27523               var groupFeature = featuresByCode[sharedGroups[j]];
27524
27525               if (groupFeature.properties.members.indexOf(props.id) === -1) {
27526                 groupFeature.properties.members.push(props.id);
27527               }
27528             }
27529           }
27530
27531           function loadRoadSpeedUnit(feature2) {
27532             var props = feature2.properties;
27533
27534             if (feature2.geometry) {
27535               if (!props.roadSpeedUnit) props.roadSpeedUnit = "km/h";
27536             } else if (props.members) {
27537               var vals = Array.from(new Set(props.members.map(function (id) {
27538                 var member = featuresByCode[id];
27539                 if (member.geometry) return member.properties.roadSpeedUnit || "km/h";
27540               }).filter(Boolean)));
27541               if (vals.length === 1) props.roadSpeedUnit = vals[0];
27542             }
27543           }
27544
27545           function loadRoadHeightUnit(feature2) {
27546             var props = feature2.properties;
27547
27548             if (feature2.geometry) {
27549               if (!props.roadHeightUnit) props.roadHeightUnit = "m";
27550             } else if (props.members) {
27551               var vals = Array.from(new Set(props.members.map(function (id) {
27552                 var member = featuresByCode[id];
27553                 if (member.geometry) return member.properties.roadHeightUnit || "m";
27554               }).filter(Boolean)));
27555               if (vals.length === 1) props.roadHeightUnit = vals[0];
27556             }
27557           }
27558
27559           function loadDriveSide(feature2) {
27560             var props = feature2.properties;
27561
27562             if (feature2.geometry) {
27563               if (!props.driveSide) props.driveSide = "right";
27564             } else if (props.members) {
27565               var vals = Array.from(new Set(props.members.map(function (id) {
27566                 var member = featuresByCode[id];
27567                 if (member.geometry) return member.properties.driveSide || "right";
27568               }).filter(Boolean)));
27569               if (vals.length === 1) props.driveSide = vals[0];
27570             }
27571           }
27572
27573           function loadCallingCodes(feature2) {
27574             var props = feature2.properties;
27575
27576             if (!feature2.geometry && props.members) {
27577               props.callingCodes = Array.from(new Set(props.members.reduce(function (array, id) {
27578                 var member = featuresByCode[id];
27579                 if (member.geometry && member.properties.callingCodes) return array.concat(member.properties.callingCodes);
27580                 return array;
27581               }, [])));
27582             }
27583           }
27584
27585           function loadFlag(feature2) {
27586             if (!feature2.properties.iso1A2) return;
27587             var flag = feature2.properties.iso1A2.replace(/./g, function (_char) {
27588               return String.fromCodePoint(_char.charCodeAt(0) + 127397);
27589             });
27590             feature2.properties.emojiFlag = flag;
27591           }
27592
27593           function loadMembersForGroupsOf(feature2) {
27594             for (var j in feature2.properties.groups) {
27595               var groupID = feature2.properties.groups[j];
27596               var groupFeature = featuresByCode[groupID];
27597               if (!groupFeature.properties.members) groupFeature.properties.members = [];
27598               groupFeature.properties.members.push(feature2.properties.id);
27599             }
27600           }
27601
27602           function cacheFeatureByIDs(feature2) {
27603             var ids = [];
27604
27605             for (var k in identifierProps) {
27606               var prop = identifierProps[k];
27607               var id = feature2.properties[prop];
27608               if (id) ids.push(id);
27609             }
27610
27611             if (feature2.properties.aliases) {
27612               for (var j in feature2.properties.aliases) {
27613                 ids.push(feature2.properties.aliases[j]);
27614               }
27615             }
27616
27617             for (var _i5 in ids) {
27618               var _id = canonicalID(ids[_i5]);
27619
27620               featuresByCode[_id] = feature2;
27621             }
27622           }
27623         }
27624
27625         function locArray(loc) {
27626           if (Array.isArray(loc)) {
27627             return loc;
27628           } else if (loc.coordinates) {
27629             return loc.coordinates;
27630           }
27631
27632           return loc.geometry.coordinates;
27633         }
27634
27635         function smallestFeature(loc) {
27636           var query = locArray(loc);
27637           var featureProperties = whichPolygonGetter(query);
27638           if (!featureProperties) return null;
27639           return featuresByCode[featureProperties.id];
27640         }
27641
27642         function countryFeature(loc) {
27643           var feature2 = smallestFeature(loc);
27644           if (!feature2) return null;
27645           var countryCode = feature2.properties.country || feature2.properties.iso1A2;
27646           return featuresByCode[countryCode] || null;
27647         }
27648
27649         var defaultOpts = {
27650           level: void 0,
27651           maxLevel: void 0,
27652           withProp: void 0
27653         };
27654
27655         function featureForLoc(loc, opts) {
27656           var targetLevel = opts.level || "country";
27657           var maxLevel = opts.maxLevel || "world";
27658           var withProp = opts.withProp;
27659           var targetLevelIndex = levels.indexOf(targetLevel);
27660           if (targetLevelIndex === -1) return null;
27661           var maxLevelIndex = levels.indexOf(maxLevel);
27662           if (maxLevelIndex === -1) return null;
27663           if (maxLevelIndex < targetLevelIndex) return null;
27664
27665           if (targetLevel === "country") {
27666             var fastFeature = countryFeature(loc);
27667
27668             if (fastFeature) {
27669               if (!withProp || fastFeature.properties[withProp]) {
27670                 return fastFeature;
27671               }
27672             }
27673           }
27674
27675           var features2 = featuresContaining(loc);
27676
27677           for (var i in features2) {
27678             var feature2 = features2[i];
27679             var levelIndex = levels.indexOf(feature2.properties.level);
27680
27681             if (feature2.properties.level === targetLevel || levelIndex > targetLevelIndex && levelIndex <= maxLevelIndex) {
27682               if (!withProp || feature2.properties[withProp]) {
27683                 return feature2;
27684               }
27685             }
27686           }
27687
27688           return null;
27689         }
27690
27691         function featureForID(id) {
27692           var stringID;
27693
27694           if (typeof id === "number") {
27695             stringID = id.toString();
27696
27697             if (stringID.length === 1) {
27698               stringID = "00" + stringID;
27699             } else if (stringID.length === 2) {
27700               stringID = "0" + stringID;
27701             }
27702           } else {
27703             stringID = canonicalID(id);
27704           }
27705
27706           return featuresByCode[stringID] || null;
27707         }
27708
27709         function smallestFeaturesForBbox(bbox) {
27710           return whichPolygonGetter.bbox(bbox).map(function (props) {
27711             return featuresByCode[props.id];
27712           });
27713         }
27714
27715         function smallestOrMatchingFeature(query) {
27716           if (_typeof(query) === "object") {
27717             return smallestFeature(query);
27718           }
27719
27720           return featureForID(query);
27721         }
27722
27723         function feature$1(query) {
27724           var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultOpts;
27725
27726           if (_typeof(query) === "object") {
27727             return featureForLoc(query, opts);
27728           }
27729
27730           return featureForID(query);
27731         }
27732
27733         function iso1A2Code(query) {
27734           var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultOpts;
27735           opts.withProp = "iso1A2";
27736           var match = feature$1(query, opts);
27737           if (!match) return null;
27738           return match.properties.iso1A2 || null;
27739         }
27740
27741         function featuresContaining(query, strict) {
27742           var matchingFeatures;
27743
27744           if (Array.isArray(query) && query.length === 4) {
27745             matchingFeatures = smallestFeaturesForBbox(query);
27746           } else {
27747             var smallestOrMatching = smallestOrMatchingFeature(query);
27748             matchingFeatures = smallestOrMatching ? [smallestOrMatching] : [];
27749           }
27750
27751           if (!matchingFeatures.length) return [];
27752           var returnFeatures;
27753
27754           if (!strict || _typeof(query) === "object") {
27755             returnFeatures = matchingFeatures.slice();
27756           } else {
27757             returnFeatures = [];
27758           }
27759
27760           for (var j in matchingFeatures) {
27761             var properties = matchingFeatures[j].properties;
27762
27763             for (var i in properties.groups) {
27764               var groupID = properties.groups[i];
27765               var groupFeature = featuresByCode[groupID];
27766
27767               if (returnFeatures.indexOf(groupFeature) === -1) {
27768                 returnFeatures.push(groupFeature);
27769               }
27770             }
27771           }
27772
27773           return returnFeatures;
27774         }
27775
27776         function featuresIn(id, strict) {
27777           var feature2 = featureForID(id);
27778           if (!feature2) return [];
27779           var features2 = [];
27780
27781           if (!strict) {
27782             features2.push(feature2);
27783           }
27784
27785           var properties = feature2.properties;
27786
27787           if (properties.members) {
27788             for (var i in properties.members) {
27789               var memberID = properties.members[i];
27790               features2.push(featuresByCode[memberID]);
27791             }
27792           }
27793
27794           return features2;
27795         }
27796
27797         function aggregateFeature(id) {
27798           var features2 = featuresIn(id, false);
27799           if (features2.length === 0) return null;
27800           var aggregateCoordinates = [];
27801
27802           for (var i in features2) {
27803             var feature2 = features2[i];
27804
27805             if (feature2.geometry && feature2.geometry.type === "MultiPolygon" && feature2.geometry.coordinates) {
27806               aggregateCoordinates = aggregateCoordinates.concat(feature2.geometry.coordinates);
27807             }
27808           }
27809
27810           return {
27811             type: "Feature",
27812             properties: features2[0].properties,
27813             geometry: {
27814               type: "MultiPolygon",
27815               coordinates: aggregateCoordinates
27816             }
27817           };
27818         }
27819
27820         function roadSpeedUnit(query) {
27821           var feature2 = smallestOrMatchingFeature(query);
27822           return feature2 && feature2.properties.roadSpeedUnit || null;
27823         }
27824
27825         function roadHeightUnit(query) {
27826           var feature2 = smallestOrMatchingFeature(query);
27827           return feature2 && feature2.properties.roadHeightUnit || null;
27828         }
27829
27830         var geojsonArea = {};
27831
27832         var wgs84$1 = {};
27833
27834         wgs84$1.RADIUS = 6378137;
27835         wgs84$1.FLATTENING = 1 / 298.257223563;
27836         wgs84$1.POLAR_RADIUS = 6356752.3142;
27837
27838         var wgs84 = wgs84$1;
27839         geojsonArea.geometry = geometry;
27840         geojsonArea.ring = ringArea;
27841
27842         function geometry(_) {
27843           var area = 0,
27844               i;
27845
27846           switch (_.type) {
27847             case 'Polygon':
27848               return polygonArea(_.coordinates);
27849
27850             case 'MultiPolygon':
27851               for (i = 0; i < _.coordinates.length; i++) {
27852                 area += polygonArea(_.coordinates[i]);
27853               }
27854
27855               return area;
27856
27857             case 'Point':
27858             case 'MultiPoint':
27859             case 'LineString':
27860             case 'MultiLineString':
27861               return 0;
27862
27863             case 'GeometryCollection':
27864               for (i = 0; i < _.geometries.length; i++) {
27865                 area += geometry(_.geometries[i]);
27866               }
27867
27868               return area;
27869           }
27870         }
27871
27872         function polygonArea(coords) {
27873           var area = 0;
27874
27875           if (coords && coords.length > 0) {
27876             area += Math.abs(ringArea(coords[0]));
27877
27878             for (var i = 1; i < coords.length; i++) {
27879               area -= Math.abs(ringArea(coords[i]));
27880             }
27881           }
27882
27883           return area;
27884         }
27885         /**
27886          * Calculate the approximate area of the polygon were it projected onto
27887          *     the earth.  Note that this area will be positive if ring is oriented
27888          *     clockwise, otherwise it will be negative.
27889          *
27890          * Reference:
27891          * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for
27892          *     Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
27893          *     Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409
27894          *
27895          * Returns:
27896          * {float} The approximate signed geodesic area of the polygon in square
27897          *     meters.
27898          */
27899
27900
27901         function ringArea(coords) {
27902           var p1,
27903               p2,
27904               p3,
27905               lowerIndex,
27906               middleIndex,
27907               upperIndex,
27908               i,
27909               area = 0,
27910               coordsLength = coords.length;
27911
27912           if (coordsLength > 2) {
27913             for (i = 0; i < coordsLength; i++) {
27914               if (i === coordsLength - 2) {
27915                 // i = N-2
27916                 lowerIndex = coordsLength - 2;
27917                 middleIndex = coordsLength - 1;
27918                 upperIndex = 0;
27919               } else if (i === coordsLength - 1) {
27920                 // i = N-1
27921                 lowerIndex = coordsLength - 1;
27922                 middleIndex = 0;
27923                 upperIndex = 1;
27924               } else {
27925                 // i = 0 to N-3
27926                 lowerIndex = i;
27927                 middleIndex = i + 1;
27928                 upperIndex = i + 2;
27929               }
27930
27931               p1 = coords[lowerIndex];
27932               p2 = coords[middleIndex];
27933               p3 = coords[upperIndex];
27934               area += (rad(p3[0]) - rad(p1[0])) * Math.sin(rad(p2[1]));
27935             }
27936
27937             area = area * wgs84.RADIUS * wgs84.RADIUS / 2;
27938           }
27939
27940           return area;
27941         }
27942
27943         function rad(_) {
27944           return _ * Math.PI / 180;
27945         }
27946
27947         var inputValidation = {};
27948
27949         var $$n = _export;
27950         var $includes = arrayIncludes.includes;
27951         var addToUnscopables$2 = addToUnscopables$6;
27952
27953         // `Array.prototype.includes` method
27954         // https://tc39.es/ecma262/#sec-array.prototype.includes
27955         $$n({ target: 'Array', proto: true }, {
27956           includes: function includes(el /* , fromIndex = 0 */) {
27957             return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined);
27958           }
27959         });
27960
27961         // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
27962         addToUnscopables$2('includes');
27963
27964         var validateCenter$1 = {};
27965
27966         validateCenter$1.validateCenter = function validateCenter(center) {
27967           var validCenterLengths = [2, 3];
27968
27969           if (!Array.isArray(center) || !validCenterLengths.includes(center.length)) {
27970             throw new Error("ERROR! Center has to be an array of length two or three");
27971           }
27972
27973           var _center = _slicedToArray(center, 2),
27974               lng = _center[0],
27975               lat = _center[1];
27976
27977           if (typeof lng !== "number" || typeof lat !== "number") {
27978             throw new Error("ERROR! Longitude and Latitude has to be numbers but where ".concat(_typeof(lng), " and ").concat(_typeof(lat)));
27979           }
27980
27981           if (lng > 180 || lng < -180) {
27982             throw new Error("ERROR! Longitude has to be between -180 and 180 but was ".concat(lng));
27983           }
27984
27985           if (lat > 90 || lat < -90) {
27986             throw new Error("ERROR! Latitude has to be between -90 and 90 but was ".concat(lat));
27987           }
27988         };
27989
27990         var validateRadius$1 = {};
27991
27992         validateRadius$1.validateRadius = function validateRadius(radius) {
27993           if (typeof radius !== "number") {
27994             throw new Error("ERROR! Radius has to be a positive number but was: ".concat(_typeof(radius)));
27995           }
27996
27997           if (radius <= 0) {
27998             throw new Error("ERROR! Radius has to be a positive number but was: ".concat(radius));
27999           }
28000         };
28001
28002         var validateNumberOfEdges$1 = {};
28003
28004         validateNumberOfEdges$1.validateNumberOfEdges = function validateNumberOfEdges(numberOfEdges) {
28005           if (typeof numberOfEdges !== "number") {
28006             var ARGUMENT_TYPE = Array.isArray(numberOfEdges) ? "array" : _typeof(numberOfEdges);
28007             throw new Error("ERROR! Number of edges has to be a number but was: ".concat(ARGUMENT_TYPE));
28008           }
28009
28010           if (numberOfEdges < 3) {
28011             throw new Error("ERROR! Number of edges has to be at least 3 but was: ".concat(numberOfEdges));
28012           }
28013         };
28014
28015         var validateEarthRadius$1 = {};
28016
28017         validateEarthRadius$1.validateEarthRadius = function validateEarthRadius(earthRadius) {
28018           if (typeof earthRadius !== "number") {
28019             var ARGUMENT_TYPE = Array.isArray(earthRadius) ? "array" : _typeof(earthRadius);
28020             throw new Error("ERROR! Earth radius has to be a number but was: ".concat(ARGUMENT_TYPE));
28021           }
28022
28023           if (earthRadius <= 0) {
28024             throw new Error("ERROR! Earth radius has to be a positive number but was: ".concat(earthRadius));
28025           }
28026         };
28027
28028         var validateBearing$1 = {};
28029
28030         validateBearing$1.validateBearing = function validateBearing(bearing) {
28031           if (typeof bearing !== "number") {
28032             var ARGUMENT_TYPE = Array.isArray(bearing) ? "array" : _typeof(bearing);
28033             throw new Error("ERROR! Bearing has to be a number but was: ".concat(ARGUMENT_TYPE));
28034           }
28035         };
28036
28037         var validateCenter = validateCenter$1.validateCenter;
28038         var validateRadius = validateRadius$1.validateRadius;
28039         var validateNumberOfEdges = validateNumberOfEdges$1.validateNumberOfEdges;
28040         var validateEarthRadius = validateEarthRadius$1.validateEarthRadius;
28041         var validateBearing = validateBearing$1.validateBearing;
28042
28043         function validateInput$1(_ref) {
28044           var center = _ref.center,
28045               radius = _ref.radius,
28046               numberOfEdges = _ref.numberOfEdges,
28047               earthRadius = _ref.earthRadius,
28048               bearing = _ref.bearing;
28049           validateCenter(center);
28050           validateRadius(radius);
28051           validateNumberOfEdges(numberOfEdges);
28052           validateEarthRadius(earthRadius);
28053           validateBearing(bearing);
28054         }
28055
28056         inputValidation.validateCenter = validateCenter;
28057         inputValidation.validateRadius = validateRadius;
28058         inputValidation.validateNumberOfEdges = validateNumberOfEdges;
28059         inputValidation.validateEarthRadius = validateEarthRadius;
28060         inputValidation.validateBearing = validateBearing;
28061         inputValidation.validateInput = validateInput$1;
28062
28063         var validateInput = inputValidation.validateInput;
28064         var defaultEarthRadius = 6378137; // equatorial Earth radius
28065
28066         function toRadians(angleInDegrees) {
28067           return angleInDegrees * Math.PI / 180;
28068         }
28069
28070         function toDegrees(angleInRadians) {
28071           return angleInRadians * 180 / Math.PI;
28072         }
28073
28074         function offset(c1, distance, earthRadius, bearing) {
28075           var lat1 = toRadians(c1[1]);
28076           var lon1 = toRadians(c1[0]);
28077           var dByR = distance / earthRadius;
28078           var lat = Math.asin(Math.sin(lat1) * Math.cos(dByR) + Math.cos(lat1) * Math.sin(dByR) * Math.cos(bearing));
28079           var lon = lon1 + Math.atan2(Math.sin(bearing) * Math.sin(dByR) * Math.cos(lat1), Math.cos(dByR) - Math.sin(lat1) * Math.sin(lat));
28080           return [toDegrees(lon), toDegrees(lat)];
28081         }
28082
28083         var circleToPolygon = function circleToPolygon(center, radius, options) {
28084           var n = getNumberOfEdges(options);
28085           var earthRadius = getEarthRadius(options);
28086           var bearing = getBearing(options);
28087           var direction = getDirection(options); // validateInput() throws error on invalid input and do nothing on valid input
28088
28089           validateInput({
28090             center: center,
28091             radius: radius,
28092             numberOfEdges: n,
28093             earthRadius: earthRadius,
28094             bearing: bearing
28095           });
28096           var start = toRadians(bearing);
28097           var coordinates = [];
28098
28099           for (var i = 0; i < n; ++i) {
28100             coordinates.push(offset(center, radius, earthRadius, start + direction * 2 * Math.PI * -i / n));
28101           }
28102
28103           coordinates.push(coordinates[0]);
28104           return {
28105             type: "Polygon",
28106             coordinates: [coordinates]
28107           };
28108         };
28109
28110         function getNumberOfEdges(options) {
28111           if (isUndefinedOrNull(options)) {
28112             return 32;
28113           } else if (isObjectNotArray(options)) {
28114             var numberOfEdges = options.numberOfEdges;
28115             return numberOfEdges === undefined ? 32 : numberOfEdges;
28116           }
28117
28118           return options;
28119         }
28120
28121         function getEarthRadius(options) {
28122           if (isUndefinedOrNull(options)) {
28123             return defaultEarthRadius;
28124           } else if (isObjectNotArray(options)) {
28125             var earthRadius = options.earthRadius;
28126             return earthRadius === undefined ? defaultEarthRadius : earthRadius;
28127           }
28128
28129           return defaultEarthRadius;
28130         }
28131
28132         function getDirection(options) {
28133           if (isObjectNotArray(options) && options.rightHandRule) {
28134             return -1;
28135           }
28136
28137           return 1;
28138         }
28139
28140         function getBearing(options) {
28141           if (isUndefinedOrNull(options)) {
28142             return 0;
28143           } else if (isObjectNotArray(options)) {
28144             var bearing = options.bearing;
28145             return bearing === undefined ? 0 : bearing;
28146           }
28147
28148           return 0;
28149         }
28150
28151         function isObjectNotArray(argument) {
28152           return argument !== null && _typeof(argument) === "object" && !Array.isArray(argument);
28153         }
28154
28155         function isUndefinedOrNull(argument) {
28156           return argument === null || argument === undefined;
28157         }
28158
28159         var $$m = _export;
28160
28161         // `Number.EPSILON` constant
28162         // https://tc39.es/ecma262/#sec-number.epsilon
28163         $$m({ target: 'Number', stat: true }, {
28164           EPSILON: Math.pow(2, -52)
28165         });
28166
28167         var uncurryThis$8 = functionUncurryThis;
28168         var requireObjectCoercible$4 = requireObjectCoercible$e;
28169         var toString$5 = toString$k;
28170
28171         var quot = /"/g;
28172         var replace$2 = uncurryThis$8(''.replace);
28173
28174         // `CreateHTML` abstract operation
28175         // https://tc39.es/ecma262/#sec-createhtml
28176         var createHtml = function (string, tag, attribute, value) {
28177           var S = toString$5(requireObjectCoercible$4(string));
28178           var p1 = '<' + tag;
28179           if (attribute !== '') p1 += ' ' + attribute + '="' + replace$2(toString$5(value), quot, '&quot;') + '"';
28180           return p1 + '>' + S + '</' + tag + '>';
28181         };
28182
28183         var fails$6 = fails$S;
28184
28185         // check the existence of a method, lowercase
28186         // of a tag and escaping quotes in arguments
28187         var stringHtmlForced = function (METHOD_NAME) {
28188           return fails$6(function () {
28189             var test = ''[METHOD_NAME]('"');
28190             return test !== test.toLowerCase() || test.split('"').length > 3;
28191           });
28192         };
28193
28194         var $$l = _export;
28195         var createHTML = createHtml;
28196         var forcedStringHTMLMethod = stringHtmlForced;
28197
28198         // `String.prototype.link` method
28199         // https://tc39.es/ecma262/#sec-string.prototype.link
28200         $$l({ target: 'String', proto: true, forced: forcedStringHTMLMethod('link') }, {
28201           link: function link(url) {
28202             return createHTML(this, 'a', 'href', url);
28203           }
28204         });
28205
28206         /**
28207          * splaytree v3.1.0
28208          * Fast Splay tree for Node and browser
28209          *
28210          * @author Alexander Milevski <info@w8r.name>
28211          * @license MIT
28212          * @preserve
28213          */
28214         var Node =
28215         /** @class */
28216         function () {
28217           function Node(key, data) {
28218             this.next = null;
28219             this.key = key;
28220             this.data = data;
28221             this.left = null;
28222             this.right = null;
28223           }
28224
28225           return Node;
28226         }();
28227         /* follows "An implementation of top-down splaying"
28228          * by D. Sleator <sleator@cs.cmu.edu> March 1992
28229          */
28230
28231
28232         function DEFAULT_COMPARE(a, b) {
28233           return a > b ? 1 : a < b ? -1 : 0;
28234         }
28235         /**
28236          * Simple top down splay, not requiring i to be in the tree t.
28237          */
28238
28239
28240         function splay(i, t, comparator) {
28241           var N = new Node(null, null);
28242           var l = N;
28243           var r = N;
28244
28245           while (true) {
28246             var cmp = comparator(i, t.key); //if (i < t.key) {
28247
28248             if (cmp < 0) {
28249               if (t.left === null) break; //if (i < t.left.key) {
28250
28251               if (comparator(i, t.left.key) < 0) {
28252                 var y = t.left;
28253                 /* rotate right */
28254
28255                 t.left = y.right;
28256                 y.right = t;
28257                 t = y;
28258                 if (t.left === null) break;
28259               }
28260
28261               r.left = t;
28262               /* link right */
28263
28264               r = t;
28265               t = t.left; //} else if (i > t.key) {
28266             } else if (cmp > 0) {
28267               if (t.right === null) break; //if (i > t.right.key) {
28268
28269               if (comparator(i, t.right.key) > 0) {
28270                 var y = t.right;
28271                 /* rotate left */
28272
28273                 t.right = y.left;
28274                 y.left = t;
28275                 t = y;
28276                 if (t.right === null) break;
28277               }
28278
28279               l.right = t;
28280               /* link left */
28281
28282               l = t;
28283               t = t.right;
28284             } else break;
28285           }
28286           /* assemble */
28287
28288
28289           l.right = t.left;
28290           r.left = t.right;
28291           t.left = N.right;
28292           t.right = N.left;
28293           return t;
28294         }
28295
28296         function insert(i, data, t, comparator) {
28297           var node = new Node(i, data);
28298
28299           if (t === null) {
28300             node.left = node.right = null;
28301             return node;
28302           }
28303
28304           t = splay(i, t, comparator);
28305           var cmp = comparator(i, t.key);
28306
28307           if (cmp < 0) {
28308             node.left = t.left;
28309             node.right = t;
28310             t.left = null;
28311           } else if (cmp >= 0) {
28312             node.right = t.right;
28313             node.left = t;
28314             t.right = null;
28315           }
28316
28317           return node;
28318         }
28319
28320         function split$2(key, v, comparator) {
28321           var left = null;
28322           var right = null;
28323
28324           if (v) {
28325             v = splay(key, v, comparator);
28326             var cmp = comparator(v.key, key);
28327
28328             if (cmp === 0) {
28329               left = v.left;
28330               right = v.right;
28331             } else if (cmp < 0) {
28332               right = v.right;
28333               v.right = null;
28334               left = v;
28335             } else {
28336               left = v.left;
28337               v.left = null;
28338               right = v;
28339             }
28340           }
28341
28342           return {
28343             left: left,
28344             right: right
28345           };
28346         }
28347
28348         function merge$3(left, right, comparator) {
28349           if (right === null) return left;
28350           if (left === null) return right;
28351           right = splay(left.key, right, comparator);
28352           right.left = left;
28353           return right;
28354         }
28355         /**
28356          * Prints level of the tree
28357          */
28358
28359
28360         function printRow(root, prefix, isTail, out, printNode) {
28361           if (root) {
28362             out("" + prefix + (isTail ? '└── ' : '├── ') + printNode(root) + "\n");
28363             var indent = prefix + (isTail ? '    ' : '│   ');
28364             if (root.left) printRow(root.left, indent, false, out, printNode);
28365             if (root.right) printRow(root.right, indent, true, out, printNode);
28366           }
28367         }
28368
28369         var Tree =
28370         /** @class */
28371         function () {
28372           function Tree(comparator) {
28373             if (comparator === void 0) {
28374               comparator = DEFAULT_COMPARE;
28375             }
28376
28377             this._root = null;
28378             this._size = 0;
28379             this._comparator = comparator;
28380           }
28381           /**
28382            * Inserts a key, allows duplicates
28383            */
28384
28385
28386           Tree.prototype.insert = function (key, data) {
28387             this._size++;
28388             return this._root = insert(key, data, this._root, this._comparator);
28389           };
28390           /**
28391            * Adds a key, if it is not present in the tree
28392            */
28393
28394
28395           Tree.prototype.add = function (key, data) {
28396             var node = new Node(key, data);
28397
28398             if (this._root === null) {
28399               node.left = node.right = null;
28400               this._size++;
28401               this._root = node;
28402             }
28403
28404             var comparator = this._comparator;
28405             var t = splay(key, this._root, comparator);
28406             var cmp = comparator(key, t.key);
28407             if (cmp === 0) this._root = t;else {
28408               if (cmp < 0) {
28409                 node.left = t.left;
28410                 node.right = t;
28411                 t.left = null;
28412               } else if (cmp > 0) {
28413                 node.right = t.right;
28414                 node.left = t;
28415                 t.right = null;
28416               }
28417
28418               this._size++;
28419               this._root = node;
28420             }
28421             return this._root;
28422           };
28423           /**
28424            * @param  {Key} key
28425            * @return {Node|null}
28426            */
28427
28428
28429           Tree.prototype.remove = function (key) {
28430             this._root = this._remove(key, this._root, this._comparator);
28431           };
28432           /**
28433            * Deletes i from the tree if it's there
28434            */
28435
28436
28437           Tree.prototype._remove = function (i, t, comparator) {
28438             var x;
28439             if (t === null) return null;
28440             t = splay(i, t, comparator);
28441             var cmp = comparator(i, t.key);
28442
28443             if (cmp === 0) {
28444               /* found it */
28445               if (t.left === null) {
28446                 x = t.right;
28447               } else {
28448                 x = splay(i, t.left, comparator);
28449                 x.right = t.right;
28450               }
28451
28452               this._size--;
28453               return x;
28454             }
28455
28456             return t;
28457             /* It wasn't there */
28458           };
28459           /**
28460            * Removes and returns the node with smallest key
28461            */
28462
28463
28464           Tree.prototype.pop = function () {
28465             var node = this._root;
28466
28467             if (node) {
28468               while (node.left) {
28469                 node = node.left;
28470               }
28471
28472               this._root = splay(node.key, this._root, this._comparator);
28473               this._root = this._remove(node.key, this._root, this._comparator);
28474               return {
28475                 key: node.key,
28476                 data: node.data
28477               };
28478             }
28479
28480             return null;
28481           };
28482           /**
28483            * Find without splaying
28484            */
28485
28486
28487           Tree.prototype.findStatic = function (key) {
28488             var current = this._root;
28489             var compare = this._comparator;
28490
28491             while (current) {
28492               var cmp = compare(key, current.key);
28493               if (cmp === 0) return current;else if (cmp < 0) current = current.left;else current = current.right;
28494             }
28495
28496             return null;
28497           };
28498
28499           Tree.prototype.find = function (key) {
28500             if (this._root) {
28501               this._root = splay(key, this._root, this._comparator);
28502               if (this._comparator(key, this._root.key) !== 0) return null;
28503             }
28504
28505             return this._root;
28506           };
28507
28508           Tree.prototype.contains = function (key) {
28509             var current = this._root;
28510             var compare = this._comparator;
28511
28512             while (current) {
28513               var cmp = compare(key, current.key);
28514               if (cmp === 0) return true;else if (cmp < 0) current = current.left;else current = current.right;
28515             }
28516
28517             return false;
28518           };
28519
28520           Tree.prototype.forEach = function (visitor, ctx) {
28521             var current = this._root;
28522             var Q = [];
28523             /* Initialize stack s */
28524
28525             var done = false;
28526
28527             while (!done) {
28528               if (current !== null) {
28529                 Q.push(current);
28530                 current = current.left;
28531               } else {
28532                 if (Q.length !== 0) {
28533                   current = Q.pop();
28534                   visitor.call(ctx, current);
28535                   current = current.right;
28536                 } else done = true;
28537               }
28538             }
28539
28540             return this;
28541           };
28542           /**
28543            * Walk key range from `low` to `high`. Stops if `fn` returns a value.
28544            */
28545
28546
28547           Tree.prototype.range = function (low, high, fn, ctx) {
28548             var Q = [];
28549             var compare = this._comparator;
28550             var node = this._root;
28551             var cmp;
28552
28553             while (Q.length !== 0 || node) {
28554               if (node) {
28555                 Q.push(node);
28556                 node = node.left;
28557               } else {
28558                 node = Q.pop();
28559                 cmp = compare(node.key, high);
28560
28561                 if (cmp > 0) {
28562                   break;
28563                 } else if (compare(node.key, low) >= 0) {
28564                   if (fn.call(ctx, node)) return this; // stop if smth is returned
28565                 }
28566
28567                 node = node.right;
28568               }
28569             }
28570
28571             return this;
28572           };
28573           /**
28574            * Returns array of keys
28575            */
28576
28577
28578           Tree.prototype.keys = function () {
28579             var keys = [];
28580             this.forEach(function (_a) {
28581               var key = _a.key;
28582               return keys.push(key);
28583             });
28584             return keys;
28585           };
28586           /**
28587            * Returns array of all the data in the nodes
28588            */
28589
28590
28591           Tree.prototype.values = function () {
28592             var values = [];
28593             this.forEach(function (_a) {
28594               var data = _a.data;
28595               return values.push(data);
28596             });
28597             return values;
28598           };
28599
28600           Tree.prototype.min = function () {
28601             if (this._root) return this.minNode(this._root).key;
28602             return null;
28603           };
28604
28605           Tree.prototype.max = function () {
28606             if (this._root) return this.maxNode(this._root).key;
28607             return null;
28608           };
28609
28610           Tree.prototype.minNode = function (t) {
28611             if (t === void 0) {
28612               t = this._root;
28613             }
28614
28615             if (t) while (t.left) {
28616               t = t.left;
28617             }
28618             return t;
28619           };
28620
28621           Tree.prototype.maxNode = function (t) {
28622             if (t === void 0) {
28623               t = this._root;
28624             }
28625
28626             if (t) while (t.right) {
28627               t = t.right;
28628             }
28629             return t;
28630           };
28631           /**
28632            * Returns node at given index
28633            */
28634
28635
28636           Tree.prototype.at = function (index) {
28637             var current = this._root;
28638             var done = false;
28639             var i = 0;
28640             var Q = [];
28641
28642             while (!done) {
28643               if (current) {
28644                 Q.push(current);
28645                 current = current.left;
28646               } else {
28647                 if (Q.length > 0) {
28648                   current = Q.pop();
28649                   if (i === index) return current;
28650                   i++;
28651                   current = current.right;
28652                 } else done = true;
28653               }
28654             }
28655
28656             return null;
28657           };
28658
28659           Tree.prototype.next = function (d) {
28660             var root = this._root;
28661             var successor = null;
28662
28663             if (d.right) {
28664               successor = d.right;
28665
28666               while (successor.left) {
28667                 successor = successor.left;
28668               }
28669
28670               return successor;
28671             }
28672
28673             var comparator = this._comparator;
28674
28675             while (root) {
28676               var cmp = comparator(d.key, root.key);
28677               if (cmp === 0) break;else if (cmp < 0) {
28678                 successor = root;
28679                 root = root.left;
28680               } else root = root.right;
28681             }
28682
28683             return successor;
28684           };
28685
28686           Tree.prototype.prev = function (d) {
28687             var root = this._root;
28688             var predecessor = null;
28689
28690             if (d.left !== null) {
28691               predecessor = d.left;
28692
28693               while (predecessor.right) {
28694                 predecessor = predecessor.right;
28695               }
28696
28697               return predecessor;
28698             }
28699
28700             var comparator = this._comparator;
28701
28702             while (root) {
28703               var cmp = comparator(d.key, root.key);
28704               if (cmp === 0) break;else if (cmp < 0) root = root.left;else {
28705                 predecessor = root;
28706                 root = root.right;
28707               }
28708             }
28709
28710             return predecessor;
28711           };
28712
28713           Tree.prototype.clear = function () {
28714             this._root = null;
28715             this._size = 0;
28716             return this;
28717           };
28718
28719           Tree.prototype.toList = function () {
28720             return toList(this._root);
28721           };
28722           /**
28723            * Bulk-load items. Both array have to be same size
28724            */
28725
28726
28727           Tree.prototype.load = function (keys, values, presort) {
28728             if (values === void 0) {
28729               values = [];
28730             }
28731
28732             if (presort === void 0) {
28733               presort = false;
28734             }
28735
28736             var size = keys.length;
28737             var comparator = this._comparator; // sort if needed
28738
28739             if (presort) sort(keys, values, 0, size - 1, comparator);
28740
28741             if (this._root === null) {
28742               // empty tree
28743               this._root = loadRecursive(keys, values, 0, size);
28744               this._size = size;
28745             } else {
28746               // that re-builds the whole tree from two in-order traversals
28747               var mergedList = mergeLists(this.toList(), createList(keys, values), comparator);
28748               size = this._size + size;
28749               this._root = sortedListToBST({
28750                 head: mergedList
28751               }, 0, size);
28752             }
28753
28754             return this;
28755           };
28756
28757           Tree.prototype.isEmpty = function () {
28758             return this._root === null;
28759           };
28760
28761           Object.defineProperty(Tree.prototype, "size", {
28762             get: function get() {
28763               return this._size;
28764             },
28765             enumerable: true,
28766             configurable: true
28767           });
28768           Object.defineProperty(Tree.prototype, "root", {
28769             get: function get() {
28770               return this._root;
28771             },
28772             enumerable: true,
28773             configurable: true
28774           });
28775
28776           Tree.prototype.toString = function (printNode) {
28777             if (printNode === void 0) {
28778               printNode = function printNode(n) {
28779                 return String(n.key);
28780               };
28781             }
28782
28783             var out = [];
28784             printRow(this._root, '', true, function (v) {
28785               return out.push(v);
28786             }, printNode);
28787             return out.join('');
28788           };
28789
28790           Tree.prototype.update = function (key, newKey, newData) {
28791             var comparator = this._comparator;
28792
28793             var _a = split$2(key, this._root, comparator),
28794                 left = _a.left,
28795                 right = _a.right;
28796
28797             if (comparator(key, newKey) < 0) {
28798               right = insert(newKey, newData, right, comparator);
28799             } else {
28800               left = insert(newKey, newData, left, comparator);
28801             }
28802
28803             this._root = merge$3(left, right, comparator);
28804           };
28805
28806           Tree.prototype.split = function (key) {
28807             return split$2(key, this._root, this._comparator);
28808           };
28809
28810           return Tree;
28811         }();
28812
28813         function loadRecursive(keys, values, start, end) {
28814           var size = end - start;
28815
28816           if (size > 0) {
28817             var middle = start + Math.floor(size / 2);
28818             var key = keys[middle];
28819             var data = values[middle];
28820             var node = new Node(key, data);
28821             node.left = loadRecursive(keys, values, start, middle);
28822             node.right = loadRecursive(keys, values, middle + 1, end);
28823             return node;
28824           }
28825
28826           return null;
28827         }
28828
28829         function createList(keys, values) {
28830           var head = new Node(null, null);
28831           var p = head;
28832
28833           for (var i = 0; i < keys.length; i++) {
28834             p = p.next = new Node(keys[i], values[i]);
28835           }
28836
28837           p.next = null;
28838           return head.next;
28839         }
28840
28841         function toList(root) {
28842           var current = root;
28843           var Q = [];
28844           var done = false;
28845           var head = new Node(null, null);
28846           var p = head;
28847
28848           while (!done) {
28849             if (current) {
28850               Q.push(current);
28851               current = current.left;
28852             } else {
28853               if (Q.length > 0) {
28854                 current = p = p.next = Q.pop();
28855                 current = current.right;
28856               } else done = true;
28857             }
28858           }
28859
28860           p.next = null; // that'll work even if the tree was empty
28861
28862           return head.next;
28863         }
28864
28865         function sortedListToBST(list, start, end) {
28866           var size = end - start;
28867
28868           if (size > 0) {
28869             var middle = start + Math.floor(size / 2);
28870             var left = sortedListToBST(list, start, middle);
28871             var root = list.head;
28872             root.left = left;
28873             list.head = list.head.next;
28874             root.right = sortedListToBST(list, middle + 1, end);
28875             return root;
28876           }
28877
28878           return null;
28879         }
28880
28881         function mergeLists(l1, l2, compare) {
28882           var head = new Node(null, null); // dummy
28883
28884           var p = head;
28885           var p1 = l1;
28886           var p2 = l2;
28887
28888           while (p1 !== null && p2 !== null) {
28889             if (compare(p1.key, p2.key) < 0) {
28890               p.next = p1;
28891               p1 = p1.next;
28892             } else {
28893               p.next = p2;
28894               p2 = p2.next;
28895             }
28896
28897             p = p.next;
28898           }
28899
28900           if (p1 !== null) {
28901             p.next = p1;
28902           } else if (p2 !== null) {
28903             p.next = p2;
28904           }
28905
28906           return head.next;
28907         }
28908
28909         function sort(keys, values, left, right, compare) {
28910           if (left >= right) return;
28911           var pivot = keys[left + right >> 1];
28912           var i = left - 1;
28913           var j = right + 1;
28914
28915           while (true) {
28916             do {
28917               i++;
28918             } while (compare(keys[i], pivot) < 0);
28919
28920             do {
28921               j--;
28922             } while (compare(keys[j], pivot) > 0);
28923
28924             if (i >= j) break;
28925             var tmp = keys[i];
28926             keys[i] = keys[j];
28927             keys[j] = tmp;
28928             tmp = values[i];
28929             values[i] = values[j];
28930             values[j] = tmp;
28931           }
28932
28933           sort(keys, values, left, j, compare);
28934           sort(keys, values, j + 1, right, compare);
28935         }
28936
28937         function _classCallCheck(instance, Constructor) {
28938           if (!(instance instanceof Constructor)) {
28939             throw new TypeError("Cannot call a class as a function");
28940           }
28941         }
28942
28943         function _defineProperties(target, props) {
28944           for (var i = 0; i < props.length; i++) {
28945             var descriptor = props[i];
28946             descriptor.enumerable = descriptor.enumerable || false;
28947             descriptor.configurable = true;
28948             if ("value" in descriptor) descriptor.writable = true;
28949             Object.defineProperty(target, descriptor.key, descriptor);
28950           }
28951         }
28952
28953         function _createClass(Constructor, protoProps, staticProps) {
28954           if (protoProps) _defineProperties(Constructor.prototype, protoProps);
28955           if (staticProps) _defineProperties(Constructor, staticProps);
28956           return Constructor;
28957         }
28958         /**
28959          * A bounding box has the format:
28960          *
28961          *  { ll: { x: xmin, y: ymin }, ur: { x: xmax, y: ymax } }
28962          *
28963          */
28964
28965
28966         var isInBbox = function isInBbox(bbox, point) {
28967           return bbox.ll.x <= point.x && point.x <= bbox.ur.x && bbox.ll.y <= point.y && point.y <= bbox.ur.y;
28968         };
28969         /* Returns either null, or a bbox (aka an ordered pair of points)
28970          * If there is only one point of overlap, a bbox with identical points
28971          * will be returned */
28972
28973
28974         var getBboxOverlap = function getBboxOverlap(b1, b2) {
28975           // check if the bboxes overlap at all
28976           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
28977
28978           var lowerX = b1.ll.x < b2.ll.x ? b2.ll.x : b1.ll.x;
28979           var upperX = b1.ur.x < b2.ur.x ? b1.ur.x : b2.ur.x; // find the middle two Y values
28980
28981           var lowerY = b1.ll.y < b2.ll.y ? b2.ll.y : b1.ll.y;
28982           var upperY = b1.ur.y < b2.ur.y ? b1.ur.y : b2.ur.y; // put those middle values together to get the overlap
28983
28984           return {
28985             ll: {
28986               x: lowerX,
28987               y: lowerY
28988             },
28989             ur: {
28990               x: upperX,
28991               y: upperY
28992             }
28993           };
28994         };
28995         /* Javascript doesn't do integer math. Everything is
28996          * floating point with percision Number.EPSILON.
28997          *
28998          * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON
28999          */
29000
29001
29002         var epsilon = Number.EPSILON; // IE Polyfill
29003
29004         if (epsilon === undefined) epsilon = Math.pow(2, -52);
29005         var EPSILON_SQ = epsilon * epsilon;
29006         /* FLP comparator */
29007
29008         var cmp = function cmp(a, b) {
29009           // check if they're both 0
29010           if (-epsilon < a && a < epsilon) {
29011             if (-epsilon < b && b < epsilon) {
29012               return 0;
29013             }
29014           } // check if they're flp equal
29015
29016
29017           var ab = a - b;
29018
29019           if (ab * ab < EPSILON_SQ * a * b) {
29020             return 0;
29021           } // normal comparison
29022
29023
29024           return a < b ? -1 : 1;
29025         };
29026         /**
29027          * This class rounds incoming values sufficiently so that
29028          * floating points problems are, for the most part, avoided.
29029          *
29030          * Incoming points are have their x & y values tested against
29031          * all previously seen x & y values. If either is 'too close'
29032          * to a previously seen value, it's value is 'snapped' to the
29033          * previously seen value.
29034          *
29035          * All points should be rounded by this class before being
29036          * stored in any data structures in the rest of this algorithm.
29037          */
29038
29039
29040         var PtRounder = /*#__PURE__*/function () {
29041           function PtRounder() {
29042             _classCallCheck(this, PtRounder);
29043
29044             this.reset();
29045           }
29046
29047           _createClass(PtRounder, [{
29048             key: "reset",
29049             value: function reset() {
29050               this.xRounder = new CoordRounder();
29051               this.yRounder = new CoordRounder();
29052             }
29053           }, {
29054             key: "round",
29055             value: function round(x, y) {
29056               return {
29057                 x: this.xRounder.round(x),
29058                 y: this.yRounder.round(y)
29059               };
29060             }
29061           }]);
29062
29063           return PtRounder;
29064         }();
29065
29066         var CoordRounder = /*#__PURE__*/function () {
29067           function CoordRounder() {
29068             _classCallCheck(this, CoordRounder);
29069
29070             this.tree = new Tree(); // preseed with 0 so we don't end up with values < Number.EPSILON
29071
29072             this.round(0);
29073           } // Note: this can rounds input values backwards or forwards.
29074           //       You might ask, why not restrict this to just rounding
29075           //       forwards? Wouldn't that allow left endpoints to always
29076           //       remain left endpoints during splitting (never change to
29077           //       right). No - it wouldn't, because we snap intersections
29078           //       to endpoints (to establish independence from the segment
29079           //       angle for t-intersections).
29080
29081
29082           _createClass(CoordRounder, [{
29083             key: "round",
29084             value: function round(coord) {
29085               var node = this.tree.add(coord);
29086               var prevNode = this.tree.prev(node);
29087
29088               if (prevNode !== null && cmp(node.key, prevNode.key) === 0) {
29089                 this.tree.remove(coord);
29090                 return prevNode.key;
29091               }
29092
29093               var nextNode = this.tree.next(node);
29094
29095               if (nextNode !== null && cmp(node.key, nextNode.key) === 0) {
29096                 this.tree.remove(coord);
29097                 return nextNode.key;
29098               }
29099
29100               return coord;
29101             }
29102           }]);
29103
29104           return CoordRounder;
29105         }(); // singleton available by import
29106
29107
29108         var rounder = new PtRounder();
29109         /* Cross Product of two vectors with first point at origin */
29110
29111         var crossProduct = function crossProduct(a, b) {
29112           return a.x * b.y - a.y * b.x;
29113         };
29114         /* Dot Product of two vectors with first point at origin */
29115
29116
29117         var dotProduct = function dotProduct(a, b) {
29118           return a.x * b.x + a.y * b.y;
29119         };
29120         /* Comparator for two vectors with same starting point */
29121
29122
29123         var compareVectorAngles = function compareVectorAngles(basePt, endPt1, endPt2) {
29124           var v1 = {
29125             x: endPt1.x - basePt.x,
29126             y: endPt1.y - basePt.y
29127           };
29128           var v2 = {
29129             x: endPt2.x - basePt.x,
29130             y: endPt2.y - basePt.y
29131           };
29132           var kross = crossProduct(v1, v2);
29133           return cmp(kross, 0);
29134         };
29135
29136         var length = function length(v) {
29137           return Math.sqrt(dotProduct(v, v));
29138         };
29139         /* Get the sine of the angle from pShared -> pAngle to pShaed -> pBase */
29140
29141
29142         var sineOfAngle = function sineOfAngle(pShared, pBase, pAngle) {
29143           var vBase = {
29144             x: pBase.x - pShared.x,
29145             y: pBase.y - pShared.y
29146           };
29147           var vAngle = {
29148             x: pAngle.x - pShared.x,
29149             y: pAngle.y - pShared.y
29150           };
29151           return crossProduct(vAngle, vBase) / length(vAngle) / length(vBase);
29152         };
29153         /* Get the cosine of the angle from pShared -> pAngle to pShaed -> pBase */
29154
29155
29156         var cosineOfAngle = function cosineOfAngle(pShared, pBase, pAngle) {
29157           var vBase = {
29158             x: pBase.x - pShared.x,
29159             y: pBase.y - pShared.y
29160           };
29161           var vAngle = {
29162             x: pAngle.x - pShared.x,
29163             y: pAngle.y - pShared.y
29164           };
29165           return dotProduct(vAngle, vBase) / length(vAngle) / length(vBase);
29166         };
29167         /* Get the x coordinate where the given line (defined by a point and vector)
29168          * crosses the horizontal line with the given y coordiante.
29169          * In the case of parrallel lines (including overlapping ones) returns null. */
29170
29171
29172         var horizontalIntersection = function horizontalIntersection(pt, v, y) {
29173           if (v.y === 0) return null;
29174           return {
29175             x: pt.x + v.x / v.y * (y - pt.y),
29176             y: y
29177           };
29178         };
29179         /* Get the y coordinate where the given line (defined by a point and vector)
29180          * crosses the vertical line with the given x coordiante.
29181          * In the case of parrallel lines (including overlapping ones) returns null. */
29182
29183
29184         var verticalIntersection = function verticalIntersection(pt, v, x) {
29185           if (v.x === 0) return null;
29186           return {
29187             x: x,
29188             y: pt.y + v.y / v.x * (x - pt.x)
29189           };
29190         };
29191         /* Get the intersection of two lines, each defined by a base point and a vector.
29192          * In the case of parrallel lines (including overlapping ones) returns null. */
29193
29194
29195         var intersection = function intersection(pt1, v1, pt2, v2) {
29196           // take some shortcuts for vertical and horizontal lines
29197           // this also ensures we don't calculate an intersection and then discover
29198           // it's actually outside the bounding box of the line
29199           if (v1.x === 0) return verticalIntersection(pt2, v2, pt1.x);
29200           if (v2.x === 0) return verticalIntersection(pt1, v1, pt2.x);
29201           if (v1.y === 0) return horizontalIntersection(pt2, v2, pt1.y);
29202           if (v2.y === 0) return horizontalIntersection(pt1, v1, pt2.y); // General case for non-overlapping segments.
29203           // This algorithm is based on Schneider and Eberly.
29204           // http://www.cimec.org.ar/~ncalvo/Schneider_Eberly.pdf - pg 244
29205
29206           var kross = crossProduct(v1, v2);
29207           if (kross == 0) return null;
29208           var ve = {
29209             x: pt2.x - pt1.x,
29210             y: pt2.y - pt1.y
29211           };
29212           var d1 = crossProduct(ve, v1) / kross;
29213           var d2 = crossProduct(ve, v2) / kross; // take the average of the two calculations to minimize rounding error
29214
29215           var x1 = pt1.x + d2 * v1.x,
29216               x2 = pt2.x + d1 * v2.x;
29217           var y1 = pt1.y + d2 * v1.y,
29218               y2 = pt2.y + d1 * v2.y;
29219           var x = (x1 + x2) / 2;
29220           var y = (y1 + y2) / 2;
29221           return {
29222             x: x,
29223             y: y
29224           };
29225         };
29226
29227         var SweepEvent = /*#__PURE__*/function () {
29228           _createClass(SweepEvent, null, [{
29229             key: "compare",
29230             // for ordering sweep events in the sweep event queue
29231             value: function compare(a, b) {
29232               // favor event with a point that the sweep line hits first
29233               var ptCmp = SweepEvent.comparePoints(a.point, b.point);
29234               if (ptCmp !== 0) return ptCmp; // the points are the same, so link them if needed
29235
29236               if (a.point !== b.point) a.link(b); // favor right events over left
29237
29238               if (a.isLeft !== b.isLeft) return a.isLeft ? 1 : -1; // we have two matching left or right endpoints
29239               // ordering of this case is the same as for their segments
29240
29241               return Segment.compare(a.segment, b.segment);
29242             } // for ordering points in sweep line order
29243
29244           }, {
29245             key: "comparePoints",
29246             value: function comparePoints(aPt, bPt) {
29247               if (aPt.x < bPt.x) return -1;
29248               if (aPt.x > bPt.x) return 1;
29249               if (aPt.y < bPt.y) return -1;
29250               if (aPt.y > bPt.y) return 1;
29251               return 0;
29252             } // Warning: 'point' input will be modified and re-used (for performance)
29253
29254           }]);
29255
29256           function SweepEvent(point, isLeft) {
29257             _classCallCheck(this, SweepEvent);
29258
29259             if (point.events === undefined) point.events = [this];else point.events.push(this);
29260             this.point = point;
29261             this.isLeft = isLeft; // this.segment, this.otherSE set by factory
29262           }
29263
29264           _createClass(SweepEvent, [{
29265             key: "link",
29266             value: function link(other) {
29267               if (other.point === this.point) {
29268                 throw new Error('Tried to link already linked events');
29269               }
29270
29271               var otherEvents = other.point.events;
29272
29273               for (var i = 0, iMax = otherEvents.length; i < iMax; i++) {
29274                 var evt = otherEvents[i];
29275                 this.point.events.push(evt);
29276                 evt.point = this.point;
29277               }
29278
29279               this.checkForConsuming();
29280             }
29281             /* Do a pass over our linked events and check to see if any pair
29282              * of segments match, and should be consumed. */
29283
29284           }, {
29285             key: "checkForConsuming",
29286             value: function checkForConsuming() {
29287               // FIXME: The loops in this method run O(n^2) => no good.
29288               //        Maintain little ordered sweep event trees?
29289               //        Can we maintaining an ordering that avoids the need
29290               //        for the re-sorting with getLeftmostComparator in geom-out?
29291               // Compare each pair of events to see if other events also match
29292               var numEvents = this.point.events.length;
29293
29294               for (var i = 0; i < numEvents; i++) {
29295                 var evt1 = this.point.events[i];
29296                 if (evt1.segment.consumedBy !== undefined) continue;
29297
29298                 for (var j = i + 1; j < numEvents; j++) {
29299                   var evt2 = this.point.events[j];
29300                   if (evt2.consumedBy !== undefined) continue;
29301                   if (evt1.otherSE.point.events !== evt2.otherSE.point.events) continue;
29302                   evt1.segment.consume(evt2.segment);
29303                 }
29304               }
29305             }
29306           }, {
29307             key: "getAvailableLinkedEvents",
29308             value: function getAvailableLinkedEvents() {
29309               // point.events is always of length 2 or greater
29310               var events = [];
29311
29312               for (var i = 0, iMax = this.point.events.length; i < iMax; i++) {
29313                 var evt = this.point.events[i];
29314
29315                 if (evt !== this && !evt.segment.ringOut && evt.segment.isInResult()) {
29316                   events.push(evt);
29317                 }
29318               }
29319
29320               return events;
29321             }
29322             /**
29323              * Returns a comparator function for sorting linked events that will
29324              * favor the event that will give us the smallest left-side angle.
29325              * All ring construction starts as low as possible heading to the right,
29326              * so by always turning left as sharp as possible we'll get polygons
29327              * without uncessary loops & holes.
29328              *
29329              * The comparator function has a compute cache such that it avoids
29330              * re-computing already-computed values.
29331              */
29332
29333           }, {
29334             key: "getLeftmostComparator",
29335             value: function getLeftmostComparator(baseEvent) {
29336               var _this = this;
29337
29338               var cache = new Map();
29339
29340               var fillCache = function fillCache(linkedEvent) {
29341                 var nextEvent = linkedEvent.otherSE;
29342                 cache.set(linkedEvent, {
29343                   sine: sineOfAngle(_this.point, baseEvent.point, nextEvent.point),
29344                   cosine: cosineOfAngle(_this.point, baseEvent.point, nextEvent.point)
29345                 });
29346               };
29347
29348               return function (a, b) {
29349                 if (!cache.has(a)) fillCache(a);
29350                 if (!cache.has(b)) fillCache(b);
29351
29352                 var _cache$get = cache.get(a),
29353                     asine = _cache$get.sine,
29354                     acosine = _cache$get.cosine;
29355
29356                 var _cache$get2 = cache.get(b),
29357                     bsine = _cache$get2.sine,
29358                     bcosine = _cache$get2.cosine; // both on or above x-axis
29359
29360
29361                 if (asine >= 0 && bsine >= 0) {
29362                   if (acosine < bcosine) return 1;
29363                   if (acosine > bcosine) return -1;
29364                   return 0;
29365                 } // both below x-axis
29366
29367
29368                 if (asine < 0 && bsine < 0) {
29369                   if (acosine < bcosine) return -1;
29370                   if (acosine > bcosine) return 1;
29371                   return 0;
29372                 } // one above x-axis, one below
29373
29374
29375                 if (bsine < asine) return -1;
29376                 if (bsine > asine) return 1;
29377                 return 0;
29378               };
29379             }
29380           }]);
29381
29382           return SweepEvent;
29383         }(); // segments and sweep events when all else is identical
29384
29385
29386         var segmentId = 0;
29387
29388         var Segment = /*#__PURE__*/function () {
29389           _createClass(Segment, null, [{
29390             key: "compare",
29391
29392             /* This compare() function is for ordering segments in the sweep
29393              * line tree, and does so according to the following criteria:
29394              *
29395              * Consider the vertical line that lies an infinestimal step to the
29396              * right of the right-more of the two left endpoints of the input
29397              * segments. Imagine slowly moving a point up from negative infinity
29398              * in the increasing y direction. Which of the two segments will that
29399              * point intersect first? That segment comes 'before' the other one.
29400              *
29401              * If neither segment would be intersected by such a line, (if one
29402              * or more of the segments are vertical) then the line to be considered
29403              * is directly on the right-more of the two left inputs.
29404              */
29405             value: function compare(a, b) {
29406               var alx = a.leftSE.point.x;
29407               var blx = b.leftSE.point.x;
29408               var arx = a.rightSE.point.x;
29409               var brx = b.rightSE.point.x; // check if they're even in the same vertical plane
29410
29411               if (brx < alx) return 1;
29412               if (arx < blx) return -1;
29413               var aly = a.leftSE.point.y;
29414               var bly = b.leftSE.point.y;
29415               var ary = a.rightSE.point.y;
29416               var bry = b.rightSE.point.y; // is left endpoint of segment B the right-more?
29417
29418               if (alx < blx) {
29419                 // are the two segments in the same horizontal plane?
29420                 if (bly < aly && bly < ary) return 1;
29421                 if (bly > aly && bly > ary) return -1; // is the B left endpoint colinear to segment A?
29422
29423                 var aCmpBLeft = a.comparePoint(b.leftSE.point);
29424                 if (aCmpBLeft < 0) return 1;
29425                 if (aCmpBLeft > 0) return -1; // is the A right endpoint colinear to segment B ?
29426
29427                 var bCmpARight = b.comparePoint(a.rightSE.point);
29428                 if (bCmpARight !== 0) return bCmpARight; // colinear segments, consider the one with left-more
29429                 // left endpoint to be first (arbitrary?)
29430
29431                 return -1;
29432               } // is left endpoint of segment A the right-more?
29433
29434
29435               if (alx > blx) {
29436                 if (aly < bly && aly < bry) return -1;
29437                 if (aly > bly && aly > bry) return 1; // is the A left endpoint colinear to segment B?
29438
29439                 var bCmpALeft = b.comparePoint(a.leftSE.point);
29440                 if (bCmpALeft !== 0) return bCmpALeft; // is the B right endpoint colinear to segment A?
29441
29442                 var aCmpBRight = a.comparePoint(b.rightSE.point);
29443                 if (aCmpBRight < 0) return 1;
29444                 if (aCmpBRight > 0) return -1; // colinear segments, consider the one with left-more
29445                 // left endpoint to be first (arbitrary?)
29446
29447                 return 1;
29448               } // if we get here, the two left endpoints are in the same
29449               // vertical plane, ie alx === blx
29450               // consider the lower left-endpoint to come first
29451
29452
29453               if (aly < bly) return -1;
29454               if (aly > bly) return 1; // left endpoints are identical
29455               // check for colinearity by using the left-more right endpoint
29456               // is the A right endpoint more left-more?
29457
29458               if (arx < brx) {
29459                 var _bCmpARight = b.comparePoint(a.rightSE.point);
29460
29461                 if (_bCmpARight !== 0) return _bCmpARight;
29462               } // is the B right endpoint more left-more?
29463
29464
29465               if (arx > brx) {
29466                 var _aCmpBRight = a.comparePoint(b.rightSE.point);
29467
29468                 if (_aCmpBRight < 0) return 1;
29469                 if (_aCmpBRight > 0) return -1;
29470               }
29471
29472               if (arx !== brx) {
29473                 // are these two [almost] vertical segments with opposite orientation?
29474                 // if so, the one with the lower right endpoint comes first
29475                 var ay = ary - aly;
29476                 var ax = arx - alx;
29477                 var by = bry - bly;
29478                 var bx = brx - blx;
29479                 if (ay > ax && by < bx) return 1;
29480                 if (ay < ax && by > bx) return -1;
29481               } // we have colinear segments with matching orientation
29482               // consider the one with more left-more right endpoint to be first
29483
29484
29485               if (arx > brx) return 1;
29486               if (arx < brx) return -1; // if we get here, two two right endpoints are in the same
29487               // vertical plane, ie arx === brx
29488               // consider the lower right-endpoint to come first
29489
29490               if (ary < bry) return -1;
29491               if (ary > bry) return 1; // right endpoints identical as well, so the segments are idential
29492               // fall back on creation order as consistent tie-breaker
29493
29494               if (a.id < b.id) return -1;
29495               if (a.id > b.id) return 1; // identical segment, ie a === b
29496
29497               return 0;
29498             }
29499             /* Warning: a reference to ringWindings input will be stored,
29500              *  and possibly will be later modified */
29501
29502           }]);
29503
29504           function Segment(leftSE, rightSE, rings, windings) {
29505             _classCallCheck(this, Segment);
29506
29507             this.id = ++segmentId;
29508             this.leftSE = leftSE;
29509             leftSE.segment = this;
29510             leftSE.otherSE = rightSE;
29511             this.rightSE = rightSE;
29512             rightSE.segment = this;
29513             rightSE.otherSE = leftSE;
29514             this.rings = rings;
29515             this.windings = windings; // left unset for performance, set later in algorithm
29516             // this.ringOut, this.consumedBy, this.prev
29517           }
29518
29519           _createClass(Segment, [{
29520             key: "replaceRightSE",
29521
29522             /* When a segment is split, the rightSE is replaced with a new sweep event */
29523             value: function replaceRightSE(newRightSE) {
29524               this.rightSE = newRightSE;
29525               this.rightSE.segment = this;
29526               this.rightSE.otherSE = this.leftSE;
29527               this.leftSE.otherSE = this.rightSE;
29528             }
29529           }, {
29530             key: "bbox",
29531             value: function bbox() {
29532               var y1 = this.leftSE.point.y;
29533               var y2 = this.rightSE.point.y;
29534               return {
29535                 ll: {
29536                   x: this.leftSE.point.x,
29537                   y: y1 < y2 ? y1 : y2
29538                 },
29539                 ur: {
29540                   x: this.rightSE.point.x,
29541                   y: y1 > y2 ? y1 : y2
29542                 }
29543               };
29544             }
29545             /* A vector from the left point to the right */
29546
29547           }, {
29548             key: "vector",
29549             value: function vector() {
29550               return {
29551                 x: this.rightSE.point.x - this.leftSE.point.x,
29552                 y: this.rightSE.point.y - this.leftSE.point.y
29553               };
29554             }
29555           }, {
29556             key: "isAnEndpoint",
29557             value: function isAnEndpoint(pt) {
29558               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;
29559             }
29560             /* Compare this segment with a point.
29561              *
29562              * A point P is considered to be colinear to a segment if there
29563              * exists a distance D such that if we travel along the segment
29564              * from one * endpoint towards the other a distance D, we find
29565              * ourselves at point P.
29566              *
29567              * Return value indicates:
29568              *
29569              *   1: point lies above the segment (to the left of vertical)
29570              *   0: point is colinear to segment
29571              *  -1: point lies below the segment (to the right of vertical)
29572              */
29573
29574           }, {
29575             key: "comparePoint",
29576             value: function comparePoint(point) {
29577               if (this.isAnEndpoint(point)) return 0;
29578               var lPt = this.leftSE.point;
29579               var rPt = this.rightSE.point;
29580               var v = this.vector(); // Exactly vertical segments.
29581
29582               if (lPt.x === rPt.x) {
29583                 if (point.x === lPt.x) return 0;
29584                 return point.x < lPt.x ? 1 : -1;
29585               } // Nearly vertical segments with an intersection.
29586               // Check to see where a point on the line with matching Y coordinate is.
29587
29588
29589               var yDist = (point.y - lPt.y) / v.y;
29590               var xFromYDist = lPt.x + yDist * v.x;
29591               if (point.x === xFromYDist) return 0; // General case.
29592               // Check to see where a point on the line with matching X coordinate is.
29593
29594               var xDist = (point.x - lPt.x) / v.x;
29595               var yFromXDist = lPt.y + xDist * v.y;
29596               if (point.y === yFromXDist) return 0;
29597               return point.y < yFromXDist ? -1 : 1;
29598             }
29599             /**
29600              * Given another segment, returns the first non-trivial intersection
29601              * between the two segments (in terms of sweep line ordering), if it exists.
29602              *
29603              * A 'non-trivial' intersection is one that will cause one or both of the
29604              * segments to be split(). As such, 'trivial' vs. 'non-trivial' intersection:
29605              *
29606              *   * endpoint of segA with endpoint of segB --> trivial
29607              *   * endpoint of segA with point along segB --> non-trivial
29608              *   * endpoint of segB with point along segA --> non-trivial
29609              *   * point along segA with point along segB --> non-trivial
29610              *
29611              * If no non-trivial intersection exists, return null
29612              * Else, return null.
29613              */
29614
29615           }, {
29616             key: "getIntersection",
29617             value: function getIntersection(other) {
29618               // If bboxes don't overlap, there can't be any intersections
29619               var tBbox = this.bbox();
29620               var oBbox = other.bbox();
29621               var bboxOverlap = getBboxOverlap(tBbox, oBbox);
29622               if (bboxOverlap === null) return null; // We first check to see if the endpoints can be considered intersections.
29623               // This will 'snap' intersections to endpoints if possible, and will
29624               // handle cases of colinearity.
29625
29626               var tlp = this.leftSE.point;
29627               var trp = this.rightSE.point;
29628               var olp = other.leftSE.point;
29629               var orp = other.rightSE.point; // does each endpoint touch the other segment?
29630               // note that we restrict the 'touching' definition to only allow segments
29631               // to touch endpoints that lie forward from where we are in the sweep line pass
29632
29633               var touchesOtherLSE = isInBbox(tBbox, olp) && this.comparePoint(olp) === 0;
29634               var touchesThisLSE = isInBbox(oBbox, tlp) && other.comparePoint(tlp) === 0;
29635               var touchesOtherRSE = isInBbox(tBbox, orp) && this.comparePoint(orp) === 0;
29636               var touchesThisRSE = isInBbox(oBbox, trp) && other.comparePoint(trp) === 0; // do left endpoints match?
29637
29638               if (touchesThisLSE && touchesOtherLSE) {
29639                 // these two cases are for colinear segments with matching left
29640                 // endpoints, and one segment being longer than the other
29641                 if (touchesThisRSE && !touchesOtherRSE) return trp;
29642                 if (!touchesThisRSE && touchesOtherRSE) return orp; // either the two segments match exactly (two trival intersections)
29643                 // or just on their left endpoint (one trivial intersection
29644
29645                 return null;
29646               } // does this left endpoint matches (other doesn't)
29647
29648
29649               if (touchesThisLSE) {
29650                 // check for segments that just intersect on opposing endpoints
29651                 if (touchesOtherRSE) {
29652                   if (tlp.x === orp.x && tlp.y === orp.y) return null;
29653                 } // t-intersection on left endpoint
29654
29655
29656                 return tlp;
29657               } // does other left endpoint matches (this doesn't)
29658
29659
29660               if (touchesOtherLSE) {
29661                 // check for segments that just intersect on opposing endpoints
29662                 if (touchesThisRSE) {
29663                   if (trp.x === olp.x && trp.y === olp.y) return null;
29664                 } // t-intersection on left endpoint
29665
29666
29667                 return olp;
29668               } // trivial intersection on right endpoints
29669
29670
29671               if (touchesThisRSE && touchesOtherRSE) return null; // t-intersections on just one right endpoint
29672
29673               if (touchesThisRSE) return trp;
29674               if (touchesOtherRSE) return orp; // None of our endpoints intersect. Look for a general intersection between
29675               // infinite lines laid over the segments
29676
29677               var pt = intersection(tlp, this.vector(), olp, other.vector()); // are the segments parrallel? Note that if they were colinear with overlap,
29678               // they would have an endpoint intersection and that case was already handled above
29679
29680               if (pt === null) return null; // is the intersection found between the lines not on the segments?
29681
29682               if (!isInBbox(bboxOverlap, pt)) return null; // round the the computed point if needed
29683
29684               return rounder.round(pt.x, pt.y);
29685             }
29686             /**
29687              * Split the given segment into multiple segments on the given points.
29688              *  * Each existing segment will retain its leftSE and a new rightSE will be
29689              *    generated for it.
29690              *  * A new segment will be generated which will adopt the original segment's
29691              *    rightSE, and a new leftSE will be generated for it.
29692              *  * If there are more than two points given to split on, new segments
29693              *    in the middle will be generated with new leftSE and rightSE's.
29694              *  * An array of the newly generated SweepEvents will be returned.
29695              *
29696              * Warning: input array of points is modified
29697              */
29698
29699           }, {
29700             key: "split",
29701             value: function split(point) {
29702               var newEvents = [];
29703               var alreadyLinked = point.events !== undefined;
29704               var newLeftSE = new SweepEvent(point, true);
29705               var newRightSE = new SweepEvent(point, false);
29706               var oldRightSE = this.rightSE;
29707               this.replaceRightSE(newRightSE);
29708               newEvents.push(newRightSE);
29709               newEvents.push(newLeftSE);
29710               var newSeg = new Segment(newLeftSE, oldRightSE, this.rings.slice(), this.windings.slice()); // when splitting a nearly vertical downward-facing segment,
29711               // sometimes one of the resulting new segments is vertical, in which
29712               // case its left and right events may need to be swapped
29713
29714               if (SweepEvent.comparePoints(newSeg.leftSE.point, newSeg.rightSE.point) > 0) {
29715                 newSeg.swapEvents();
29716               }
29717
29718               if (SweepEvent.comparePoints(this.leftSE.point, this.rightSE.point) > 0) {
29719                 this.swapEvents();
29720               } // in the point we just used to create new sweep events with was already
29721               // linked to other events, we need to check if either of the affected
29722               // segments should be consumed
29723
29724
29725               if (alreadyLinked) {
29726                 newLeftSE.checkForConsuming();
29727                 newRightSE.checkForConsuming();
29728               }
29729
29730               return newEvents;
29731             }
29732             /* Swap which event is left and right */
29733
29734           }, {
29735             key: "swapEvents",
29736             value: function swapEvents() {
29737               var tmpEvt = this.rightSE;
29738               this.rightSE = this.leftSE;
29739               this.leftSE = tmpEvt;
29740               this.leftSE.isLeft = true;
29741               this.rightSE.isLeft = false;
29742
29743               for (var i = 0, iMax = this.windings.length; i < iMax; i++) {
29744                 this.windings[i] *= -1;
29745               }
29746             }
29747             /* Consume another segment. We take their rings under our wing
29748              * and mark them as consumed. Use for perfectly overlapping segments */
29749
29750           }, {
29751             key: "consume",
29752             value: function consume(other) {
29753               var consumer = this;
29754               var consumee = other;
29755
29756               while (consumer.consumedBy) {
29757                 consumer = consumer.consumedBy;
29758               }
29759
29760               while (consumee.consumedBy) {
29761                 consumee = consumee.consumedBy;
29762               }
29763
29764               var cmp = Segment.compare(consumer, consumee);
29765               if (cmp === 0) return; // already consumed
29766               // the winner of the consumption is the earlier segment
29767               // according to sweep line ordering
29768
29769               if (cmp > 0) {
29770                 var tmp = consumer;
29771                 consumer = consumee;
29772                 consumee = tmp;
29773               } // make sure a segment doesn't consume it's prev
29774
29775
29776               if (consumer.prev === consumee) {
29777                 var _tmp = consumer;
29778                 consumer = consumee;
29779                 consumee = _tmp;
29780               }
29781
29782               for (var i = 0, iMax = consumee.rings.length; i < iMax; i++) {
29783                 var ring = consumee.rings[i];
29784                 var winding = consumee.windings[i];
29785                 var index = consumer.rings.indexOf(ring);
29786
29787                 if (index === -1) {
29788                   consumer.rings.push(ring);
29789                   consumer.windings.push(winding);
29790                 } else consumer.windings[index] += winding;
29791               }
29792
29793               consumee.rings = null;
29794               consumee.windings = null;
29795               consumee.consumedBy = consumer; // mark sweep events consumed as to maintain ordering in sweep event queue
29796
29797               consumee.leftSE.consumedBy = consumer.leftSE;
29798               consumee.rightSE.consumedBy = consumer.rightSE;
29799             }
29800             /* The first segment previous segment chain that is in the result */
29801
29802           }, {
29803             key: "prevInResult",
29804             value: function prevInResult() {
29805               if (this._prevInResult !== undefined) return this._prevInResult;
29806               if (!this.prev) this._prevInResult = null;else if (this.prev.isInResult()) this._prevInResult = this.prev;else this._prevInResult = this.prev.prevInResult();
29807               return this._prevInResult;
29808             }
29809           }, {
29810             key: "beforeState",
29811             value: function beforeState() {
29812               if (this._beforeState !== undefined) return this._beforeState;
29813               if (!this.prev) this._beforeState = {
29814                 rings: [],
29815                 windings: [],
29816                 multiPolys: []
29817               };else {
29818                 var seg = this.prev.consumedBy || this.prev;
29819                 this._beforeState = seg.afterState();
29820               }
29821               return this._beforeState;
29822             }
29823           }, {
29824             key: "afterState",
29825             value: function afterState() {
29826               if (this._afterState !== undefined) return this._afterState;
29827               var beforeState = this.beforeState();
29828               this._afterState = {
29829                 rings: beforeState.rings.slice(0),
29830                 windings: beforeState.windings.slice(0),
29831                 multiPolys: []
29832               };
29833               var ringsAfter = this._afterState.rings;
29834               var windingsAfter = this._afterState.windings;
29835               var mpsAfter = this._afterState.multiPolys; // calculate ringsAfter, windingsAfter
29836
29837               for (var i = 0, iMax = this.rings.length; i < iMax; i++) {
29838                 var ring = this.rings[i];
29839                 var winding = this.windings[i];
29840                 var index = ringsAfter.indexOf(ring);
29841
29842                 if (index === -1) {
29843                   ringsAfter.push(ring);
29844                   windingsAfter.push(winding);
29845                 } else windingsAfter[index] += winding;
29846               } // calcualte polysAfter
29847
29848
29849               var polysAfter = [];
29850               var polysExclude = [];
29851
29852               for (var _i = 0, _iMax = ringsAfter.length; _i < _iMax; _i++) {
29853                 if (windingsAfter[_i] === 0) continue; // non-zero rule
29854
29855                 var _ring = ringsAfter[_i];
29856                 var poly = _ring.poly;
29857                 if (polysExclude.indexOf(poly) !== -1) continue;
29858                 if (_ring.isExterior) polysAfter.push(poly);else {
29859                   if (polysExclude.indexOf(poly) === -1) polysExclude.push(poly);
29860
29861                   var _index = polysAfter.indexOf(_ring.poly);
29862
29863                   if (_index !== -1) polysAfter.splice(_index, 1);
29864                 }
29865               } // calculate multiPolysAfter
29866
29867
29868               for (var _i2 = 0, _iMax2 = polysAfter.length; _i2 < _iMax2; _i2++) {
29869                 var mp = polysAfter[_i2].multiPoly;
29870                 if (mpsAfter.indexOf(mp) === -1) mpsAfter.push(mp);
29871               }
29872
29873               return this._afterState;
29874             }
29875             /* Is this segment part of the final result? */
29876
29877           }, {
29878             key: "isInResult",
29879             value: function isInResult() {
29880               // if we've been consumed, we're not in the result
29881               if (this.consumedBy) return false;
29882               if (this._isInResult !== undefined) return this._isInResult;
29883               var mpsBefore = this.beforeState().multiPolys;
29884               var mpsAfter = this.afterState().multiPolys;
29885
29886               switch (operation.type) {
29887                 case 'union':
29888                   {
29889                     // UNION - included iff:
29890                     //  * On one side of us there is 0 poly interiors AND
29891                     //  * On the other side there is 1 or more.
29892                     var noBefores = mpsBefore.length === 0;
29893                     var noAfters = mpsAfter.length === 0;
29894                     this._isInResult = noBefores !== noAfters;
29895                     break;
29896                   }
29897
29898                 case 'intersection':
29899                   {
29900                     // INTERSECTION - included iff:
29901                     //  * on one side of us all multipolys are rep. with poly interiors AND
29902                     //  * on the other side of us, not all multipolys are repsented
29903                     //    with poly interiors
29904                     var least;
29905                     var most;
29906
29907                     if (mpsBefore.length < mpsAfter.length) {
29908                       least = mpsBefore.length;
29909                       most = mpsAfter.length;
29910                     } else {
29911                       least = mpsAfter.length;
29912                       most = mpsBefore.length;
29913                     }
29914
29915                     this._isInResult = most === operation.numMultiPolys && least < most;
29916                     break;
29917                   }
29918
29919                 case 'xor':
29920                   {
29921                     // XOR - included iff:
29922                     //  * the difference between the number of multipolys represented
29923                     //    with poly interiors on our two sides is an odd number
29924                     var diff = Math.abs(mpsBefore.length - mpsAfter.length);
29925                     this._isInResult = diff % 2 === 1;
29926                     break;
29927                   }
29928
29929                 case 'difference':
29930                   {
29931                     // DIFFERENCE included iff:
29932                     //  * on exactly one side, we have just the subject
29933                     var isJustSubject = function isJustSubject(mps) {
29934                       return mps.length === 1 && mps[0].isSubject;
29935                     };
29936
29937                     this._isInResult = isJustSubject(mpsBefore) !== isJustSubject(mpsAfter);
29938                     break;
29939                   }
29940
29941                 default:
29942                   throw new Error("Unrecognized operation type found ".concat(operation.type));
29943               }
29944
29945               return this._isInResult;
29946             }
29947           }], [{
29948             key: "fromRing",
29949             value: function fromRing(pt1, pt2, ring) {
29950               var leftPt, rightPt, winding; // ordering the two points according to sweep line ordering
29951
29952               var cmpPts = SweepEvent.comparePoints(pt1, pt2);
29953
29954               if (cmpPts < 0) {
29955                 leftPt = pt1;
29956                 rightPt = pt2;
29957                 winding = 1;
29958               } else if (cmpPts > 0) {
29959                 leftPt = pt2;
29960                 rightPt = pt1;
29961                 winding = -1;
29962               } else throw new Error("Tried to create degenerate segment at [".concat(pt1.x, ", ").concat(pt1.y, "]"));
29963
29964               var leftSE = new SweepEvent(leftPt, true);
29965               var rightSE = new SweepEvent(rightPt, false);
29966               return new Segment(leftSE, rightSE, [ring], [winding]);
29967             }
29968           }]);
29969
29970           return Segment;
29971         }();
29972
29973         var RingIn = /*#__PURE__*/function () {
29974           function RingIn(geomRing, poly, isExterior) {
29975             _classCallCheck(this, RingIn);
29976
29977             if (!Array.isArray(geomRing) || geomRing.length === 0) {
29978               throw new Error('Input geometry is not a valid Polygon or MultiPolygon');
29979             }
29980
29981             this.poly = poly;
29982             this.isExterior = isExterior;
29983             this.segments = [];
29984
29985             if (typeof geomRing[0][0] !== 'number' || typeof geomRing[0][1] !== 'number') {
29986               throw new Error('Input geometry is not a valid Polygon or MultiPolygon');
29987             }
29988
29989             var firstPoint = rounder.round(geomRing[0][0], geomRing[0][1]);
29990             this.bbox = {
29991               ll: {
29992                 x: firstPoint.x,
29993                 y: firstPoint.y
29994               },
29995               ur: {
29996                 x: firstPoint.x,
29997                 y: firstPoint.y
29998               }
29999             };
30000             var prevPoint = firstPoint;
30001
30002             for (var i = 1, iMax = geomRing.length; i < iMax; i++) {
30003               if (typeof geomRing[i][0] !== 'number' || typeof geomRing[i][1] !== 'number') {
30004                 throw new Error('Input geometry is not a valid Polygon or MultiPolygon');
30005               }
30006
30007               var point = rounder.round(geomRing[i][0], geomRing[i][1]); // skip repeated points
30008
30009               if (point.x === prevPoint.x && point.y === prevPoint.y) continue;
30010               this.segments.push(Segment.fromRing(prevPoint, point, this));
30011               if (point.x < this.bbox.ll.x) this.bbox.ll.x = point.x;
30012               if (point.y < this.bbox.ll.y) this.bbox.ll.y = point.y;
30013               if (point.x > this.bbox.ur.x) this.bbox.ur.x = point.x;
30014               if (point.y > this.bbox.ur.y) this.bbox.ur.y = point.y;
30015               prevPoint = point;
30016             } // add segment from last to first if last is not the same as first
30017
30018
30019             if (firstPoint.x !== prevPoint.x || firstPoint.y !== prevPoint.y) {
30020               this.segments.push(Segment.fromRing(prevPoint, firstPoint, this));
30021             }
30022           }
30023
30024           _createClass(RingIn, [{
30025             key: "getSweepEvents",
30026             value: function getSweepEvents() {
30027               var sweepEvents = [];
30028
30029               for (var i = 0, iMax = this.segments.length; i < iMax; i++) {
30030                 var segment = this.segments[i];
30031                 sweepEvents.push(segment.leftSE);
30032                 sweepEvents.push(segment.rightSE);
30033               }
30034
30035               return sweepEvents;
30036             }
30037           }]);
30038
30039           return RingIn;
30040         }();
30041
30042         var PolyIn = /*#__PURE__*/function () {
30043           function PolyIn(geomPoly, multiPoly) {
30044             _classCallCheck(this, PolyIn);
30045
30046             if (!Array.isArray(geomPoly)) {
30047               throw new Error('Input geometry is not a valid Polygon or MultiPolygon');
30048             }
30049
30050             this.exteriorRing = new RingIn(geomPoly[0], this, true); // copy by value
30051
30052             this.bbox = {
30053               ll: {
30054                 x: this.exteriorRing.bbox.ll.x,
30055                 y: this.exteriorRing.bbox.ll.y
30056               },
30057               ur: {
30058                 x: this.exteriorRing.bbox.ur.x,
30059                 y: this.exteriorRing.bbox.ur.y
30060               }
30061             };
30062             this.interiorRings = [];
30063
30064             for (var i = 1, iMax = geomPoly.length; i < iMax; i++) {
30065               var ring = new RingIn(geomPoly[i], this, false);
30066               if (ring.bbox.ll.x < this.bbox.ll.x) this.bbox.ll.x = ring.bbox.ll.x;
30067               if (ring.bbox.ll.y < this.bbox.ll.y) this.bbox.ll.y = ring.bbox.ll.y;
30068               if (ring.bbox.ur.x > this.bbox.ur.x) this.bbox.ur.x = ring.bbox.ur.x;
30069               if (ring.bbox.ur.y > this.bbox.ur.y) this.bbox.ur.y = ring.bbox.ur.y;
30070               this.interiorRings.push(ring);
30071             }
30072
30073             this.multiPoly = multiPoly;
30074           }
30075
30076           _createClass(PolyIn, [{
30077             key: "getSweepEvents",
30078             value: function getSweepEvents() {
30079               var sweepEvents = this.exteriorRing.getSweepEvents();
30080
30081               for (var i = 0, iMax = this.interiorRings.length; i < iMax; i++) {
30082                 var ringSweepEvents = this.interiorRings[i].getSweepEvents();
30083
30084                 for (var j = 0, jMax = ringSweepEvents.length; j < jMax; j++) {
30085                   sweepEvents.push(ringSweepEvents[j]);
30086                 }
30087               }
30088
30089               return sweepEvents;
30090             }
30091           }]);
30092
30093           return PolyIn;
30094         }();
30095
30096         var MultiPolyIn = /*#__PURE__*/function () {
30097           function MultiPolyIn(geom, isSubject) {
30098             _classCallCheck(this, MultiPolyIn);
30099
30100             if (!Array.isArray(geom)) {
30101               throw new Error('Input geometry is not a valid Polygon or MultiPolygon');
30102             }
30103
30104             try {
30105               // if the input looks like a polygon, convert it to a multipolygon
30106               if (typeof geom[0][0][0] === 'number') geom = [geom];
30107             } catch (ex) {// The input is either malformed or has empty arrays.
30108               // In either case, it will be handled later on.
30109             }
30110
30111             this.polys = [];
30112             this.bbox = {
30113               ll: {
30114                 x: Number.POSITIVE_INFINITY,
30115                 y: Number.POSITIVE_INFINITY
30116               },
30117               ur: {
30118                 x: Number.NEGATIVE_INFINITY,
30119                 y: Number.NEGATIVE_INFINITY
30120               }
30121             };
30122
30123             for (var i = 0, iMax = geom.length; i < iMax; i++) {
30124               var poly = new PolyIn(geom[i], this);
30125               if (poly.bbox.ll.x < this.bbox.ll.x) this.bbox.ll.x = poly.bbox.ll.x;
30126               if (poly.bbox.ll.y < this.bbox.ll.y) this.bbox.ll.y = poly.bbox.ll.y;
30127               if (poly.bbox.ur.x > this.bbox.ur.x) this.bbox.ur.x = poly.bbox.ur.x;
30128               if (poly.bbox.ur.y > this.bbox.ur.y) this.bbox.ur.y = poly.bbox.ur.y;
30129               this.polys.push(poly);
30130             }
30131
30132             this.isSubject = isSubject;
30133           }
30134
30135           _createClass(MultiPolyIn, [{
30136             key: "getSweepEvents",
30137             value: function getSweepEvents() {
30138               var sweepEvents = [];
30139
30140               for (var i = 0, iMax = this.polys.length; i < iMax; i++) {
30141                 var polySweepEvents = this.polys[i].getSweepEvents();
30142
30143                 for (var j = 0, jMax = polySweepEvents.length; j < jMax; j++) {
30144                   sweepEvents.push(polySweepEvents[j]);
30145                 }
30146               }
30147
30148               return sweepEvents;
30149             }
30150           }]);
30151
30152           return MultiPolyIn;
30153         }();
30154
30155         var RingOut = /*#__PURE__*/function () {
30156           _createClass(RingOut, null, [{
30157             key: "factory",
30158
30159             /* Given the segments from the sweep line pass, compute & return a series
30160              * of closed rings from all the segments marked to be part of the result */
30161             value: function factory(allSegments) {
30162               var ringsOut = [];
30163
30164               for (var i = 0, iMax = allSegments.length; i < iMax; i++) {
30165                 var segment = allSegments[i];
30166                 if (!segment.isInResult() || segment.ringOut) continue;
30167                 var prevEvent = null;
30168                 var event = segment.leftSE;
30169                 var nextEvent = segment.rightSE;
30170                 var events = [event];
30171                 var startingPoint = event.point;
30172                 var intersectionLEs = [];
30173                 /* Walk the chain of linked events to form a closed ring */
30174
30175                 while (true) {
30176                   prevEvent = event;
30177                   event = nextEvent;
30178                   events.push(event);
30179                   /* Is the ring complete? */
30180
30181                   if (event.point === startingPoint) break;
30182
30183                   while (true) {
30184                     var availableLEs = event.getAvailableLinkedEvents();
30185                     /* Did we hit a dead end? This shouldn't happen. Indicates some earlier
30186                      * part of the algorithm malfunctioned... please file a bug report. */
30187
30188                     if (availableLEs.length === 0) {
30189                       var firstPt = events[0].point;
30190                       var lastPt = events[events.length - 1].point;
30191                       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, "]."));
30192                     }
30193                     /* Only one way to go, so cotinue on the path */
30194
30195
30196                     if (availableLEs.length === 1) {
30197                       nextEvent = availableLEs[0].otherSE;
30198                       break;
30199                     }
30200                     /* We must have an intersection. Check for a completed loop */
30201
30202
30203                     var indexLE = null;
30204
30205                     for (var j = 0, jMax = intersectionLEs.length; j < jMax; j++) {
30206                       if (intersectionLEs[j].point === event.point) {
30207                         indexLE = j;
30208                         break;
30209                       }
30210                     }
30211                     /* Found a completed loop. Cut that off and make a ring */
30212
30213
30214                     if (indexLE !== null) {
30215                       var intersectionLE = intersectionLEs.splice(indexLE)[0];
30216                       var ringEvents = events.splice(intersectionLE.index);
30217                       ringEvents.unshift(ringEvents[0].otherSE);
30218                       ringsOut.push(new RingOut(ringEvents.reverse()));
30219                       continue;
30220                     }
30221                     /* register the intersection */
30222
30223
30224                     intersectionLEs.push({
30225                       index: events.length,
30226                       point: event.point
30227                     });
30228                     /* Choose the left-most option to continue the walk */
30229
30230                     var comparator = event.getLeftmostComparator(prevEvent);
30231                     nextEvent = availableLEs.sort(comparator)[0].otherSE;
30232                     break;
30233                   }
30234                 }
30235
30236                 ringsOut.push(new RingOut(events));
30237               }
30238
30239               return ringsOut;
30240             }
30241           }]);
30242
30243           function RingOut(events) {
30244             _classCallCheck(this, RingOut);
30245
30246             this.events = events;
30247
30248             for (var i = 0, iMax = events.length; i < iMax; i++) {
30249               events[i].segment.ringOut = this;
30250             }
30251
30252             this.poly = null;
30253           }
30254
30255           _createClass(RingOut, [{
30256             key: "getGeom",
30257             value: function getGeom() {
30258               // Remove superfluous points (ie extra points along a straight line),
30259               var prevPt = this.events[0].point;
30260               var points = [prevPt];
30261
30262               for (var i = 1, iMax = this.events.length - 1; i < iMax; i++) {
30263                 var _pt = this.events[i].point;
30264                 var _nextPt = this.events[i + 1].point;
30265                 if (compareVectorAngles(_pt, prevPt, _nextPt) === 0) continue;
30266                 points.push(_pt);
30267                 prevPt = _pt;
30268               } // ring was all (within rounding error of angle calc) colinear points
30269
30270
30271               if (points.length === 1) return null; // check if the starting point is necessary
30272
30273               var pt = points[0];
30274               var nextPt = points[1];
30275               if (compareVectorAngles(pt, prevPt, nextPt) === 0) points.shift();
30276               points.push(points[0]);
30277               var step = this.isExteriorRing() ? 1 : -1;
30278               var iStart = this.isExteriorRing() ? 0 : points.length - 1;
30279               var iEnd = this.isExteriorRing() ? points.length : -1;
30280               var orderedPoints = [];
30281
30282               for (var _i = iStart; _i != iEnd; _i += step) {
30283                 orderedPoints.push([points[_i].x, points[_i].y]);
30284               }
30285
30286               return orderedPoints;
30287             }
30288           }, {
30289             key: "isExteriorRing",
30290             value: function isExteriorRing() {
30291               if (this._isExteriorRing === undefined) {
30292                 var enclosing = this.enclosingRing();
30293                 this._isExteriorRing = enclosing ? !enclosing.isExteriorRing() : true;
30294               }
30295
30296               return this._isExteriorRing;
30297             }
30298           }, {
30299             key: "enclosingRing",
30300             value: function enclosingRing() {
30301               if (this._enclosingRing === undefined) {
30302                 this._enclosingRing = this._calcEnclosingRing();
30303               }
30304
30305               return this._enclosingRing;
30306             }
30307             /* Returns the ring that encloses this one, if any */
30308
30309           }, {
30310             key: "_calcEnclosingRing",
30311             value: function _calcEnclosingRing() {
30312               // start with the ealier sweep line event so that the prevSeg
30313               // chain doesn't lead us inside of a loop of ours
30314               var leftMostEvt = this.events[0];
30315
30316               for (var i = 1, iMax = this.events.length; i < iMax; i++) {
30317                 var evt = this.events[i];
30318                 if (SweepEvent.compare(leftMostEvt, evt) > 0) leftMostEvt = evt;
30319               }
30320
30321               var prevSeg = leftMostEvt.segment.prevInResult();
30322               var prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;
30323
30324               while (true) {
30325                 // no segment found, thus no ring can enclose us
30326                 if (!prevSeg) return null; // no segments below prev segment found, thus the ring of the prev
30327                 // segment must loop back around and enclose us
30328
30329                 if (!prevPrevSeg) return prevSeg.ringOut; // if the two segments are of different rings, the ring of the prev
30330                 // segment must either loop around us or the ring of the prev prev
30331                 // seg, which would make us and the ring of the prev peers
30332
30333                 if (prevPrevSeg.ringOut !== prevSeg.ringOut) {
30334                   if (prevPrevSeg.ringOut.enclosingRing() !== prevSeg.ringOut) {
30335                     return prevSeg.ringOut;
30336                   } else return prevSeg.ringOut.enclosingRing();
30337                 } // two segments are from the same ring, so this was a penisula
30338                 // of that ring. iterate downward, keep searching
30339
30340
30341                 prevSeg = prevPrevSeg.prevInResult();
30342                 prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;
30343               }
30344             }
30345           }]);
30346
30347           return RingOut;
30348         }();
30349
30350         var PolyOut = /*#__PURE__*/function () {
30351           function PolyOut(exteriorRing) {
30352             _classCallCheck(this, PolyOut);
30353
30354             this.exteriorRing = exteriorRing;
30355             exteriorRing.poly = this;
30356             this.interiorRings = [];
30357           }
30358
30359           _createClass(PolyOut, [{
30360             key: "addInterior",
30361             value: function addInterior(ring) {
30362               this.interiorRings.push(ring);
30363               ring.poly = this;
30364             }
30365           }, {
30366             key: "getGeom",
30367             value: function getGeom() {
30368               var geom = [this.exteriorRing.getGeom()]; // exterior ring was all (within rounding error of angle calc) colinear points
30369
30370               if (geom[0] === null) return null;
30371
30372               for (var i = 0, iMax = this.interiorRings.length; i < iMax; i++) {
30373                 var ringGeom = this.interiorRings[i].getGeom(); // interior ring was all (within rounding error of angle calc) colinear points
30374
30375                 if (ringGeom === null) continue;
30376                 geom.push(ringGeom);
30377               }
30378
30379               return geom;
30380             }
30381           }]);
30382
30383           return PolyOut;
30384         }();
30385
30386         var MultiPolyOut = /*#__PURE__*/function () {
30387           function MultiPolyOut(rings) {
30388             _classCallCheck(this, MultiPolyOut);
30389
30390             this.rings = rings;
30391             this.polys = this._composePolys(rings);
30392           }
30393
30394           _createClass(MultiPolyOut, [{
30395             key: "getGeom",
30396             value: function getGeom() {
30397               var geom = [];
30398
30399               for (var i = 0, iMax = this.polys.length; i < iMax; i++) {
30400                 var polyGeom = this.polys[i].getGeom(); // exterior ring was all (within rounding error of angle calc) colinear points
30401
30402                 if (polyGeom === null) continue;
30403                 geom.push(polyGeom);
30404               }
30405
30406               return geom;
30407             }
30408           }, {
30409             key: "_composePolys",
30410             value: function _composePolys(rings) {
30411               var polys = [];
30412
30413               for (var i = 0, iMax = rings.length; i < iMax; i++) {
30414                 var ring = rings[i];
30415                 if (ring.poly) continue;
30416                 if (ring.isExteriorRing()) polys.push(new PolyOut(ring));else {
30417                   var enclosingRing = ring.enclosingRing();
30418                   if (!enclosingRing.poly) polys.push(new PolyOut(enclosingRing));
30419                   enclosingRing.poly.addInterior(ring);
30420                 }
30421               }
30422
30423               return polys;
30424             }
30425           }]);
30426
30427           return MultiPolyOut;
30428         }();
30429         /**
30430          * NOTE:  We must be careful not to change any segments while
30431          *        they are in the SplayTree. AFAIK, there's no way to tell
30432          *        the tree to rebalance itself - thus before splitting
30433          *        a segment that's in the tree, we remove it from the tree,
30434          *        do the split, then re-insert it. (Even though splitting a
30435          *        segment *shouldn't* change its correct position in the
30436          *        sweep line tree, the reality is because of rounding errors,
30437          *        it sometimes does.)
30438          */
30439
30440
30441         var SweepLine = /*#__PURE__*/function () {
30442           function SweepLine(queue) {
30443             var comparator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Segment.compare;
30444
30445             _classCallCheck(this, SweepLine);
30446
30447             this.queue = queue;
30448             this.tree = new Tree(comparator);
30449             this.segments = [];
30450           }
30451
30452           _createClass(SweepLine, [{
30453             key: "process",
30454             value: function process(event) {
30455               var segment = event.segment;
30456               var newEvents = []; // if we've already been consumed by another segment,
30457               // clean up our body parts and get out
30458
30459               if (event.consumedBy) {
30460                 if (event.isLeft) this.queue.remove(event.otherSE);else this.tree.remove(segment);
30461                 return newEvents;
30462               }
30463
30464               var node = event.isLeft ? this.tree.insert(segment) : this.tree.find(segment);
30465               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.');
30466               var prevNode = node;
30467               var nextNode = node;
30468               var prevSeg = undefined;
30469               var nextSeg = undefined; // skip consumed segments still in tree
30470
30471               while (prevSeg === undefined) {
30472                 prevNode = this.tree.prev(prevNode);
30473                 if (prevNode === null) prevSeg = null;else if (prevNode.key.consumedBy === undefined) prevSeg = prevNode.key;
30474               } // skip consumed segments still in tree
30475
30476
30477               while (nextSeg === undefined) {
30478                 nextNode = this.tree.next(nextNode);
30479                 if (nextNode === null) nextSeg = null;else if (nextNode.key.consumedBy === undefined) nextSeg = nextNode.key;
30480               }
30481
30482               if (event.isLeft) {
30483                 // Check for intersections against the previous segment in the sweep line
30484                 var prevMySplitter = null;
30485
30486                 if (prevSeg) {
30487                   var prevInter = prevSeg.getIntersection(segment);
30488
30489                   if (prevInter !== null) {
30490                     if (!segment.isAnEndpoint(prevInter)) prevMySplitter = prevInter;
30491
30492                     if (!prevSeg.isAnEndpoint(prevInter)) {
30493                       var newEventsFromSplit = this._splitSafely(prevSeg, prevInter);
30494
30495                       for (var i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {
30496                         newEvents.push(newEventsFromSplit[i]);
30497                       }
30498                     }
30499                   }
30500                 } // Check for intersections against the next segment in the sweep line
30501
30502
30503                 var nextMySplitter = null;
30504
30505                 if (nextSeg) {
30506                   var nextInter = nextSeg.getIntersection(segment);
30507
30508                   if (nextInter !== null) {
30509                     if (!segment.isAnEndpoint(nextInter)) nextMySplitter = nextInter;
30510
30511                     if (!nextSeg.isAnEndpoint(nextInter)) {
30512                       var _newEventsFromSplit = this._splitSafely(nextSeg, nextInter);
30513
30514                       for (var _i = 0, _iMax = _newEventsFromSplit.length; _i < _iMax; _i++) {
30515                         newEvents.push(_newEventsFromSplit[_i]);
30516                       }
30517                     }
30518                   }
30519                 } // For simplicity, even if we find more than one intersection we only
30520                 // spilt on the 'earliest' (sweep-line style) of the intersections.
30521                 // The other intersection will be handled in a future process().
30522
30523
30524                 if (prevMySplitter !== null || nextMySplitter !== null) {
30525                   var mySplitter = null;
30526                   if (prevMySplitter === null) mySplitter = nextMySplitter;else if (nextMySplitter === null) mySplitter = prevMySplitter;else {
30527                     var cmpSplitters = SweepEvent.comparePoints(prevMySplitter, nextMySplitter);
30528                     mySplitter = cmpSplitters <= 0 ? prevMySplitter : nextMySplitter;
30529                   } // Rounding errors can cause changes in ordering,
30530                   // so remove afected segments and right sweep events before splitting
30531
30532                   this.queue.remove(segment.rightSE);
30533                   newEvents.push(segment.rightSE);
30534
30535                   var _newEventsFromSplit2 = segment.split(mySplitter);
30536
30537                   for (var _i2 = 0, _iMax2 = _newEventsFromSplit2.length; _i2 < _iMax2; _i2++) {
30538                     newEvents.push(_newEventsFromSplit2[_i2]);
30539                   }
30540                 }
30541
30542                 if (newEvents.length > 0) {
30543                   // We found some intersections, so re-do the current event to
30544                   // make sure sweep line ordering is totally consistent for later
30545                   // use with the segment 'prev' pointers
30546                   this.tree.remove(segment);
30547                   newEvents.push(event);
30548                 } else {
30549                   // done with left event
30550                   this.segments.push(segment);
30551                   segment.prev = prevSeg;
30552                 }
30553               } else {
30554                 // event.isRight
30555                 // since we're about to be removed from the sweep line, check for
30556                 // intersections between our previous and next segments
30557                 if (prevSeg && nextSeg) {
30558                   var inter = prevSeg.getIntersection(nextSeg);
30559
30560                   if (inter !== null) {
30561                     if (!prevSeg.isAnEndpoint(inter)) {
30562                       var _newEventsFromSplit3 = this._splitSafely(prevSeg, inter);
30563
30564                       for (var _i3 = 0, _iMax3 = _newEventsFromSplit3.length; _i3 < _iMax3; _i3++) {
30565                         newEvents.push(_newEventsFromSplit3[_i3]);
30566                       }
30567                     }
30568
30569                     if (!nextSeg.isAnEndpoint(inter)) {
30570                       var _newEventsFromSplit4 = this._splitSafely(nextSeg, inter);
30571
30572                       for (var _i4 = 0, _iMax4 = _newEventsFromSplit4.length; _i4 < _iMax4; _i4++) {
30573                         newEvents.push(_newEventsFromSplit4[_i4]);
30574                       }
30575                     }
30576                   }
30577                 }
30578
30579                 this.tree.remove(segment);
30580               }
30581
30582               return newEvents;
30583             }
30584             /* Safely split a segment that is currently in the datastructures
30585              * IE - a segment other than the one that is currently being processed. */
30586
30587           }, {
30588             key: "_splitSafely",
30589             value: function _splitSafely(seg, pt) {
30590               // Rounding errors can cause changes in ordering,
30591               // so remove afected segments and right sweep events before splitting
30592               // removeNode() doesn't work, so have re-find the seg
30593               // https://github.com/w8r/splay-tree/pull/5
30594               this.tree.remove(seg);
30595               var rightSE = seg.rightSE;
30596               this.queue.remove(rightSE);
30597               var newEvents = seg.split(pt);
30598               newEvents.push(rightSE); // splitting can trigger consumption
30599
30600               if (seg.consumedBy === undefined) this.tree.insert(seg);
30601               return newEvents;
30602             }
30603           }]);
30604
30605           return SweepLine;
30606         }();
30607
30608         var POLYGON_CLIPPING_MAX_QUEUE_SIZE = typeof process !== 'undefined' && process.env.POLYGON_CLIPPING_MAX_QUEUE_SIZE || 1000000;
30609         var POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS = typeof process !== 'undefined' && process.env.POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS || 1000000;
30610
30611         var Operation = /*#__PURE__*/function () {
30612           function Operation() {
30613             _classCallCheck(this, Operation);
30614           }
30615
30616           _createClass(Operation, [{
30617             key: "run",
30618             value: function run(type, geom, moreGeoms) {
30619               operation.type = type;
30620               rounder.reset();
30621               /* Convert inputs to MultiPoly objects */
30622
30623               var multipolys = [new MultiPolyIn(geom, true)];
30624
30625               for (var i = 0, iMax = moreGeoms.length; i < iMax; i++) {
30626                 multipolys.push(new MultiPolyIn(moreGeoms[i], false));
30627               }
30628
30629               operation.numMultiPolys = multipolys.length;
30630               /* BBox optimization for difference operation
30631                * If the bbox of a multipolygon that's part of the clipping doesn't
30632                * intersect the bbox of the subject at all, we can just drop that
30633                * multiploygon. */
30634
30635               if (operation.type === 'difference') {
30636                 // in place removal
30637                 var subject = multipolys[0];
30638                 var _i = 1;
30639
30640                 while (_i < multipolys.length) {
30641                   if (getBboxOverlap(multipolys[_i].bbox, subject.bbox) !== null) _i++;else multipolys.splice(_i, 1);
30642                 }
30643               }
30644               /* BBox optimization for intersection operation
30645                * If we can find any pair of multipolygons whose bbox does not overlap,
30646                * then the result will be empty. */
30647
30648
30649               if (operation.type === 'intersection') {
30650                 // TODO: this is O(n^2) in number of polygons. By sorting the bboxes,
30651                 //       it could be optimized to O(n * ln(n))
30652                 for (var _i2 = 0, _iMax = multipolys.length; _i2 < _iMax; _i2++) {
30653                   var mpA = multipolys[_i2];
30654
30655                   for (var j = _i2 + 1, jMax = multipolys.length; j < jMax; j++) {
30656                     if (getBboxOverlap(mpA.bbox, multipolys[j].bbox) === null) return [];
30657                   }
30658                 }
30659               }
30660               /* Put segment endpoints in a priority queue */
30661
30662
30663               var queue = new Tree(SweepEvent.compare);
30664
30665               for (var _i3 = 0, _iMax2 = multipolys.length; _i3 < _iMax2; _i3++) {
30666                 var sweepEvents = multipolys[_i3].getSweepEvents();
30667
30668                 for (var _j = 0, _jMax = sweepEvents.length; _j < _jMax; _j++) {
30669                   queue.insert(sweepEvents[_j]);
30670
30671                   if (queue.size > POLYGON_CLIPPING_MAX_QUEUE_SIZE) {
30672                     // prevents an infinite loop, an otherwise common manifestation of bugs
30673                     throw new Error('Infinite loop when putting segment endpoints in a priority queue ' + '(queue size too big). Please file a bug report.');
30674                   }
30675                 }
30676               }
30677               /* Pass the sweep line over those endpoints */
30678
30679
30680               var sweepLine = new SweepLine(queue);
30681               var prevQueueSize = queue.size;
30682               var node = queue.pop();
30683
30684               while (node) {
30685                 var evt = node.key;
30686
30687                 if (queue.size === prevQueueSize) {
30688                   // prevents an infinite loop, an otherwise common manifestation of bugs
30689                   var seg = evt.segment;
30690                   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.');
30691                 }
30692
30693                 if (queue.size > POLYGON_CLIPPING_MAX_QUEUE_SIZE) {
30694                   // prevents an infinite loop, an otherwise common manifestation of bugs
30695                   throw new Error('Infinite loop when passing sweep line over endpoints ' + '(queue size too big). Please file a bug report.');
30696                 }
30697
30698                 if (sweepLine.segments.length > POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS) {
30699                   // prevents an infinite loop, an otherwise common manifestation of bugs
30700                   throw new Error('Infinite loop when passing sweep line over endpoints ' + '(too many sweep line segments). Please file a bug report.');
30701                 }
30702
30703                 var newEvents = sweepLine.process(evt);
30704
30705                 for (var _i4 = 0, _iMax3 = newEvents.length; _i4 < _iMax3; _i4++) {
30706                   var _evt = newEvents[_i4];
30707                   if (_evt.consumedBy === undefined) queue.insert(_evt);
30708                 }
30709
30710                 prevQueueSize = queue.size;
30711                 node = queue.pop();
30712               } // free some memory we don't need anymore
30713
30714
30715               rounder.reset();
30716               /* Collect and compile segments we're keeping into a multipolygon */
30717
30718               var ringsOut = RingOut.factory(sweepLine.segments);
30719               var result = new MultiPolyOut(ringsOut);
30720               return result.getGeom();
30721             }
30722           }]);
30723
30724           return Operation;
30725         }(); // singleton available by import
30726
30727
30728         var operation = new Operation();
30729
30730         var union = function union(geom) {
30731           for (var _len = arguments.length, moreGeoms = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
30732             moreGeoms[_key - 1] = arguments[_key];
30733           }
30734
30735           return operation.run('union', geom, moreGeoms);
30736         };
30737
30738         var intersection$1 = function intersection(geom) {
30739           for (var _len2 = arguments.length, moreGeoms = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
30740             moreGeoms[_key2 - 1] = arguments[_key2];
30741           }
30742
30743           return operation.run('intersection', geom, moreGeoms);
30744         };
30745
30746         var xor = function xor(geom) {
30747           for (var _len3 = arguments.length, moreGeoms = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
30748             moreGeoms[_key3 - 1] = arguments[_key3];
30749           }
30750
30751           return operation.run('xor', geom, moreGeoms);
30752         };
30753
30754         var difference = function difference(subjectGeom) {
30755           for (var _len4 = arguments.length, clippingGeoms = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
30756             clippingGeoms[_key4 - 1] = arguments[_key4];
30757           }
30758
30759           return operation.run('difference', subjectGeom, clippingGeoms);
30760         };
30761
30762         var index = {
30763           union: union,
30764           intersection: intersection$1,
30765           xor: xor,
30766           difference: difference
30767         };
30768
30769         var geojsonPrecision = {exports: {}};
30770
30771         (function () {
30772           function parse(t, coordinatePrecision, extrasPrecision) {
30773             function point(p) {
30774               return p.map(function (e, index) {
30775                 if (index < 2) {
30776                   return 1 * e.toFixed(coordinatePrecision);
30777                 } else {
30778                   return 1 * e.toFixed(extrasPrecision);
30779                 }
30780               });
30781             }
30782
30783             function multi(l) {
30784               return l.map(point);
30785             }
30786
30787             function poly(p) {
30788               return p.map(multi);
30789             }
30790
30791             function multiPoly(m) {
30792               return m.map(poly);
30793             }
30794
30795             function geometry(obj) {
30796               if (!obj) {
30797                 return {};
30798               }
30799
30800               switch (obj.type) {
30801                 case "Point":
30802                   obj.coordinates = point(obj.coordinates);
30803                   return obj;
30804
30805                 case "LineString":
30806                 case "MultiPoint":
30807                   obj.coordinates = multi(obj.coordinates);
30808                   return obj;
30809
30810                 case "Polygon":
30811                 case "MultiLineString":
30812                   obj.coordinates = poly(obj.coordinates);
30813                   return obj;
30814
30815                 case "MultiPolygon":
30816                   obj.coordinates = multiPoly(obj.coordinates);
30817                   return obj;
30818
30819                 case "GeometryCollection":
30820                   obj.geometries = obj.geometries.map(geometry);
30821                   return obj;
30822
30823                 default:
30824                   return {};
30825               }
30826             }
30827
30828             function feature(obj) {
30829               obj.geometry = geometry(obj.geometry);
30830               return obj;
30831             }
30832
30833             function featureCollection(f) {
30834               f.features = f.features.map(feature);
30835               return f;
30836             }
30837
30838             function geometryCollection(g) {
30839               g.geometries = g.geometries.map(geometry);
30840               return g;
30841             }
30842
30843             if (!t) {
30844               return t;
30845             }
30846
30847             switch (t.type) {
30848               case "Feature":
30849                 return feature(t);
30850
30851               case "GeometryCollection":
30852                 return geometryCollection(t);
30853
30854               case "FeatureCollection":
30855                 return featureCollection(t);
30856
30857               case "Point":
30858               case "LineString":
30859               case "Polygon":
30860               case "MultiPoint":
30861               case "MultiPolygon":
30862               case "MultiLineString":
30863                 return geometry(t);
30864
30865               default:
30866                 return t;
30867             }
30868           }
30869
30870           geojsonPrecision.exports = parse;
30871           geojsonPrecision.exports.parse = parse;
30872         })();
30873
30874         var precision = geojsonPrecision.exports;
30875
30876         var $$k = _export;
30877         var fails$5 = fails$S;
30878         var toObject$1 = toObject$j;
30879         var toPrimitive = toPrimitive$3;
30880
30881         var FORCED$5 = fails$5(function () {
30882           return new Date(NaN).toJSON() !== null
30883             || Date.prototype.toJSON.call({ toISOString: function () { return 1; } }) !== 1;
30884         });
30885
30886         // `Date.prototype.toJSON` method
30887         // https://tc39.es/ecma262/#sec-date.prototype.tojson
30888         $$k({ target: 'Date', proto: true, forced: FORCED$5 }, {
30889           // eslint-disable-next-line no-unused-vars -- required for `.length`
30890           toJSON: function toJSON(key) {
30891             var O = toObject$1(this);
30892             var pv = toPrimitive(O, 'number');
30893             return typeof pv == 'number' && !isFinite(pv) ? null : O.toISOString();
30894           }
30895         });
30896
30897         var $$j = _export;
30898         var call$1 = functionCall;
30899
30900         // `URL.prototype.toJSON` method
30901         // https://url.spec.whatwg.org/#dom-url-tojson
30902         $$j({ target: 'URL', proto: true, enumerable: true }, {
30903           toJSON: function toJSON() {
30904             return call$1(URL.prototype.toString, this);
30905           }
30906         });
30907
30908         function isObject$3(obj) {
30909           return _typeof(obj) === 'object' && obj !== null;
30910         }
30911
30912         function forEach(obj, cb) {
30913           if (Array.isArray(obj)) {
30914             obj.forEach(cb);
30915           } else if (isObject$3(obj)) {
30916             Object.keys(obj).forEach(function (key) {
30917               var val = obj[key];
30918               cb(val, key);
30919             });
30920           }
30921         }
30922
30923         function getTreeDepth(obj) {
30924           var depth = 0;
30925
30926           if (Array.isArray(obj) || isObject$3(obj)) {
30927             forEach(obj, function (val) {
30928               if (Array.isArray(val) || isObject$3(val)) {
30929                 var tmpDepth = getTreeDepth(val);
30930
30931                 if (tmpDepth > depth) {
30932                   depth = tmpDepth;
30933                 }
30934               }
30935             });
30936             return depth + 1;
30937           }
30938
30939           return depth;
30940         }
30941
30942         function stringify(obj, options) {
30943           options = options || {};
30944           var indent = JSON.stringify([1], null, get(options, 'indent', 2)).slice(2, -3);
30945           var addMargin = get(options, 'margins', false);
30946           var addArrayMargin = get(options, 'arrayMargins', false);
30947           var addObjectMargin = get(options, 'objectMargins', false);
30948           var maxLength = indent === '' ? Infinity : get(options, 'maxLength', 80);
30949           var maxNesting = get(options, 'maxNesting', Infinity);
30950           return function _stringify(obj, currentIndent, reserved) {
30951             if (obj && typeof obj.toJSON === 'function') {
30952               obj = obj.toJSON();
30953             }
30954
30955             var string = JSON.stringify(obj);
30956
30957             if (string === undefined) {
30958               return string;
30959             }
30960
30961             var length = maxLength - currentIndent.length - reserved;
30962             var treeDepth = getTreeDepth(obj);
30963
30964             if (treeDepth <= maxNesting && string.length <= length) {
30965               var prettified = prettify(string, {
30966                 addMargin: addMargin,
30967                 addArrayMargin: addArrayMargin,
30968                 addObjectMargin: addObjectMargin
30969               });
30970
30971               if (prettified.length <= length) {
30972                 return prettified;
30973               }
30974             }
30975
30976             if (isObject$3(obj)) {
30977               var nextIndent = currentIndent + indent;
30978               var items = [];
30979               var delimiters;
30980
30981               var comma = function comma(array, index) {
30982                 return index === array.length - 1 ? 0 : 1;
30983               };
30984
30985               if (Array.isArray(obj)) {
30986                 for (var index = 0; index < obj.length; index++) {
30987                   items.push(_stringify(obj[index], nextIndent, comma(obj, index)) || 'null');
30988                 }
30989
30990                 delimiters = '[]';
30991               } else {
30992                 Object.keys(obj).forEach(function (key, index, array) {
30993                   var keyPart = JSON.stringify(key) + ': ';
30994
30995                   var value = _stringify(obj[key], nextIndent, keyPart.length + comma(array, index));
30996
30997                   if (value !== undefined) {
30998                     items.push(keyPart + value);
30999                   }
31000                 });
31001                 delimiters = '{}';
31002               }
31003
31004               if (items.length > 0) {
31005                 return [delimiters[0], indent + items.join(',\n' + nextIndent), delimiters[1]].join('\n' + currentIndent);
31006               }
31007             }
31008
31009             return string;
31010           }(obj, '', 0);
31011         } // Note: This regex matches even invalid JSON strings, but since we’re
31012         // working on the output of `JSON.stringify` we know that only valid strings
31013         // are present (unless the user supplied a weird `options.indent` but in
31014         // that case we don’t care since the output would be invalid anyway).
31015
31016
31017         var stringOrChar = /("(?:[^\\"]|\\.)*")|[:,\][}{]/g;
31018
31019         function prettify(string, options) {
31020           options = options || {};
31021           var tokens = {
31022             '{': '{',
31023             '}': '}',
31024             '[': '[',
31025             ']': ']',
31026             ',': ', ',
31027             ':': ': '
31028           };
31029
31030           if (options.addMargin || options.addObjectMargin) {
31031             tokens['{'] = '{ ';
31032             tokens['}'] = ' }';
31033           }
31034
31035           if (options.addMargin || options.addArrayMargin) {
31036             tokens['['] = '[ ';
31037             tokens[']'] = ' ]';
31038           }
31039
31040           return string.replace(stringOrChar, function (match, string) {
31041             return string ? match : tokens[match];
31042           });
31043         }
31044
31045         function get(options, name, defaultValue) {
31046           return name in options ? options[name] : defaultValue;
31047         }
31048
31049         var jsonStringifyPrettyCompact = stringify;
31050
31051         var _default = /*#__PURE__*/function () {
31052           // constructor
31053           //
31054           // `fc`  Optional FeatureCollection of known features
31055           //
31056           // Optionally pass a GeoJSON FeatureCollection of known features which we can refer to later.
31057           // Each feature must have a filename-like `id`, for example: `something.geojson`
31058           //
31059           // {
31060           //   "type": "FeatureCollection"
31061           //   "features": [
31062           //     {
31063           //       "type": "Feature",
31064           //       "id": "philly_metro.geojson",
31065           //       "properties": { … },
31066           //       "geometry": { … }
31067           //     }
31068           //   ]
31069           // }
31070           function _default(fc) {
31071             var _this = this;
31072
31073             _classCallCheck$1(this, _default);
31074
31075             // The _cache retains resolved features, so if you ask for the same thing multiple times
31076             // we don't repeat the expensive resolving/clipping operations.
31077             //
31078             // Each feature has a stable identifier that is used as the cache key.
31079             // The identifiers look like:
31080             // - for point locations, the stringified point:          e.g. '[8.67039,49.41882]'
31081             // - for geojson locations, the geojson id:               e.g. 'de-hamburg.geojson'
31082             // - for countrycoder locations, feature.id property:     e.g. 'Q2'  (countrycoder uses Wikidata identifiers)
31083             // - for aggregated locationSets, +[include]-[exclude]:   e.g '+[Q2]-[Q18,Q27611]'
31084             this._cache = {}; // When strict mode = true, throw on invalid locations or locationSets.
31085             // When strict mode = false, return `null` for invalid locations or locationSets.
31086
31087             this._strict = true; // process input FeatureCollection
31088
31089             if (fc && fc.type === 'FeatureCollection' && Array.isArray(fc.features)) {
31090               fc.features.forEach(function (feature) {
31091                 feature.properties = feature.properties || {};
31092                 var props = feature.properties; // Get `id` from either `id` or `properties`
31093
31094                 var id = feature.id || props.id;
31095                 if (!id || !/^\S+\.geojson$/i.test(id)) return; // Ensure `id` exists and is lowercase
31096
31097                 id = id.toLowerCase();
31098                 feature.id = id;
31099                 props.id = id; // Ensure `area` property exists
31100
31101                 if (!props.area) {
31102                   var area = geojsonArea.geometry(feature.geometry) / 1e6; // m² to km²
31103
31104                   props.area = Number(area.toFixed(2));
31105                 }
31106
31107                 _this._cache[id] = feature;
31108               });
31109             } // Replace CountryCoder world geometry to be a polygon covering the world.
31110
31111
31112             var world = _cloneDeep(feature$1('Q2'));
31113
31114             world.geometry = {
31115               type: 'Polygon',
31116               coordinates: [[[-180, -90], [180, -90], [180, 90], [-180, 90], [-180, -90]]]
31117             };
31118             world.id = 'Q2';
31119             world.properties.id = 'Q2';
31120             world.properties.area = geojsonArea.geometry(world.geometry) / 1e6; // m² to km²
31121
31122             this._cache.Q2 = world;
31123           } // validateLocation
31124           // `location`  The location to validate
31125           //
31126           // Pass a `location` value to validate
31127           //
31128           // Returns a result like:
31129           //   {
31130           //     type:     'point', 'geojson', or 'countrycoder'
31131           //     location:  the queried location
31132           //     id:        the stable identifier for the feature
31133           //   }
31134           // or `null` if the location is invalid
31135           //
31136
31137
31138           _createClass$1(_default, [{
31139             key: "validateLocation",
31140             value: function validateLocation(location) {
31141               if (Array.isArray(location) && (location.length === 2 || location.length === 3)) {
31142                 // [lon, lat] or [lon, lat, radius] point?
31143                 var lon = location[0];
31144                 var lat = location[1];
31145                 var radius = location[2];
31146
31147                 if (Number.isFinite(lon) && lon >= -180 && lon <= 180 && Number.isFinite(lat) && lat >= -90 && lat <= 90 && (location.length === 2 || Number.isFinite(radius) && radius > 0)) {
31148                   var id = '[' + location.toString() + ']';
31149                   return {
31150                     type: 'point',
31151                     location: location,
31152                     id: id
31153                   };
31154                 }
31155               } else if (typeof location === 'string' && /^\S+\.geojson$/i.test(location)) {
31156                 // a .geojson filename?
31157                 var _id = location.toLowerCase();
31158
31159                 if (this._cache[_id]) {
31160                   return {
31161                     type: 'geojson',
31162                     location: location,
31163                     id: _id
31164                   };
31165                 }
31166               } else if (typeof location === 'string' || typeof location === 'number') {
31167                 // a country-coder value?
31168                 var feature = feature$1(location);
31169
31170                 if (feature) {
31171                   // Use wikidata QID as the identifier, since that seems to be the one
31172                   // property that everything in CountryCoder is guaranteed to have.
31173                   var _id2 = feature.properties.wikidata;
31174                   return {
31175                     type: 'countrycoder',
31176                     location: location,
31177                     id: _id2
31178                   };
31179                 }
31180               }
31181
31182               if (this._strict) {
31183                 throw new Error("validateLocation:  Invalid location: \"".concat(location, "\"."));
31184               } else {
31185                 return null;
31186               }
31187             } // resolveLocation
31188             // `location`  The location to resolve
31189             //
31190             // Pass a `location` value to resolve
31191             //
31192             // Returns a result like:
31193             //   {
31194             //     type:      'point', 'geojson', or 'countrycoder'
31195             //     location:  the queried location
31196             //     id:        a stable identifier for the feature
31197             //     feature:   the resolved GeoJSON feature
31198             //   }
31199             //  or `null` if the location is invalid
31200             //
31201
31202           }, {
31203             key: "resolveLocation",
31204             value: function resolveLocation(location) {
31205               var valid = this.validateLocation(location);
31206               if (!valid) return null;
31207               var id = valid.id; // Return a result from cache if we can
31208
31209               if (this._cache[id]) {
31210                 return Object.assign(valid, {
31211                   feature: this._cache[id]
31212                 });
31213               } // A [lon,lat] coordinate pair?
31214
31215
31216               if (valid.type === 'point') {
31217                 var lon = location[0];
31218                 var lat = location[1];
31219                 var radius = location[2] || 25; // km
31220
31221                 var EDGES = 10;
31222                 var PRECISION = 3;
31223                 var area = Math.PI * radius * radius;
31224                 var feature = this._cache[id] = precision({
31225                   type: 'Feature',
31226                   id: id,
31227                   properties: {
31228                     id: id,
31229                     area: Number(area.toFixed(2))
31230                   },
31231                   geometry: circleToPolygon([lon, lat], radius * 1000, EDGES) // km to m
31232
31233                 }, PRECISION);
31234                 return Object.assign(valid, {
31235                   feature: feature
31236                 }); // A .geojson filename?
31237               } else if (valid.type === 'geojson') ; else if (valid.type === 'countrycoder') {
31238                 var _feature = _cloneDeep(feature$1(id));
31239
31240                 var props = _feature.properties; // -> This block of code is weird and requires some explanation. <-
31241                 // CountryCoder includes higher level features which are made up of members.
31242                 // These features don't have their own geometry, but CountryCoder provides an
31243                 //   `aggregateFeature` method to combine these members into a MultiPolygon.
31244                 // In the past, Turf/JSTS/martinez could not handle the aggregated features,
31245                 //   so we'd iteratively union them all together.  (this was slow)
31246                 // But now mfogel/polygon-clipping handles these MultiPolygons like a boss.
31247                 // This approach also has the benefit of removing all the internal boaders and
31248                 //   simplifying the regional polygons a lot.
31249
31250                 if (Array.isArray(props.members)) {
31251                   var aggregate = aggregateFeature(id);
31252                   aggregate.geometry.coordinates = _clip([aggregate], 'UNION').geometry.coordinates;
31253                   _feature.geometry = aggregate.geometry;
31254                 } // Ensure `area` property exists
31255
31256
31257                 if (!props.area) {
31258                   var _area = geojsonArea.geometry(_feature.geometry) / 1e6; // m² to km²
31259
31260
31261                   props.area = Number(_area.toFixed(2));
31262                 } // Ensure `id` property exists
31263
31264
31265                 _feature.id = id;
31266                 props.id = id;
31267                 this._cache[id] = _feature;
31268                 return Object.assign(valid, {
31269                   feature: _feature
31270                 });
31271               }
31272
31273               if (this._strict) {
31274                 throw new Error("resolveLocation:  Couldn't resolve location \"".concat(location, "\"."));
31275               } else {
31276                 return null;
31277               }
31278             } // validateLocationSet
31279             // `locationSet`  the locationSet to validate
31280             //
31281             // Pass a locationSet Object to validate like:
31282             //   {
31283             //     include: [ Array of locations ],
31284             //     exclude: [ Array of locations ]
31285             //   }
31286             //
31287             // Returns a result like:
31288             //   {
31289             //     type:         'locationset'
31290             //     locationSet:  the queried locationSet
31291             //     id:           the stable identifier for the feature
31292             //   }
31293             // or `null` if the locationSet is invalid
31294             //
31295
31296           }, {
31297             key: "validateLocationSet",
31298             value: function validateLocationSet(locationSet) {
31299               locationSet = locationSet || {};
31300               var validator = this.validateLocation.bind(this);
31301               var include = (locationSet.include || []).map(validator).filter(Boolean);
31302               var exclude = (locationSet.exclude || []).map(validator).filter(Boolean);
31303
31304               if (!include.length) {
31305                 if (this._strict) {
31306                   throw new Error("validateLocationSet:  LocationSet includes nothing.");
31307                 } else {
31308                   // non-strict mode, replace an empty locationSet with one that includes "the world"
31309                   locationSet.include = ['Q2'];
31310                   include = [{
31311                     type: 'countrycoder',
31312                     location: 'Q2',
31313                     id: 'Q2'
31314                   }];
31315                 }
31316               } // Generate stable identifier
31317
31318
31319               include.sort(_sortLocations);
31320               var id = '+[' + include.map(function (d) {
31321                 return d.id;
31322               }).join(',') + ']';
31323
31324               if (exclude.length) {
31325                 exclude.sort(_sortLocations);
31326                 id += '-[' + exclude.map(function (d) {
31327                   return d.id;
31328                 }).join(',') + ']';
31329               }
31330
31331               return {
31332                 type: 'locationset',
31333                 locationSet: locationSet,
31334                 id: id
31335               };
31336             } // resolveLocationSet
31337             // `locationSet`  the locationSet to resolve
31338             //
31339             // Pass a locationSet Object to validate like:
31340             //   {
31341             //     include: [ Array of locations ],
31342             //     exclude: [ Array of locations ]
31343             //   }
31344             //
31345             // Returns a result like:
31346             //   {
31347             //     type:         'locationset'
31348             //     locationSet:  the queried locationSet
31349             //     id:           the stable identifier for the feature
31350             //     feature:      the resolved GeoJSON feature
31351             //   }
31352             // or `null` if the locationSet is invalid
31353             //
31354
31355           }, {
31356             key: "resolveLocationSet",
31357             value: function resolveLocationSet(locationSet) {
31358               locationSet = locationSet || {};
31359               var valid = this.validateLocationSet(locationSet);
31360               if (!valid) return null;
31361               var id = valid.id; // Return a result from cache if we can
31362
31363               if (this._cache[id]) {
31364                 return Object.assign(valid, {
31365                   feature: this._cache[id]
31366                 });
31367               }
31368
31369               var resolver = this.resolveLocation.bind(this);
31370               var includes = (locationSet.include || []).map(resolver).filter(Boolean);
31371               var excludes = (locationSet.exclude || []).map(resolver).filter(Boolean); // Return quickly if it's a single included location..
31372
31373               if (includes.length === 1 && excludes.length === 0) {
31374                 return Object.assign(valid, {
31375                   feature: includes[0].feature
31376                 });
31377               } // Calculate unions
31378
31379
31380               var includeGeoJSON = _clip(includes.map(function (d) {
31381                 return d.feature;
31382               }), 'UNION');
31383
31384               var excludeGeoJSON = _clip(excludes.map(function (d) {
31385                 return d.feature;
31386               }), 'UNION'); // Calculate difference, update `area` and return result
31387
31388
31389               var resultGeoJSON = excludeGeoJSON ? _clip([includeGeoJSON, excludeGeoJSON], 'DIFFERENCE') : includeGeoJSON;
31390               var area = geojsonArea.geometry(resultGeoJSON.geometry) / 1e6; // m² to km²
31391
31392               resultGeoJSON.id = id;
31393               resultGeoJSON.properties = {
31394                 id: id,
31395                 area: Number(area.toFixed(2))
31396               };
31397               this._cache[id] = resultGeoJSON;
31398               return Object.assign(valid, {
31399                 feature: resultGeoJSON
31400               });
31401             } // strict
31402             //
31403
31404           }, {
31405             key: "strict",
31406             value: function strict(val) {
31407               if (val === undefined) {
31408                 // get
31409                 return this._strict;
31410               } else {
31411                 // set
31412                 this._strict = val;
31413                 return this;
31414               }
31415             } // cache
31416             // convenience method to access the internal cache
31417
31418           }, {
31419             key: "cache",
31420             value: function cache() {
31421               return this._cache;
31422             } // stringify
31423             // convenience method to prettyStringify the given object
31424
31425           }, {
31426             key: "stringify",
31427             value: function stringify(obj, options) {
31428               return jsonStringifyPrettyCompact(obj, options);
31429             }
31430           }]);
31431
31432           return _default;
31433         }(); // Wrap the mfogel/polygon-clipping library and return a GeoJSON feature.
31434
31435         function _clip(features, which) {
31436           if (!Array.isArray(features) || !features.length) return null;
31437           var fn = {
31438             UNION: index.union,
31439             DIFFERENCE: index.difference
31440           }[which];
31441           var args = features.map(function (feature) {
31442             return feature.geometry.coordinates;
31443           });
31444           var coords = fn.apply(null, args);
31445           return {
31446             type: 'Feature',
31447             properties: {},
31448             geometry: {
31449               type: whichType(coords),
31450               coordinates: coords
31451             }
31452           }; // is this a Polygon or a MultiPolygon?
31453
31454           function whichType(coords) {
31455             var a = Array.isArray(coords);
31456             var b = a && Array.isArray(coords[0]);
31457             var c = b && Array.isArray(coords[0][0]);
31458             var d = c && Array.isArray(coords[0][0][0]);
31459             return d ? 'MultiPolygon' : 'Polygon';
31460           }
31461         }
31462
31463         function _cloneDeep(obj) {
31464           return JSON.parse(JSON.stringify(obj));
31465         } // Sorting the location lists is ok because they end up unioned together.
31466         // This sorting makes it possible to generate a deterministic id.
31467
31468
31469         function _sortLocations(a, b) {
31470           var rank = {
31471             countrycoder: 1,
31472             geojson: 2,
31473             point: 3
31474           };
31475           var aRank = rank[a.type];
31476           var bRank = rank[b.type];
31477           return aRank > bRank ? 1 : aRank < bRank ? -1 : a.id.localeCompare(b.id);
31478         }
31479
31480         var $$i = _export;
31481
31482         // `Number.MAX_SAFE_INTEGER` constant
31483         // https://tc39.es/ecma262/#sec-number.max_safe_integer
31484         $$i({ target: 'Number', stat: true }, {
31485           MAX_SAFE_INTEGER: 0x1FFFFFFFFFFFFF
31486         });
31487
31488         var aesJs = {exports: {}};
31489
31490         (function (module, exports) {
31491           (function (root) {
31492
31493             function checkInt(value) {
31494               return parseInt(value) === value;
31495             }
31496
31497             function checkInts(arrayish) {
31498               if (!checkInt(arrayish.length)) {
31499                 return false;
31500               }
31501
31502               for (var i = 0; i < arrayish.length; i++) {
31503                 if (!checkInt(arrayish[i]) || arrayish[i] < 0 || arrayish[i] > 255) {
31504                   return false;
31505                 }
31506               }
31507
31508               return true;
31509             }
31510
31511             function coerceArray(arg, copy) {
31512               // ArrayBuffer view
31513               if (arg.buffer && arg.name === 'Uint8Array') {
31514                 if (copy) {
31515                   if (arg.slice) {
31516                     arg = arg.slice();
31517                   } else {
31518                     arg = Array.prototype.slice.call(arg);
31519                   }
31520                 }
31521
31522                 return arg;
31523               } // It's an array; check it is a valid representation of a byte
31524
31525
31526               if (Array.isArray(arg)) {
31527                 if (!checkInts(arg)) {
31528                   throw new Error('Array contains invalid value: ' + arg);
31529                 }
31530
31531                 return new Uint8Array(arg);
31532               } // Something else, but behaves like an array (maybe a Buffer? Arguments?)
31533
31534
31535               if (checkInt(arg.length) && checkInts(arg)) {
31536                 return new Uint8Array(arg);
31537               }
31538
31539               throw new Error('unsupported array-like object');
31540             }
31541
31542             function createArray(length) {
31543               return new Uint8Array(length);
31544             }
31545
31546             function copyArray(sourceArray, targetArray, targetStart, sourceStart, sourceEnd) {
31547               if (sourceStart != null || sourceEnd != null) {
31548                 if (sourceArray.slice) {
31549                   sourceArray = sourceArray.slice(sourceStart, sourceEnd);
31550                 } else {
31551                   sourceArray = Array.prototype.slice.call(sourceArray, sourceStart, sourceEnd);
31552                 }
31553               }
31554
31555               targetArray.set(sourceArray, targetStart);
31556             }
31557
31558             var convertUtf8 = function () {
31559               function toBytes(text) {
31560                 var result = [],
31561                     i = 0;
31562                 text = encodeURI(text);
31563
31564                 while (i < text.length) {
31565                   var c = text.charCodeAt(i++); // if it is a % sign, encode the following 2 bytes as a hex value
31566
31567                   if (c === 37) {
31568                     result.push(parseInt(text.substr(i, 2), 16));
31569                     i += 2; // otherwise, just the actual byte
31570                   } else {
31571                     result.push(c);
31572                   }
31573                 }
31574
31575                 return coerceArray(result);
31576               }
31577
31578               function fromBytes(bytes) {
31579                 var result = [],
31580                     i = 0;
31581
31582                 while (i < bytes.length) {
31583                   var c = bytes[i];
31584
31585                   if (c < 128) {
31586                     result.push(String.fromCharCode(c));
31587                     i++;
31588                   } else if (c > 191 && c < 224) {
31589                     result.push(String.fromCharCode((c & 0x1f) << 6 | bytes[i + 1] & 0x3f));
31590                     i += 2;
31591                   } else {
31592                     result.push(String.fromCharCode((c & 0x0f) << 12 | (bytes[i + 1] & 0x3f) << 6 | bytes[i + 2] & 0x3f));
31593                     i += 3;
31594                   }
31595                 }
31596
31597                 return result.join('');
31598               }
31599
31600               return {
31601                 toBytes: toBytes,
31602                 fromBytes: fromBytes
31603               };
31604             }();
31605
31606             var convertHex = function () {
31607               function toBytes(text) {
31608                 var result = [];
31609
31610                 for (var i = 0; i < text.length; i += 2) {
31611                   result.push(parseInt(text.substr(i, 2), 16));
31612                 }
31613
31614                 return result;
31615               } // http://ixti.net/development/javascript/2011/11/11/base64-encodedecode-of-utf8-in-browser-with-js.html
31616
31617
31618               var Hex = '0123456789abcdef';
31619
31620               function fromBytes(bytes) {
31621                 var result = [];
31622
31623                 for (var i = 0; i < bytes.length; i++) {
31624                   var v = bytes[i];
31625                   result.push(Hex[(v & 0xf0) >> 4] + Hex[v & 0x0f]);
31626                 }
31627
31628                 return result.join('');
31629               }
31630
31631               return {
31632                 toBytes: toBytes,
31633                 fromBytes: fromBytes
31634               };
31635             }(); // Number of rounds by keysize
31636
31637
31638             var numberOfRounds = {
31639               16: 10,
31640               24: 12,
31641               32: 14
31642             }; // Round constant words
31643
31644             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)
31645
31646             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];
31647             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
31648
31649             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];
31650             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];
31651             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];
31652             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
31653
31654             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];
31655             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];
31656             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];
31657             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
31658
31659             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];
31660             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];
31661             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];
31662             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];
31663
31664             function convertToInt32(bytes) {
31665               var result = [];
31666
31667               for (var i = 0; i < bytes.length; i += 4) {
31668                 result.push(bytes[i] << 24 | bytes[i + 1] << 16 | bytes[i + 2] << 8 | bytes[i + 3]);
31669               }
31670
31671               return result;
31672             }
31673
31674             var AES = function AES(key) {
31675               if (!(this instanceof AES)) {
31676                 throw Error('AES must be instanitated with `new`');
31677               }
31678
31679               Object.defineProperty(this, 'key', {
31680                 value: coerceArray(key, true)
31681               });
31682
31683               this._prepare();
31684             };
31685
31686             AES.prototype._prepare = function () {
31687               var rounds = numberOfRounds[this.key.length];
31688
31689               if (rounds == null) {
31690                 throw new Error('invalid key size (must be 16, 24 or 32 bytes)');
31691               } // encryption round keys
31692
31693
31694               this._Ke = []; // decryption round keys
31695
31696               this._Kd = [];
31697
31698               for (var i = 0; i <= rounds; i++) {
31699                 this._Ke.push([0, 0, 0, 0]);
31700
31701                 this._Kd.push([0, 0, 0, 0]);
31702               }
31703
31704               var roundKeyCount = (rounds + 1) * 4;
31705               var KC = this.key.length / 4; // convert the key into ints
31706
31707               var tk = convertToInt32(this.key); // copy values into round key arrays
31708
31709               var index;
31710
31711               for (var i = 0; i < KC; i++) {
31712                 index = i >> 2;
31713                 this._Ke[index][i % 4] = tk[i];
31714                 this._Kd[rounds - index][i % 4] = tk[i];
31715               } // key expansion (fips-197 section 5.2)
31716
31717
31718               var rconpointer = 0;
31719               var t = KC,
31720                   tt;
31721
31722               while (t < roundKeyCount) {
31723                 tt = tk[KC - 1];
31724                 tk[0] ^= S[tt >> 16 & 0xFF] << 24 ^ S[tt >> 8 & 0xFF] << 16 ^ S[tt & 0xFF] << 8 ^ S[tt >> 24 & 0xFF] ^ rcon[rconpointer] << 24;
31725                 rconpointer += 1; // key expansion (for non-256 bit)
31726
31727                 if (KC != 8) {
31728                   for (var i = 1; i < KC; i++) {
31729                     tk[i] ^= tk[i - 1];
31730                   } // key expansion for 256-bit keys is "slightly different" (fips-197)
31731
31732                 } else {
31733                   for (var i = 1; i < KC / 2; i++) {
31734                     tk[i] ^= tk[i - 1];
31735                   }
31736
31737                   tt = tk[KC / 2 - 1];
31738                   tk[KC / 2] ^= S[tt & 0xFF] ^ S[tt >> 8 & 0xFF] << 8 ^ S[tt >> 16 & 0xFF] << 16 ^ S[tt >> 24 & 0xFF] << 24;
31739
31740                   for (var i = KC / 2 + 1; i < KC; i++) {
31741                     tk[i] ^= tk[i - 1];
31742                   }
31743                 } // copy values into round key arrays
31744
31745
31746                 var i = 0,
31747                     r,
31748                     c;
31749
31750                 while (i < KC && t < roundKeyCount) {
31751                   r = t >> 2;
31752                   c = t % 4;
31753                   this._Ke[r][c] = tk[i];
31754                   this._Kd[rounds - r][c] = tk[i++];
31755                   t++;
31756                 }
31757               } // inverse-cipher-ify the decryption round key (fips-197 section 5.3)
31758
31759
31760               for (var r = 1; r < rounds; r++) {
31761                 for (var c = 0; c < 4; c++) {
31762                   tt = this._Kd[r][c];
31763                   this._Kd[r][c] = U1[tt >> 24 & 0xFF] ^ U2[tt >> 16 & 0xFF] ^ U3[tt >> 8 & 0xFF] ^ U4[tt & 0xFF];
31764                 }
31765               }
31766             };
31767
31768             AES.prototype.encrypt = function (plaintext) {
31769               if (plaintext.length != 16) {
31770                 throw new Error('invalid plaintext size (must be 16 bytes)');
31771               }
31772
31773               var rounds = this._Ke.length - 1;
31774               var a = [0, 0, 0, 0]; // convert plaintext to (ints ^ key)
31775
31776               var t = convertToInt32(plaintext);
31777
31778               for (var i = 0; i < 4; i++) {
31779                 t[i] ^= this._Ke[0][i];
31780               } // apply round transforms
31781
31782
31783               for (var r = 1; r < rounds; r++) {
31784                 for (var i = 0; i < 4; i++) {
31785                   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];
31786                 }
31787
31788                 t = a.slice();
31789               } // the last round is special
31790
31791
31792               var result = createArray(16),
31793                   tt;
31794
31795               for (var i = 0; i < 4; i++) {
31796                 tt = this._Ke[rounds][i];
31797                 result[4 * i] = (S[t[i] >> 24 & 0xff] ^ tt >> 24) & 0xff;
31798                 result[4 * i + 1] = (S[t[(i + 1) % 4] >> 16 & 0xff] ^ tt >> 16) & 0xff;
31799                 result[4 * i + 2] = (S[t[(i + 2) % 4] >> 8 & 0xff] ^ tt >> 8) & 0xff;
31800                 result[4 * i + 3] = (S[t[(i + 3) % 4] & 0xff] ^ tt) & 0xff;
31801               }
31802
31803               return result;
31804             };
31805
31806             AES.prototype.decrypt = function (ciphertext) {
31807               if (ciphertext.length != 16) {
31808                 throw new Error('invalid ciphertext size (must be 16 bytes)');
31809               }
31810
31811               var rounds = this._Kd.length - 1;
31812               var a = [0, 0, 0, 0]; // convert plaintext to (ints ^ key)
31813
31814               var t = convertToInt32(ciphertext);
31815
31816               for (var i = 0; i < 4; i++) {
31817                 t[i] ^= this._Kd[0][i];
31818               } // apply round transforms
31819
31820
31821               for (var r = 1; r < rounds; r++) {
31822                 for (var i = 0; i < 4; i++) {
31823                   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];
31824                 }
31825
31826                 t = a.slice();
31827               } // the last round is special
31828
31829
31830               var result = createArray(16),
31831                   tt;
31832
31833               for (var i = 0; i < 4; i++) {
31834                 tt = this._Kd[rounds][i];
31835                 result[4 * i] = (Si[t[i] >> 24 & 0xff] ^ tt >> 24) & 0xff;
31836                 result[4 * i + 1] = (Si[t[(i + 3) % 4] >> 16 & 0xff] ^ tt >> 16) & 0xff;
31837                 result[4 * i + 2] = (Si[t[(i + 2) % 4] >> 8 & 0xff] ^ tt >> 8) & 0xff;
31838                 result[4 * i + 3] = (Si[t[(i + 1) % 4] & 0xff] ^ tt) & 0xff;
31839               }
31840
31841               return result;
31842             };
31843             /**
31844              *  Mode Of Operation - Electonic Codebook (ECB)
31845              */
31846
31847
31848             var ModeOfOperationECB = function ModeOfOperationECB(key) {
31849               if (!(this instanceof ModeOfOperationECB)) {
31850                 throw Error('AES must be instanitated with `new`');
31851               }
31852
31853               this.description = "Electronic Code Block";
31854               this.name = "ecb";
31855               this._aes = new AES(key);
31856             };
31857
31858             ModeOfOperationECB.prototype.encrypt = function (plaintext) {
31859               plaintext = coerceArray(plaintext);
31860
31861               if (plaintext.length % 16 !== 0) {
31862                 throw new Error('invalid plaintext size (must be multiple of 16 bytes)');
31863               }
31864
31865               var ciphertext = createArray(plaintext.length);
31866               var block = createArray(16);
31867
31868               for (var i = 0; i < plaintext.length; i += 16) {
31869                 copyArray(plaintext, block, 0, i, i + 16);
31870                 block = this._aes.encrypt(block);
31871                 copyArray(block, ciphertext, i);
31872               }
31873
31874               return ciphertext;
31875             };
31876
31877             ModeOfOperationECB.prototype.decrypt = function (ciphertext) {
31878               ciphertext = coerceArray(ciphertext);
31879
31880               if (ciphertext.length % 16 !== 0) {
31881                 throw new Error('invalid ciphertext size (must be multiple of 16 bytes)');
31882               }
31883
31884               var plaintext = createArray(ciphertext.length);
31885               var block = createArray(16);
31886
31887               for (var i = 0; i < ciphertext.length; i += 16) {
31888                 copyArray(ciphertext, block, 0, i, i + 16);
31889                 block = this._aes.decrypt(block);
31890                 copyArray(block, plaintext, i);
31891               }
31892
31893               return plaintext;
31894             };
31895             /**
31896              *  Mode Of Operation - Cipher Block Chaining (CBC)
31897              */
31898
31899
31900             var ModeOfOperationCBC = function ModeOfOperationCBC(key, iv) {
31901               if (!(this instanceof ModeOfOperationCBC)) {
31902                 throw Error('AES must be instanitated with `new`');
31903               }
31904
31905               this.description = "Cipher Block Chaining";
31906               this.name = "cbc";
31907
31908               if (!iv) {
31909                 iv = createArray(16);
31910               } else if (iv.length != 16) {
31911                 throw new Error('invalid initialation vector size (must be 16 bytes)');
31912               }
31913
31914               this._lastCipherblock = coerceArray(iv, true);
31915               this._aes = new AES(key);
31916             };
31917
31918             ModeOfOperationCBC.prototype.encrypt = function (plaintext) {
31919               plaintext = coerceArray(plaintext);
31920
31921               if (plaintext.length % 16 !== 0) {
31922                 throw new Error('invalid plaintext size (must be multiple of 16 bytes)');
31923               }
31924
31925               var ciphertext = createArray(plaintext.length);
31926               var block = createArray(16);
31927
31928               for (var i = 0; i < plaintext.length; i += 16) {
31929                 copyArray(plaintext, block, 0, i, i + 16);
31930
31931                 for (var j = 0; j < 16; j++) {
31932                   block[j] ^= this._lastCipherblock[j];
31933                 }
31934
31935                 this._lastCipherblock = this._aes.encrypt(block);
31936                 copyArray(this._lastCipherblock, ciphertext, i);
31937               }
31938
31939               return ciphertext;
31940             };
31941
31942             ModeOfOperationCBC.prototype.decrypt = function (ciphertext) {
31943               ciphertext = coerceArray(ciphertext);
31944
31945               if (ciphertext.length % 16 !== 0) {
31946                 throw new Error('invalid ciphertext size (must be multiple of 16 bytes)');
31947               }
31948
31949               var plaintext = createArray(ciphertext.length);
31950               var block = createArray(16);
31951
31952               for (var i = 0; i < ciphertext.length; i += 16) {
31953                 copyArray(ciphertext, block, 0, i, i + 16);
31954                 block = this._aes.decrypt(block);
31955
31956                 for (var j = 0; j < 16; j++) {
31957                   plaintext[i + j] = block[j] ^ this._lastCipherblock[j];
31958                 }
31959
31960                 copyArray(ciphertext, this._lastCipherblock, 0, i, i + 16);
31961               }
31962
31963               return plaintext;
31964             };
31965             /**
31966              *  Mode Of Operation - Cipher Feedback (CFB)
31967              */
31968
31969
31970             var ModeOfOperationCFB = function ModeOfOperationCFB(key, iv, segmentSize) {
31971               if (!(this instanceof ModeOfOperationCFB)) {
31972                 throw Error('AES must be instanitated with `new`');
31973               }
31974
31975               this.description = "Cipher Feedback";
31976               this.name = "cfb";
31977
31978               if (!iv) {
31979                 iv = createArray(16);
31980               } else if (iv.length != 16) {
31981                 throw new Error('invalid initialation vector size (must be 16 size)');
31982               }
31983
31984               if (!segmentSize) {
31985                 segmentSize = 1;
31986               }
31987
31988               this.segmentSize = segmentSize;
31989               this._shiftRegister = coerceArray(iv, true);
31990               this._aes = new AES(key);
31991             };
31992
31993             ModeOfOperationCFB.prototype.encrypt = function (plaintext) {
31994               if (plaintext.length % this.segmentSize != 0) {
31995                 throw new Error('invalid plaintext size (must be segmentSize bytes)');
31996               }
31997
31998               var encrypted = coerceArray(plaintext, true);
31999               var xorSegment;
32000
32001               for (var i = 0; i < encrypted.length; i += this.segmentSize) {
32002                 xorSegment = this._aes.encrypt(this._shiftRegister);
32003
32004                 for (var j = 0; j < this.segmentSize; j++) {
32005                   encrypted[i + j] ^= xorSegment[j];
32006                 } // Shift the register
32007
32008
32009                 copyArray(this._shiftRegister, this._shiftRegister, 0, this.segmentSize);
32010                 copyArray(encrypted, this._shiftRegister, 16 - this.segmentSize, i, i + this.segmentSize);
32011               }
32012
32013               return encrypted;
32014             };
32015
32016             ModeOfOperationCFB.prototype.decrypt = function (ciphertext) {
32017               if (ciphertext.length % this.segmentSize != 0) {
32018                 throw new Error('invalid ciphertext size (must be segmentSize bytes)');
32019               }
32020
32021               var plaintext = coerceArray(ciphertext, true);
32022               var xorSegment;
32023
32024               for (var i = 0; i < plaintext.length; i += this.segmentSize) {
32025                 xorSegment = this._aes.encrypt(this._shiftRegister);
32026
32027                 for (var j = 0; j < this.segmentSize; j++) {
32028                   plaintext[i + j] ^= xorSegment[j];
32029                 } // Shift the register
32030
32031
32032                 copyArray(this._shiftRegister, this._shiftRegister, 0, this.segmentSize);
32033                 copyArray(ciphertext, this._shiftRegister, 16 - this.segmentSize, i, i + this.segmentSize);
32034               }
32035
32036               return plaintext;
32037             };
32038             /**
32039              *  Mode Of Operation - Output Feedback (OFB)
32040              */
32041
32042
32043             var ModeOfOperationOFB = function ModeOfOperationOFB(key, iv) {
32044               if (!(this instanceof ModeOfOperationOFB)) {
32045                 throw Error('AES must be instanitated with `new`');
32046               }
32047
32048               this.description = "Output Feedback";
32049               this.name = "ofb";
32050
32051               if (!iv) {
32052                 iv = createArray(16);
32053               } else if (iv.length != 16) {
32054                 throw new Error('invalid initialation vector size (must be 16 bytes)');
32055               }
32056
32057               this._lastPrecipher = coerceArray(iv, true);
32058               this._lastPrecipherIndex = 16;
32059               this._aes = new AES(key);
32060             };
32061
32062             ModeOfOperationOFB.prototype.encrypt = function (plaintext) {
32063               var encrypted = coerceArray(plaintext, true);
32064
32065               for (var i = 0; i < encrypted.length; i++) {
32066                 if (this._lastPrecipherIndex === 16) {
32067                   this._lastPrecipher = this._aes.encrypt(this._lastPrecipher);
32068                   this._lastPrecipherIndex = 0;
32069                 }
32070
32071                 encrypted[i] ^= this._lastPrecipher[this._lastPrecipherIndex++];
32072               }
32073
32074               return encrypted;
32075             }; // Decryption is symetric
32076
32077
32078             ModeOfOperationOFB.prototype.decrypt = ModeOfOperationOFB.prototype.encrypt;
32079             /**
32080              *  Counter object for CTR common mode of operation
32081              */
32082
32083             var Counter = function Counter(initialValue) {
32084               if (!(this instanceof Counter)) {
32085                 throw Error('Counter must be instanitated with `new`');
32086               } // We allow 0, but anything false-ish uses the default 1
32087
32088
32089               if (initialValue !== 0 && !initialValue) {
32090                 initialValue = 1;
32091               }
32092
32093               if (typeof initialValue === 'number') {
32094                 this._counter = createArray(16);
32095                 this.setValue(initialValue);
32096               } else {
32097                 this.setBytes(initialValue);
32098               }
32099             };
32100
32101             Counter.prototype.setValue = function (value) {
32102               if (typeof value !== 'number' || parseInt(value) != value) {
32103                 throw new Error('invalid counter value (must be an integer)');
32104               } // We cannot safely handle numbers beyond the safe range for integers
32105
32106
32107               if (value > Number.MAX_SAFE_INTEGER) {
32108                 throw new Error('integer value out of safe range');
32109               }
32110
32111               for (var index = 15; index >= 0; --index) {
32112                 this._counter[index] = value % 256;
32113                 value = parseInt(value / 256);
32114               }
32115             };
32116
32117             Counter.prototype.setBytes = function (bytes) {
32118               bytes = coerceArray(bytes, true);
32119
32120               if (bytes.length != 16) {
32121                 throw new Error('invalid counter bytes size (must be 16 bytes)');
32122               }
32123
32124               this._counter = bytes;
32125             };
32126
32127             Counter.prototype.increment = function () {
32128               for (var i = 15; i >= 0; i--) {
32129                 if (this._counter[i] === 255) {
32130                   this._counter[i] = 0;
32131                 } else {
32132                   this._counter[i]++;
32133                   break;
32134                 }
32135               }
32136             };
32137             /**
32138              *  Mode Of Operation - Counter (CTR)
32139              */
32140
32141
32142             var ModeOfOperationCTR = function ModeOfOperationCTR(key, counter) {
32143               if (!(this instanceof ModeOfOperationCTR)) {
32144                 throw Error('AES must be instanitated with `new`');
32145               }
32146
32147               this.description = "Counter";
32148               this.name = "ctr";
32149
32150               if (!(counter instanceof Counter)) {
32151                 counter = new Counter(counter);
32152               }
32153
32154               this._counter = counter;
32155               this._remainingCounter = null;
32156               this._remainingCounterIndex = 16;
32157               this._aes = new AES(key);
32158             };
32159
32160             ModeOfOperationCTR.prototype.encrypt = function (plaintext) {
32161               var encrypted = coerceArray(plaintext, true);
32162
32163               for (var i = 0; i < encrypted.length; i++) {
32164                 if (this._remainingCounterIndex === 16) {
32165                   this._remainingCounter = this._aes.encrypt(this._counter._counter);
32166                   this._remainingCounterIndex = 0;
32167
32168                   this._counter.increment();
32169                 }
32170
32171                 encrypted[i] ^= this._remainingCounter[this._remainingCounterIndex++];
32172               }
32173
32174               return encrypted;
32175             }; // Decryption is symetric
32176
32177
32178             ModeOfOperationCTR.prototype.decrypt = ModeOfOperationCTR.prototype.encrypt; ///////////////////////
32179             // Padding
32180             // See:https://tools.ietf.org/html/rfc2315
32181
32182             function pkcs7pad(data) {
32183               data = coerceArray(data, true);
32184               var padder = 16 - data.length % 16;
32185               var result = createArray(data.length + padder);
32186               copyArray(data, result);
32187
32188               for (var i = data.length; i < result.length; i++) {
32189                 result[i] = padder;
32190               }
32191
32192               return result;
32193             }
32194
32195             function pkcs7strip(data) {
32196               data = coerceArray(data, true);
32197
32198               if (data.length < 16) {
32199                 throw new Error('PKCS#7 invalid length');
32200               }
32201
32202               var padder = data[data.length - 1];
32203
32204               if (padder > 16) {
32205                 throw new Error('PKCS#7 padding byte out of range');
32206               }
32207
32208               var length = data.length - padder;
32209
32210               for (var i = 0; i < padder; i++) {
32211                 if (data[length + i] !== padder) {
32212                   throw new Error('PKCS#7 invalid padding byte');
32213                 }
32214               }
32215
32216               var result = createArray(length);
32217               copyArray(data, result, 0, 0, length);
32218               return result;
32219             } ///////////////////////
32220             // Exporting
32221             // The block cipher
32222
32223
32224             var aesjs = {
32225               AES: AES,
32226               Counter: Counter,
32227               ModeOfOperation: {
32228                 ecb: ModeOfOperationECB,
32229                 cbc: ModeOfOperationCBC,
32230                 cfb: ModeOfOperationCFB,
32231                 ofb: ModeOfOperationOFB,
32232                 ctr: ModeOfOperationCTR
32233               },
32234               utils: {
32235                 hex: convertHex,
32236                 utf8: convertUtf8
32237               },
32238               padding: {
32239                 pkcs7: {
32240                   pad: pkcs7pad,
32241                   strip: pkcs7strip
32242                 }
32243               },
32244               _arrayTest: {
32245                 coerceArray: coerceArray,
32246                 createArray: createArray,
32247                 copyArray: copyArray
32248               }
32249             }; // node.js
32250
32251             {
32252               module.exports = aesjs; // RequireJS/AMD
32253               // http://www.requirejs.org/docs/api.html
32254               // https://github.com/amdjs/amdjs-api/wiki/AMD
32255             }
32256           })();
32257         })(aesJs);
32258
32259         var aesjs = aesJs.exports;
32260
32261         // We can use keys that are 128 bits (16 bytes), 192 bits (24 bytes) or 256 bits (32 bytes).
32262         // To generate a random key:  window.crypto.getRandomValues(new Uint8Array(16));
32263         // This default signing key is built into iD and can be used to mask/unmask sensitive values.
32264
32265         var DEFAULT_128 = [250, 157, 60, 79, 142, 134, 229, 129, 138, 126, 210, 129, 29, 71, 160, 208];
32266         function utilAesEncrypt(text, key) {
32267           key = key || DEFAULT_128;
32268           var textBytes = aesjs.utils.utf8.toBytes(text);
32269           var aesCtr = new aesjs.ModeOfOperation.ctr(key);
32270           var encryptedBytes = aesCtr.encrypt(textBytes);
32271           var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes);
32272           return encryptedHex;
32273         }
32274         function utilAesDecrypt(encryptedHex, key) {
32275           key = key || DEFAULT_128;
32276           var encryptedBytes = aesjs.utils.hex.toBytes(encryptedHex);
32277           var aesCtr = new aesjs.ModeOfOperation.ctr(key);
32278           var decryptedBytes = aesCtr.decrypt(encryptedBytes);
32279           var text = aesjs.utils.utf8.fromBytes(decryptedBytes);
32280           return text;
32281         }
32282
32283         function utilCleanTags(tags) {
32284           var out = {};
32285
32286           for (var k in tags) {
32287             if (!k) continue;
32288             var v = tags[k];
32289
32290             if (v !== undefined) {
32291               out[k] = cleanValue(k, v);
32292             }
32293           }
32294
32295           return out;
32296
32297           function cleanValue(k, v) {
32298             function keepSpaces(k) {
32299               return /_hours|_times|:conditional$/.test(k);
32300             }
32301
32302             function skip(k) {
32303               return /^(description|note|fixme)$/.test(k);
32304             }
32305
32306             if (skip(k)) return v;
32307             var cleaned = v.split(';').map(function (s) {
32308               return s.trim();
32309             }).join(keepSpaces(k) ? '; ' : ';'); // The code below is not intended to validate websites and emails.
32310             // It is only intended to prevent obvious copy-paste errors. (#2323)
32311             // clean website- and email-like tags
32312
32313             if (k.indexOf('website') !== -1 || k.indexOf('email') !== -1 || cleaned.indexOf('http') === 0) {
32314               cleaned = cleaned.replace(/[\u200B-\u200F\uFEFF]/g, ''); // strip LRM and other zero width chars
32315             }
32316
32317             return cleaned;
32318           }
32319         }
32320
32321         var _detected;
32322
32323         function utilDetect(refresh) {
32324           if (_detected && !refresh) return _detected;
32325           _detected = {};
32326           var ua = navigator.userAgent;
32327           var m = null;
32328           /* Browser */
32329
32330           m = ua.match(/(edge)\/?\s*(\.?\d+(\.\d+)*)/i); // Edge
32331
32332           if (m !== null) {
32333             _detected.browser = m[1];
32334             _detected.version = m[2];
32335           }
32336
32337           if (!_detected.browser) {
32338             m = ua.match(/Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/i); // IE11
32339
32340             if (m !== null) {
32341               _detected.browser = 'msie';
32342               _detected.version = m[1];
32343             }
32344           }
32345
32346           if (!_detected.browser) {
32347             m = ua.match(/(opr)\/?\s*(\.?\d+(\.\d+)*)/i); // Opera 15+
32348
32349             if (m !== null) {
32350               _detected.browser = 'Opera';
32351               _detected.version = m[2];
32352             }
32353           }
32354
32355           if (!_detected.browser) {
32356             m = ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
32357
32358             if (m !== null) {
32359               _detected.browser = m[1];
32360               _detected.version = m[2];
32361               m = ua.match(/version\/([\.\d]+)/i);
32362               if (m !== null) _detected.version = m[1];
32363             }
32364           }
32365
32366           if (!_detected.browser) {
32367             _detected.browser = navigator.appName;
32368             _detected.version = navigator.appVersion;
32369           } // keep major.minor version only..
32370
32371
32372           _detected.version = _detected.version.split(/\W/).slice(0, 2).join('.'); // detect other browser capabilities
32373           // Legacy Opera has incomplete svg style support. See #715
32374
32375           _detected.opera = _detected.browser.toLowerCase() === 'opera' && parseFloat(_detected.version) < 15;
32376
32377           if (_detected.browser.toLowerCase() === 'msie') {
32378             _detected.ie = true;
32379             _detected.browser = 'Internet Explorer';
32380             _detected.support = parseFloat(_detected.version) >= 11;
32381           } else {
32382             _detected.ie = false;
32383             _detected.support = true;
32384           }
32385
32386           _detected.filedrop = window.FileReader && 'ondrop' in window;
32387           _detected.download = !(_detected.ie || _detected.browser.toLowerCase() === 'edge');
32388           _detected.cssfilters = !(_detected.ie || _detected.browser.toLowerCase() === 'edge');
32389           /* Platform */
32390
32391           if (/Win/.test(ua)) {
32392             _detected.os = 'win';
32393             _detected.platform = 'Windows';
32394           } else if (/Mac/.test(ua)) {
32395             _detected.os = 'mac';
32396             _detected.platform = 'Macintosh';
32397           } else if (/X11/.test(ua) || /Linux/.test(ua)) {
32398             _detected.os = 'linux';
32399             _detected.platform = 'Linux';
32400           } else {
32401             _detected.os = 'win';
32402             _detected.platform = 'Unknown';
32403           }
32404
32405           _detected.isMobileWebKit = (/\b(iPad|iPhone|iPod)\b/.test(ua) || // HACK: iPadOS 13+ requests desktop sites by default by using a Mac user agent,
32406           // so assume any "mac" with multitouch is actually iOS
32407           navigator.platform === 'MacIntel' && 'maxTouchPoints' in navigator && navigator.maxTouchPoints > 1) && /WebKit/.test(ua) && !/Edge/.test(ua) && !window.MSStream;
32408           /* Locale */
32409           // An array of locales requested by the browser in priority order.
32410
32411           _detected.browserLocales = Array.from(new Set( // remove duplicates
32412           [navigator.language].concat(navigator.languages || []).concat([// old property for backwards compatibility
32413           navigator.userLanguage]) // remove any undefined values
32414           .filter(Boolean)));
32415           /* Host */
32416
32417           var loc = window.top.location;
32418           var origin = loc.origin;
32419
32420           if (!origin) {
32421             // for unpatched IE11
32422             origin = loc.protocol + '//' + loc.hostname + (loc.port ? ':' + loc.port : '');
32423           }
32424
32425           _detected.host = origin + loc.pathname;
32426           return _detected;
32427         }
32428
32429         // Like selection.property('value', ...), but avoids no-op value sets,
32430         // which can result in layout/repaint thrashing in some situations.
32431
32432         /** @returns {string} */
32433         function utilGetSetValue(selection, value) {
32434           function d3_selection_value(value) {
32435             function valueNull() {
32436               delete this.value;
32437             }
32438
32439             function valueConstant() {
32440               if (this.value !== value) {
32441                 this.value = value;
32442               }
32443             }
32444
32445             function valueFunction() {
32446               var x = value.apply(this, arguments);
32447
32448               if (x === null || x === undefined) {
32449                 delete this.value;
32450               } else if (this.value !== x) {
32451                 this.value = x;
32452               }
32453             }
32454
32455             return value === null || value === undefined ? valueNull : typeof value === 'function' ? valueFunction : valueConstant;
32456           }
32457
32458           if (arguments.length === 1) {
32459             return selection.property('value');
32460           }
32461
32462           return selection.each(d3_selection_value(value));
32463         }
32464
32465         function utilKeybinding(namespace) {
32466           var _keybindings = {};
32467
32468           function testBindings(d3_event, isCapturing) {
32469             var didMatch = false;
32470             var bindings = Object.keys(_keybindings).map(function (id) {
32471               return _keybindings[id];
32472             });
32473             var i, binding; // Most key shortcuts will accept either lower or uppercase ('h' or 'H'),
32474             // so we don't strictly match on the shift key, but we prioritize
32475             // shifted keybindings first, and fallback to unshifted only if no match.
32476             // (This lets us differentiate between '←'/'⇧←' or '⌘Z'/'⌘⇧Z')
32477             // priority match shifted keybindings first
32478
32479             for (i = 0; i < bindings.length; i++) {
32480               binding = bindings[i];
32481               if (!binding.event.modifiers.shiftKey) continue; // no shift
32482
32483               if (!!binding.capture !== isCapturing) continue;
32484
32485               if (matches(d3_event, binding, true)) {
32486                 binding.callback(d3_event);
32487                 didMatch = true; // match a max of one binding per event
32488
32489                 break;
32490               }
32491             }
32492
32493             if (didMatch) return; // then unshifted keybindings
32494
32495             for (i = 0; i < bindings.length; i++) {
32496               binding = bindings[i];
32497               if (binding.event.modifiers.shiftKey) continue; // shift
32498
32499               if (!!binding.capture !== isCapturing) continue;
32500
32501               if (matches(d3_event, binding, false)) {
32502                 binding.callback(d3_event);
32503                 break;
32504               }
32505             }
32506
32507             function matches(d3_event, binding, testShift) {
32508               var event = d3_event;
32509               var isMatch = false;
32510               var tryKeyCode = true; // Prefer a match on `KeyboardEvent.key`
32511
32512               if (event.key !== undefined) {
32513                 tryKeyCode = event.key.charCodeAt(0) > 255; // outside ISO-Latin-1
32514
32515                 isMatch = true;
32516
32517                 if (binding.event.key === undefined) {
32518                   isMatch = false;
32519                 } else if (Array.isArray(binding.event.key)) {
32520                   if (binding.event.key.map(function (s) {
32521                     return s.toLowerCase();
32522                   }).indexOf(event.key.toLowerCase()) === -1) {
32523                     isMatch = false;
32524                   }
32525                 } else {
32526                   if (event.key.toLowerCase() !== binding.event.key.toLowerCase()) {
32527                     isMatch = false;
32528                   }
32529                 }
32530               } // Fallback match on `KeyboardEvent.keyCode`, can happen if:
32531               // - browser doesn't support `KeyboardEvent.key`
32532               // - `KeyboardEvent.key` is outside ISO-Latin-1 range (cyrillic?)
32533
32534
32535               if (!isMatch && tryKeyCode) {
32536                 isMatch = event.keyCode === binding.event.keyCode;
32537               }
32538
32539               if (!isMatch) return false; // test modifier keys
32540
32541               if (!(event.ctrlKey && event.altKey)) {
32542                 // if both are set, assume AltGr and skip it - #4096
32543                 if (event.ctrlKey !== binding.event.modifiers.ctrlKey) return false;
32544                 if (event.altKey !== binding.event.modifiers.altKey) return false;
32545               }
32546
32547               if (event.metaKey !== binding.event.modifiers.metaKey) return false;
32548               if (testShift && event.shiftKey !== binding.event.modifiers.shiftKey) return false;
32549               return true;
32550             }
32551           }
32552
32553           function capture(d3_event) {
32554             testBindings(d3_event, true);
32555           }
32556
32557           function bubble(d3_event) {
32558             var tagName = select(d3_event.target).node().tagName;
32559
32560             if (tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA') {
32561               return;
32562             }
32563
32564             testBindings(d3_event, false);
32565           }
32566
32567           function keybinding(selection) {
32568             selection = selection || select(document);
32569             selection.on('keydown.capture.' + namespace, capture, true);
32570             selection.on('keydown.bubble.' + namespace, bubble, false);
32571             return keybinding;
32572           } // was: keybinding.off()
32573
32574
32575           keybinding.unbind = function (selection) {
32576             _keybindings = [];
32577             selection = selection || select(document);
32578             selection.on('keydown.capture.' + namespace, null);
32579             selection.on('keydown.bubble.' + namespace, null);
32580             return keybinding;
32581           };
32582
32583           keybinding.clear = function () {
32584             _keybindings = {};
32585             return keybinding;
32586           }; // Remove one or more keycode bindings.
32587
32588
32589           keybinding.off = function (codes, capture) {
32590             var arr = utilArrayUniq([].concat(codes));
32591
32592             for (var i = 0; i < arr.length; i++) {
32593               var id = arr[i] + (capture ? '-capture' : '-bubble');
32594               delete _keybindings[id];
32595             }
32596
32597             return keybinding;
32598           }; // Add one or more keycode bindings.
32599
32600
32601           keybinding.on = function (codes, callback, capture) {
32602             if (typeof callback !== 'function') {
32603               return keybinding.off(codes, capture);
32604             }
32605
32606             var arr = utilArrayUniq([].concat(codes));
32607
32608             for (var i = 0; i < arr.length; i++) {
32609               var id = arr[i] + (capture ? '-capture' : '-bubble');
32610               var binding = {
32611                 id: id,
32612                 capture: capture,
32613                 callback: callback,
32614                 event: {
32615                   key: undefined,
32616                   // preferred
32617                   keyCode: 0,
32618                   // fallback
32619                   modifiers: {
32620                     shiftKey: false,
32621                     ctrlKey: false,
32622                     altKey: false,
32623                     metaKey: false
32624                   }
32625                 }
32626               };
32627
32628               if (_keybindings[id]) {
32629                 console.warn('warning: duplicate keybinding for "' + id + '"'); // eslint-disable-line no-console
32630               }
32631
32632               _keybindings[id] = binding;
32633               var matches = arr[i].toLowerCase().match(/(?:(?:[^+⇧⌃⌥⌘])+|[⇧⌃⌥⌘]|\+\+|^\+$)/g);
32634
32635               for (var j = 0; j < matches.length; j++) {
32636                 // Normalise matching errors
32637                 if (matches[j] === '++') matches[j] = '+';
32638
32639                 if (matches[j] in utilKeybinding.modifierCodes) {
32640                   var prop = utilKeybinding.modifierProperties[utilKeybinding.modifierCodes[matches[j]]];
32641                   binding.event.modifiers[prop] = true;
32642                 } else {
32643                   binding.event.key = utilKeybinding.keys[matches[j]] || matches[j];
32644
32645                   if (matches[j] in utilKeybinding.keyCodes) {
32646                     binding.event.keyCode = utilKeybinding.keyCodes[matches[j]];
32647                   }
32648                 }
32649               }
32650             }
32651
32652             return keybinding;
32653           };
32654
32655           return keybinding;
32656         }
32657         /*
32658          * See https://github.com/keithamus/jwerty
32659          */
32660
32661         utilKeybinding.modifierCodes = {
32662           // Shift key, ⇧
32663           '⇧': 16,
32664           shift: 16,
32665           // CTRL key, on Mac: ⌃
32666           '⌃': 17,
32667           ctrl: 17,
32668           // ALT key, on Mac: ⌥ (Alt)
32669           '⌥': 18,
32670           alt: 18,
32671           option: 18,
32672           // META, on Mac: ⌘ (CMD), on Windows (Win), on Linux (Super)
32673           '⌘': 91,
32674           meta: 91,
32675           cmd: 91,
32676           'super': 91,
32677           win: 91
32678         };
32679         utilKeybinding.modifierProperties = {
32680           16: 'shiftKey',
32681           17: 'ctrlKey',
32682           18: 'altKey',
32683           91: 'metaKey'
32684         };
32685         utilKeybinding.plusKeys = ['plus', 'ffplus', '=', 'ffequals', '≠', '±'];
32686         utilKeybinding.minusKeys = ['_', '-', 'ffminus', 'dash', '–', '—'];
32687         utilKeybinding.keys = {
32688           // Backspace key, on Mac: ⌫ (Backspace)
32689           '⌫': 'Backspace',
32690           backspace: 'Backspace',
32691           // Tab Key, on Mac: ⇥ (Tab), on Windows ⇥⇥
32692           '⇥': 'Tab',
32693           '⇆': 'Tab',
32694           tab: 'Tab',
32695           // Return key, ↩
32696           '↩': 'Enter',
32697           '↵': 'Enter',
32698           '⏎': 'Enter',
32699           'return': 'Enter',
32700           enter: 'Enter',
32701           '⌅': 'Enter',
32702           // Pause/Break key
32703           'pause': 'Pause',
32704           'pause-break': 'Pause',
32705           // Caps Lock key, ⇪
32706           '⇪': 'CapsLock',
32707           caps: 'CapsLock',
32708           'caps-lock': 'CapsLock',
32709           // Escape key, on Mac: ⎋, on Windows: Esc
32710           '⎋': ['Escape', 'Esc'],
32711           escape: ['Escape', 'Esc'],
32712           esc: ['Escape', 'Esc'],
32713           // Space key
32714           space: [' ', 'Spacebar'],
32715           // Page-Up key, or pgup, on Mac: ↖
32716           '↖': 'PageUp',
32717           pgup: 'PageUp',
32718           'page-up': 'PageUp',
32719           // Page-Down key, or pgdown, on Mac: ↘
32720           '↘': 'PageDown',
32721           pgdown: 'PageDown',
32722           'page-down': 'PageDown',
32723           // END key, on Mac: ⇟
32724           '⇟': 'End',
32725           end: 'End',
32726           // HOME key, on Mac: ⇞
32727           '⇞': 'Home',
32728           home: 'Home',
32729           // Insert key, or ins
32730           ins: 'Insert',
32731           insert: 'Insert',
32732           // Delete key, on Mac: ⌦ (Delete)
32733           '⌦': ['Delete', 'Del'],
32734           del: ['Delete', 'Del'],
32735           'delete': ['Delete', 'Del'],
32736           // Left Arrow Key, or ←
32737           '←': ['ArrowLeft', 'Left'],
32738           left: ['ArrowLeft', 'Left'],
32739           'arrow-left': ['ArrowLeft', 'Left'],
32740           // Up Arrow Key, or ↑
32741           '↑': ['ArrowUp', 'Up'],
32742           up: ['ArrowUp', 'Up'],
32743           'arrow-up': ['ArrowUp', 'Up'],
32744           // Right Arrow Key, or →
32745           '→': ['ArrowRight', 'Right'],
32746           right: ['ArrowRight', 'Right'],
32747           'arrow-right': ['ArrowRight', 'Right'],
32748           // Up Arrow Key, or ↓
32749           '↓': ['ArrowDown', 'Down'],
32750           down: ['ArrowDown', 'Down'],
32751           'arrow-down': ['ArrowDown', 'Down'],
32752           // odities, stuff for backward compatibility (browsers and code):
32753           // Num-Multiply, or *
32754           '*': ['*', 'Multiply'],
32755           star: ['*', 'Multiply'],
32756           asterisk: ['*', 'Multiply'],
32757           multiply: ['*', 'Multiply'],
32758           // Num-Plus or +
32759           '+': ['+', 'Add'],
32760           'plus': ['+', 'Add'],
32761           // Num-Subtract, or -
32762           '-': ['-', 'Subtract'],
32763           subtract: ['-', 'Subtract'],
32764           'dash': ['-', 'Subtract'],
32765           // Semicolon
32766           semicolon: ';',
32767           // = or equals
32768           equals: '=',
32769           // Comma, or ,
32770           comma: ',',
32771           // Period, or ., or full-stop
32772           period: '.',
32773           'full-stop': '.',
32774           // Slash, or /, or forward-slash
32775           slash: '/',
32776           'forward-slash': '/',
32777           // Tick, or `, or back-quote
32778           tick: '`',
32779           'back-quote': '`',
32780           // Open bracket, or [
32781           'open-bracket': '[',
32782           // Back slash, or \
32783           'back-slash': '\\',
32784           // Close backet, or ]
32785           'close-bracket': ']',
32786           // Apostrophe, or Quote, or '
32787           quote: '\'',
32788           apostrophe: '\'',
32789           // NUMPAD 0-9
32790           'num-0': '0',
32791           'num-1': '1',
32792           'num-2': '2',
32793           'num-3': '3',
32794           'num-4': '4',
32795           'num-5': '5',
32796           'num-6': '6',
32797           'num-7': '7',
32798           'num-8': '8',
32799           'num-9': '9',
32800           // F1-F25
32801           f1: 'F1',
32802           f2: 'F2',
32803           f3: 'F3',
32804           f4: 'F4',
32805           f5: 'F5',
32806           f6: 'F6',
32807           f7: 'F7',
32808           f8: 'F8',
32809           f9: 'F9',
32810           f10: 'F10',
32811           f11: 'F11',
32812           f12: 'F12',
32813           f13: 'F13',
32814           f14: 'F14',
32815           f15: 'F15',
32816           f16: 'F16',
32817           f17: 'F17',
32818           f18: 'F18',
32819           f19: 'F19',
32820           f20: 'F20',
32821           f21: 'F21',
32822           f22: 'F22',
32823           f23: 'F23',
32824           f24: 'F24',
32825           f25: 'F25'
32826         };
32827         utilKeybinding.keyCodes = {
32828           // Backspace key, on Mac: ⌫ (Backspace)
32829           '⌫': 8,
32830           backspace: 8,
32831           // Tab Key, on Mac: ⇥ (Tab), on Windows ⇥⇥
32832           '⇥': 9,
32833           '⇆': 9,
32834           tab: 9,
32835           // Return key, ↩
32836           '↩': 13,
32837           '↵': 13,
32838           '⏎': 13,
32839           'return': 13,
32840           enter: 13,
32841           '⌅': 13,
32842           // Pause/Break key
32843           'pause': 19,
32844           'pause-break': 19,
32845           // Caps Lock key, ⇪
32846           '⇪': 20,
32847           caps: 20,
32848           'caps-lock': 20,
32849           // Escape key, on Mac: ⎋, on Windows: Esc
32850           '⎋': 27,
32851           escape: 27,
32852           esc: 27,
32853           // Space key
32854           space: 32,
32855           // Page-Up key, or pgup, on Mac: ↖
32856           '↖': 33,
32857           pgup: 33,
32858           'page-up': 33,
32859           // Page-Down key, or pgdown, on Mac: ↘
32860           '↘': 34,
32861           pgdown: 34,
32862           'page-down': 34,
32863           // END key, on Mac: ⇟
32864           '⇟': 35,
32865           end: 35,
32866           // HOME key, on Mac: ⇞
32867           '⇞': 36,
32868           home: 36,
32869           // Insert key, or ins
32870           ins: 45,
32871           insert: 45,
32872           // Delete key, on Mac: ⌦ (Delete)
32873           '⌦': 46,
32874           del: 46,
32875           'delete': 46,
32876           // Left Arrow Key, or ←
32877           '←': 37,
32878           left: 37,
32879           'arrow-left': 37,
32880           // Up Arrow Key, or ↑
32881           '↑': 38,
32882           up: 38,
32883           'arrow-up': 38,
32884           // Right Arrow Key, or →
32885           '→': 39,
32886           right: 39,
32887           'arrow-right': 39,
32888           // Up Arrow Key, or ↓
32889           '↓': 40,
32890           down: 40,
32891           'arrow-down': 40,
32892           // odities, printing characters that come out wrong:
32893           // Firefox Equals
32894           'ffequals': 61,
32895           // Num-Multiply, or *
32896           '*': 106,
32897           star: 106,
32898           asterisk: 106,
32899           multiply: 106,
32900           // Num-Plus or +
32901           '+': 107,
32902           'plus': 107,
32903           // Num-Subtract, or -
32904           '-': 109,
32905           subtract: 109,
32906           // Vertical Bar / Pipe
32907           '|': 124,
32908           // Firefox Plus
32909           'ffplus': 171,
32910           // Firefox Minus
32911           'ffminus': 173,
32912           // Semicolon
32913           ';': 186,
32914           semicolon: 186,
32915           // = or equals
32916           '=': 187,
32917           'equals': 187,
32918           // Comma, or ,
32919           ',': 188,
32920           comma: 188,
32921           // Dash / Underscore key
32922           'dash': 189,
32923           // Period, or ., or full-stop
32924           '.': 190,
32925           period: 190,
32926           'full-stop': 190,
32927           // Slash, or /, or forward-slash
32928           '/': 191,
32929           slash: 191,
32930           'forward-slash': 191,
32931           // Tick, or `, or back-quote
32932           '`': 192,
32933           tick: 192,
32934           'back-quote': 192,
32935           // Open bracket, or [
32936           '[': 219,
32937           'open-bracket': 219,
32938           // Back slash, or \
32939           '\\': 220,
32940           'back-slash': 220,
32941           // Close backet, or ]
32942           ']': 221,
32943           'close-bracket': 221,
32944           // Apostrophe, or Quote, or '
32945           '\'': 222,
32946           quote: 222,
32947           apostrophe: 222
32948         }; // NUMPAD 0-9
32949
32950         var i = 95,
32951             n = 0;
32952
32953         while (++i < 106) {
32954           utilKeybinding.keyCodes['num-' + n] = i;
32955           ++n;
32956         } // 0-9
32957
32958
32959         i = 47;
32960         n = 0;
32961
32962         while (++i < 58) {
32963           utilKeybinding.keyCodes[n] = i;
32964           ++n;
32965         } // F1-F25
32966
32967
32968         i = 111;
32969         n = 1;
32970
32971         while (++i < 136) {
32972           utilKeybinding.keyCodes['f' + n] = i;
32973           ++n;
32974         } // a-z
32975
32976
32977         i = 64;
32978
32979         while (++i < 91) {
32980           utilKeybinding.keyCodes[String.fromCharCode(i).toLowerCase()] = i;
32981         }
32982
32983         function utilObjectOmit(obj, omitKeys) {
32984           return Object.keys(obj).reduce(function (result, key) {
32985             if (omitKeys.indexOf(key) === -1) {
32986               result[key] = obj[key]; // keep
32987             }
32988
32989             return result;
32990           }, {});
32991         }
32992
32993         // Copies a variable number of methods from source to target.
32994         function utilRebind(target, source) {
32995           var i = 1,
32996               n = arguments.length,
32997               method;
32998
32999           while (++i < n) {
33000             target[method = arguments[i]] = d3_rebind(target, source, source[method]);
33001           }
33002
33003           return target;
33004         } // Method is assumed to be a standard D3 getter-setter:
33005         // If passed with no arguments, gets the value.
33006         // If passed with arguments, sets the value and returns the target.
33007
33008         function d3_rebind(target, source, method) {
33009           return function () {
33010             var value = method.apply(source, arguments);
33011             return value === source ? target : value;
33012           };
33013         }
33014
33015         // A per-domain session mutex backed by a cookie and dead man's
33016         // switch. If the session crashes, the mutex will auto-release
33017         // after 5 seconds.
33018         // This accepts a string and returns an object that complies with utilSessionMutexType
33019         function utilSessionMutex(name) {
33020           var mutex = {};
33021           var intervalID;
33022
33023           function renew() {
33024             var expires = new Date();
33025             expires.setSeconds(expires.getSeconds() + 5);
33026             document.cookie = name + '=1; expires=' + expires.toUTCString() + '; sameSite=strict';
33027           }
33028
33029           mutex.lock = function () {
33030             if (intervalID) return true;
33031             var cookie = document.cookie.replace(new RegExp('(?:(?:^|.*;)\\s*' + name + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1');
33032             if (cookie) return false;
33033             renew();
33034             intervalID = window.setInterval(renew, 4000);
33035             return true;
33036           };
33037
33038           mutex.unlock = function () {
33039             if (!intervalID) return;
33040             document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT; sameSite=strict';
33041             clearInterval(intervalID);
33042             intervalID = null;
33043           };
33044
33045           mutex.locked = function () {
33046             return !!intervalID;
33047           };
33048
33049           return mutex;
33050         }
33051
33052         function utilTiler() {
33053           var _size = [256, 256];
33054           var _scale = 256;
33055           var _tileSize = 256;
33056           var _zoomExtent = [0, 20];
33057           var _translate = [_size[0] / 2, _size[1] / 2];
33058           var _margin = 0;
33059           var _skipNullIsland = false;
33060
33061           function clamp(num, min, max) {
33062             return Math.max(min, Math.min(num, max));
33063           }
33064
33065           function nearNullIsland(tile) {
33066             var x = tile[0];
33067             var y = tile[1];
33068             var z = tile[2];
33069
33070             if (z >= 7) {
33071               var center = Math.pow(2, z - 1);
33072               var width = Math.pow(2, z - 6);
33073               var min = center - width / 2;
33074               var max = center + width / 2 - 1;
33075               return x >= min && x <= max && y >= min && y <= max;
33076             }
33077
33078             return false;
33079           }
33080
33081           function tiler() {
33082             var z = geoScaleToZoom(_scale / (2 * Math.PI), _tileSize);
33083             var z0 = clamp(Math.round(z), _zoomExtent[0], _zoomExtent[1]);
33084             var tileMin = 0;
33085             var tileMax = Math.pow(2, z0) - 1;
33086             var log2ts = Math.log(_tileSize) * Math.LOG2E;
33087             var k = Math.pow(2, z - z0 + log2ts);
33088             var origin = [(_translate[0] - _scale / 2) / k, (_translate[1] - _scale / 2) / k];
33089             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));
33090             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));
33091             var tiles = [];
33092
33093             for (var i = 0; i < rows.length; i++) {
33094               var y = rows[i];
33095
33096               for (var j = 0; j < cols.length; j++) {
33097                 var x = cols[j];
33098
33099                 if (i >= _margin && i <= rows.length - _margin && j >= _margin && j <= cols.length - _margin) {
33100                   tiles.unshift([x, y, z0]); // tiles in view at beginning
33101                 } else {
33102                   tiles.push([x, y, z0]); // tiles in margin at the end
33103                 }
33104               }
33105             }
33106
33107             tiles.translate = origin;
33108             tiles.scale = k;
33109             return tiles;
33110           }
33111           /**
33112            * getTiles() returns an array of tiles that cover the map view
33113            */
33114
33115
33116           tiler.getTiles = function (projection) {
33117             var origin = [projection.scale() * Math.PI - projection.translate()[0], projection.scale() * Math.PI - projection.translate()[1]];
33118             this.size(projection.clipExtent()[1]).scale(projection.scale() * 2 * Math.PI).translate(projection.translate());
33119             var tiles = tiler();
33120             var ts = tiles.scale;
33121             return tiles.map(function (tile) {
33122               if (_skipNullIsland && nearNullIsland(tile)) {
33123                 return false;
33124               }
33125
33126               var x = tile[0] * ts - origin[0];
33127               var y = tile[1] * ts - origin[1];
33128               return {
33129                 id: tile.toString(),
33130                 xyz: tile,
33131                 extent: geoExtent(projection.invert([x, y + ts]), projection.invert([x + ts, y]))
33132               };
33133             }).filter(Boolean);
33134           };
33135           /**
33136            * getGeoJSON() returns a FeatureCollection for debugging tiles
33137            */
33138
33139
33140           tiler.getGeoJSON = function (projection) {
33141             var features = tiler.getTiles(projection).map(function (tile) {
33142               return {
33143                 type: 'Feature',
33144                 properties: {
33145                   id: tile.id,
33146                   name: tile.id
33147                 },
33148                 geometry: {
33149                   type: 'Polygon',
33150                   coordinates: [tile.extent.polygon()]
33151                 }
33152               };
33153             });
33154             return {
33155               type: 'FeatureCollection',
33156               features: features
33157             };
33158           };
33159
33160           tiler.tileSize = function (val) {
33161             if (!arguments.length) return _tileSize;
33162             _tileSize = val;
33163             return tiler;
33164           };
33165
33166           tiler.zoomExtent = function (val) {
33167             if (!arguments.length) return _zoomExtent;
33168             _zoomExtent = val;
33169             return tiler;
33170           };
33171
33172           tiler.size = function (val) {
33173             if (!arguments.length) return _size;
33174             _size = val;
33175             return tiler;
33176           };
33177
33178           tiler.scale = function (val) {
33179             if (!arguments.length) return _scale;
33180             _scale = val;
33181             return tiler;
33182           };
33183
33184           tiler.translate = function (val) {
33185             if (!arguments.length) return _translate;
33186             _translate = val;
33187             return tiler;
33188           }; // number to extend the rows/columns beyond those covering the viewport
33189
33190
33191           tiler.margin = function (val) {
33192             if (!arguments.length) return _margin;
33193             _margin = +val;
33194             return tiler;
33195           };
33196
33197           tiler.skipNullIsland = function (val) {
33198             if (!arguments.length) return _skipNullIsland;
33199             _skipNullIsland = val;
33200             return tiler;
33201           };
33202
33203           return tiler;
33204         }
33205
33206         function utilTriggerEvent(target, type) {
33207           target.each(function () {
33208             var evt = document.createEvent('HTMLEvents');
33209             evt.initEvent(type, true, true);
33210             this.dispatchEvent(evt);
33211           });
33212         }
33213
33214         var _mainLocations = coreLocations(); // singleton
33215         // `coreLocations` maintains an internal index of all the boundaries/geofences used by iD.
33216         // It's used by presets, community index, background imagery, to know where in the world these things are valid.
33217         // These geofences should be defined by `locationSet` objects:
33218         //
33219         // let locationSet = {
33220         //   include: [ Array of locations ],
33221         //   exclude: [ Array of locations ]
33222         // };
33223         //
33224         // For more info see the location-conflation and country-coder projects, see:
33225         // https://github.com/ideditor/location-conflation
33226         // https://github.com/ideditor/country-coder
33227         //
33228
33229         function coreLocations() {
33230           var _this = {};
33231           var _resolvedFeatures = {}; // cache of *resolved* locationSet features
33232
33233           var _loco = new _default(); // instance of a location-conflation resolver
33234
33235
33236           var _wp; // instance of a which-polygon index
33237           // pre-resolve the worldwide locationSet
33238
33239
33240           var world = {
33241             locationSet: {
33242               include: ['Q2']
33243             }
33244           };
33245           resolveLocationSet(world);
33246           rebuildIndex();
33247           var _queue = [];
33248
33249           var _deferred = new Set();
33250
33251           var _inProcess; // Returns a Promise to process the queue
33252
33253
33254           function processQueue() {
33255             if (!_queue.length) return Promise.resolve(); // console.log(`queue length ${_queue.length}`);
33256
33257             var chunk = _queue.pop();
33258
33259             return new Promise(function (resolvePromise) {
33260               var handle = window.requestIdleCallback(function () {
33261                 _deferred["delete"](handle); // const t0 = performance.now();
33262
33263
33264                 chunk.forEach(resolveLocationSet); // const t1 = performance.now();
33265                 // console.log('chunk processed in ' + (t1 - t0) + ' ms');
33266
33267                 resolvePromise();
33268               });
33269
33270               _deferred.add(handle);
33271             }).then(function () {
33272               return processQueue();
33273             });
33274           } // Pass an Object with a `locationSet` property,
33275           // Performs the locationSet resolution, caches the result, and sets a `locationSetID` property on the object.
33276
33277
33278           function resolveLocationSet(obj) {
33279             if (obj.locationSetID) return; // work was done already
33280
33281             try {
33282               var locationSet = obj.locationSet;
33283
33284               if (!locationSet) {
33285                 throw new Error('object missing locationSet property');
33286               }
33287
33288               if (!locationSet.include) {
33289                 // missing `include`, default to worldwide include
33290                 locationSet.include = ['Q2']; // https://github.com/openstreetmap/iD/pull/8305#discussion_r662344647
33291               }
33292
33293               var resolved = _loco.resolveLocationSet(locationSet);
33294
33295               var locationSetID = resolved.id;
33296               obj.locationSetID = locationSetID;
33297
33298               if (!resolved.feature.geometry.coordinates.length || !resolved.feature.properties.area) {
33299                 throw new Error("locationSet ".concat(locationSetID, " resolves to an empty feature."));
33300               }
33301
33302               if (!_resolvedFeatures[locationSetID]) {
33303                 // First time seeing this locationSet feature
33304                 var feature = JSON.parse(JSON.stringify(resolved.feature)); // deep clone
33305
33306                 feature.id = locationSetID; // Important: always use the locationSet `id` (`+[Q30]`), not the feature `id` (`Q30`)
33307
33308                 feature.properties.id = locationSetID;
33309                 _resolvedFeatures[locationSetID] = feature; // insert into cache
33310               }
33311             } catch (err) {
33312               obj.locationSet = {
33313                 include: ['Q2']
33314               }; // default worldwide
33315
33316               obj.locationSetID = '+[Q2]';
33317             }
33318           } // Rebuilds the whichPolygon index with whatever features have been resolved.
33319
33320
33321           function rebuildIndex() {
33322             _wp = whichPolygon_1({
33323               features: Object.values(_resolvedFeatures)
33324             });
33325           } //
33326           // `mergeCustomGeoJSON`
33327           //  Accepts an FeatureCollection-like object containing custom locations
33328           //  Each feature must have a filename-like `id`, for example: `something.geojson`
33329           //
33330           //  {
33331           //    "type": "FeatureCollection"
33332           //    "features": [
33333           //      {
33334           //        "type": "Feature",
33335           //        "id": "philly_metro.geojson",
33336           //        "properties": { … },
33337           //        "geometry": { … }
33338           //      }
33339           //    ]
33340           //  }
33341           //
33342
33343
33344           _this.mergeCustomGeoJSON = function (fc) {
33345             if (fc && fc.type === 'FeatureCollection' && Array.isArray(fc.features)) {
33346               fc.features.forEach(function (feature) {
33347                 feature.properties = feature.properties || {};
33348                 var props = feature.properties; // Get `id` from either `id` or `properties`
33349
33350                 var id = feature.id || props.id;
33351                 if (!id || !/^\S+\.geojson$/i.test(id)) return; // Ensure `id` exists and is lowercase
33352
33353                 id = id.toLowerCase();
33354                 feature.id = id;
33355                 props.id = id; // Ensure `area` property exists
33356
33357                 if (!props.area) {
33358                   var area = geojsonArea.geometry(feature.geometry) / 1e6; // m² to km²
33359
33360                   props.area = Number(area.toFixed(2));
33361                 }
33362
33363                 _loco._cache[id] = feature;
33364               });
33365             }
33366           }; //
33367           // `mergeLocationSets`
33368           //  Accepts an Array of Objects containing `locationSet` properties.
33369           //  The locationSets will be resolved and indexed in the background.
33370           //  [
33371           //   { id: 'preset1', locationSet: {…} },
33372           //   { id: 'preset2', locationSet: {…} },
33373           //   { id: 'preset3', locationSet: {…} },
33374           //   …
33375           //  ]
33376           //  After resolving and indexing, the Objects will be decorated with a
33377           //  `locationSetID` property.
33378           //  [
33379           //   { id: 'preset1', locationSet: {…}, locationSetID: '+[Q2]' },
33380           //   { id: 'preset2', locationSet: {…}, locationSetID: '+[Q30]' },
33381           //   { id: 'preset3', locationSet: {…}, locationSetID: '+[Q2]' },
33382           //   …
33383           //  ]
33384           //
33385           //  Returns a Promise fulfilled when the resolving/indexing has been completed
33386           //  This will take some seconds but happen in the background during browser idle time.
33387           //
33388
33389
33390           _this.mergeLocationSets = function (objects) {
33391             if (!Array.isArray(objects)) return Promise.reject('nothing to do'); // Resolve all locationSets -> geojson, processing data in chunks
33392             //
33393             // Because this will happen during idle callbacks, we want to choose a chunk size
33394             // that won't make the browser stutter too badly.  LocationSets that are a simple
33395             // country coder include will resolve instantly, but ones that involve complex
33396             // include/exclude operations will take some milliseconds longer.
33397             //
33398             // Some discussion and performance results on these tickets:
33399             // https://github.com/ideditor/location-conflation/issues/26
33400             // https://github.com/osmlab/name-suggestion-index/issues/4784#issuecomment-742003434
33401
33402             _queue = _queue.concat(utilArrayChunk(objects, 200));
33403
33404             if (!_inProcess) {
33405               _inProcess = processQueue().then(function () {
33406                 rebuildIndex();
33407                 _inProcess = null;
33408                 return objects;
33409               });
33410             }
33411
33412             return _inProcess;
33413           }; //
33414           // `locationSetID`
33415           // Returns a locationSetID for a given locationSet (fallback to `+[Q2]`, world)
33416           // (The locationset doesn't necessarily need to be resolved to compute its `id`)
33417           //
33418           // Arguments
33419           //   `locationSet`: A locationSet, e.g. `{ include: ['us'] }`
33420           // Returns
33421           //   The locationSetID, e.g. `+[Q30]`
33422           //
33423
33424
33425           _this.locationSetID = function (locationSet) {
33426             var locationSetID;
33427
33428             try {
33429               locationSetID = _loco.validateLocationSet(locationSet).id;
33430             } catch (err) {
33431               locationSetID = '+[Q2]'; // the world
33432             }
33433
33434             return locationSetID;
33435           }; //
33436           // `feature`
33437           // Returns the resolved GeoJSON feature for a given locationSetID (fallback to 'world')
33438           //
33439           // Arguments
33440           //   `locationSetID`: id of the form like `+[Q30]`  (United States)
33441           // Returns
33442           //   A GeoJSON feature:
33443           //   {
33444           //     type: 'Feature',
33445           //     id: '+[Q30]',
33446           //     properties: { id: '+[Q30]', area: 21817019.17, … },
33447           //     geometry: { … }
33448           //   }
33449
33450
33451           _this.feature = function (locationSetID) {
33452             return _resolvedFeatures[locationSetID] || _resolvedFeatures['+[Q2]'];
33453           }; //
33454           // `locationsAt`
33455           // Find all the resolved locationSets valid at the given location.
33456           // Results include the area (in km²) to facilitate sorting.
33457           //
33458           // Arguments
33459           //   `loc`: the [lon,lat] location to query, e.g. `[-74.4813, 40.7967]`
33460           // Returns
33461           //   Object of locationSetIDs to areas (in km²)
33462           //   {
33463           //     "+[Q2]": 511207893.3958111,
33464           //     "+[Q30]": 21817019.17,
33465           //     "+[new_jersey.geojson]": 22390.77,
33466           //     …
33467           //   }
33468           //
33469
33470
33471           _this.locationsAt = function (loc) {
33472             var result = {};
33473             (_wp(loc, true) || []).forEach(function (prop) {
33474               return result[prop.id] = prop.area;
33475             });
33476             return result;
33477           }; //
33478           // `query`
33479           // Execute a query directly against which-polygon
33480           // https://github.com/mapbox/which-polygon
33481           //
33482           // Arguments
33483           //   `loc`: the [lon,lat] location to query,
33484           //   `multi`: `true` to return all results, `false` to return first result
33485           // Returns
33486           //   Array of GeoJSON *properties* for the locationSet features that exist at `loc`
33487           //
33488
33489
33490           _this.query = function (loc, multi) {
33491             return _wp(loc, multi);
33492           }; // Direct access to the location-conflation resolver
33493
33494
33495           _this.loco = function () {
33496             return _loco;
33497           }; // Direct access to the which-polygon index
33498
33499
33500           _this.wp = function () {
33501             return _wp;
33502           };
33503
33504           return _this;
33505         }
33506
33507         var $$h = _export;
33508         var $findIndex = arrayIteration.findIndex;
33509         var addToUnscopables$1 = addToUnscopables$6;
33510
33511         var FIND_INDEX = 'findIndex';
33512         var SKIPS_HOLES = true;
33513
33514         // Shouldn't skip holes
33515         if (FIND_INDEX in []) Array(1)[FIND_INDEX](function () { SKIPS_HOLES = false; });
33516
33517         // `Array.prototype.findIndex` method
33518         // https://tc39.es/ecma262/#sec-array.prototype.findindex
33519         $$h({ target: 'Array', proto: true, forced: SKIPS_HOLES }, {
33520           findIndex: function findIndex(callbackfn /* , that = undefined */) {
33521             return $findIndex(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
33522           }
33523         });
33524
33525         // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
33526         addToUnscopables$1(FIND_INDEX);
33527
33528         var global$5 = global$1m;
33529         var isRegExp = isRegexp;
33530
33531         var TypeError$3 = global$5.TypeError;
33532
33533         var notARegexp = function (it) {
33534           if (isRegExp(it)) {
33535             throw TypeError$3("The method doesn't accept regular expressions");
33536           } return it;
33537         };
33538
33539         var wellKnownSymbol = wellKnownSymbol$t;
33540
33541         var MATCH = wellKnownSymbol('match');
33542
33543         var correctIsRegexpLogic = function (METHOD_NAME) {
33544           var regexp = /./;
33545           try {
33546             '/./'[METHOD_NAME](regexp);
33547           } catch (error1) {
33548             try {
33549               regexp[MATCH] = false;
33550               return '/./'[METHOD_NAME](regexp);
33551             } catch (error2) { /* empty */ }
33552           } return false;
33553         };
33554
33555         var $$g = _export;
33556         var uncurryThis$7 = functionUncurryThis;
33557         var notARegExp$2 = notARegexp;
33558         var requireObjectCoercible$3 = requireObjectCoercible$e;
33559         var toString$4 = toString$k;
33560         var correctIsRegExpLogic$2 = correctIsRegexpLogic;
33561
33562         var stringIndexOf = uncurryThis$7(''.indexOf);
33563
33564         // `String.prototype.includes` method
33565         // https://tc39.es/ecma262/#sec-string.prototype.includes
33566         $$g({ target: 'String', proto: true, forced: !correctIsRegExpLogic$2('includes') }, {
33567           includes: function includes(searchString /* , position = 0 */) {
33568             return !!~stringIndexOf(
33569               toString$4(requireObjectCoercible$3(this)),
33570               toString$4(notARegExp$2(searchString)),
33571               arguments.length > 1 ? arguments[1] : undefined
33572             );
33573           }
33574         });
33575
33576         /** Detect free variable `global` from Node.js. */
33577         var freeGlobal = (typeof global === "undefined" ? "undefined" : _typeof(global)) == 'object' && global && global.Object === Object && global;
33578
33579         /** Detect free variable `self`. */
33580
33581         var freeSelf = (typeof self === "undefined" ? "undefined" : _typeof(self)) == 'object' && self && self.Object === Object && self;
33582         /** Used as a reference to the global object. */
33583
33584         var root = freeGlobal || freeSelf || Function('return this')();
33585
33586         /** Built-in value references. */
33587
33588         var _Symbol = root.Symbol;
33589
33590         /** Used for built-in method references. */
33591
33592         var objectProto$1 = Object.prototype;
33593         /** Used to check objects for own properties. */
33594
33595         var hasOwnProperty$2 = objectProto$1.hasOwnProperty;
33596         /**
33597          * Used to resolve the
33598          * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
33599          * of values.
33600          */
33601
33602         var nativeObjectToString$1 = objectProto$1.toString;
33603         /** Built-in value references. */
33604
33605         var symToStringTag$1 = _Symbol ? _Symbol.toStringTag : undefined;
33606         /**
33607          * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
33608          *
33609          * @private
33610          * @param {*} value The value to query.
33611          * @returns {string} Returns the raw `toStringTag`.
33612          */
33613
33614         function getRawTag(value) {
33615           var isOwn = hasOwnProperty$2.call(value, symToStringTag$1),
33616               tag = value[symToStringTag$1];
33617
33618           try {
33619             value[symToStringTag$1] = undefined;
33620             var unmasked = true;
33621           } catch (e) {}
33622
33623           var result = nativeObjectToString$1.call(value);
33624
33625           if (unmasked) {
33626             if (isOwn) {
33627               value[symToStringTag$1] = tag;
33628             } else {
33629               delete value[symToStringTag$1];
33630             }
33631           }
33632
33633           return result;
33634         }
33635
33636         /** Used for built-in method references. */
33637         var objectProto = Object.prototype;
33638         /**
33639          * Used to resolve the
33640          * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
33641          * of values.
33642          */
33643
33644         var nativeObjectToString = objectProto.toString;
33645         /**
33646          * Converts `value` to a string using `Object.prototype.toString`.
33647          *
33648          * @private
33649          * @param {*} value The value to convert.
33650          * @returns {string} Returns the converted string.
33651          */
33652
33653         function objectToString(value) {
33654           return nativeObjectToString.call(value);
33655         }
33656
33657         /** `Object#toString` result references. */
33658
33659         var nullTag = '[object Null]',
33660             undefinedTag = '[object Undefined]';
33661         /** Built-in value references. */
33662
33663         var symToStringTag = _Symbol ? _Symbol.toStringTag : undefined;
33664         /**
33665          * The base implementation of `getTag` without fallbacks for buggy environments.
33666          *
33667          * @private
33668          * @param {*} value The value to query.
33669          * @returns {string} Returns the `toStringTag`.
33670          */
33671
33672         function baseGetTag(value) {
33673           if (value == null) {
33674             return value === undefined ? undefinedTag : nullTag;
33675           }
33676
33677           return symToStringTag && symToStringTag in Object(value) ? getRawTag(value) : objectToString(value);
33678         }
33679
33680         /**
33681          * Checks if `value` is object-like. A value is object-like if it's not `null`
33682          * and has a `typeof` result of "object".
33683          *
33684          * @static
33685          * @memberOf _
33686          * @since 4.0.0
33687          * @category Lang
33688          * @param {*} value The value to check.
33689          * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
33690          * @example
33691          *
33692          * _.isObjectLike({});
33693          * // => true
33694          *
33695          * _.isObjectLike([1, 2, 3]);
33696          * // => true
33697          *
33698          * _.isObjectLike(_.noop);
33699          * // => false
33700          *
33701          * _.isObjectLike(null);
33702          * // => false
33703          */
33704         function isObjectLike(value) {
33705           return value != null && _typeof(value) == 'object';
33706         }
33707
33708         /** `Object#toString` result references. */
33709
33710         var symbolTag = '[object Symbol]';
33711         /**
33712          * Checks if `value` is classified as a `Symbol` primitive or object.
33713          *
33714          * @static
33715          * @memberOf _
33716          * @since 4.0.0
33717          * @category Lang
33718          * @param {*} value The value to check.
33719          * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
33720          * @example
33721          *
33722          * _.isSymbol(Symbol.iterator);
33723          * // => true
33724          *
33725          * _.isSymbol('abc');
33726          * // => false
33727          */
33728
33729         function isSymbol(value) {
33730           return _typeof(value) == 'symbol' || isObjectLike(value) && baseGetTag(value) == symbolTag;
33731         }
33732
33733         /**
33734          * A specialized version of `_.map` for arrays without support for iteratee
33735          * shorthands.
33736          *
33737          * @private
33738          * @param {Array} [array] The array to iterate over.
33739          * @param {Function} iteratee The function invoked per iteration.
33740          * @returns {Array} Returns the new mapped array.
33741          */
33742         function arrayMap(array, iteratee) {
33743           var index = -1,
33744               length = array == null ? 0 : array.length,
33745               result = Array(length);
33746
33747           while (++index < length) {
33748             result[index] = iteratee(array[index], index, array);
33749           }
33750
33751           return result;
33752         }
33753
33754         /**
33755          * Checks if `value` is classified as an `Array` object.
33756          *
33757          * @static
33758          * @memberOf _
33759          * @since 0.1.0
33760          * @category Lang
33761          * @param {*} value The value to check.
33762          * @returns {boolean} Returns `true` if `value` is an array, else `false`.
33763          * @example
33764          *
33765          * _.isArray([1, 2, 3]);
33766          * // => true
33767          *
33768          * _.isArray(document.body.children);
33769          * // => false
33770          *
33771          * _.isArray('abc');
33772          * // => false
33773          *
33774          * _.isArray(_.noop);
33775          * // => false
33776          */
33777         var isArray$1 = Array.isArray;
33778
33779         /** Used as references for various `Number` constants. */
33780
33781         var INFINITY = 1 / 0;
33782         /** Used to convert symbols to primitives and strings. */
33783
33784         var symbolProto = _Symbol ? _Symbol.prototype : undefined,
33785             symbolToString = symbolProto ? symbolProto.toString : undefined;
33786         /**
33787          * The base implementation of `_.toString` which doesn't convert nullish
33788          * values to empty strings.
33789          *
33790          * @private
33791          * @param {*} value The value to process.
33792          * @returns {string} Returns the string.
33793          */
33794
33795         function baseToString(value) {
33796           // Exit early for strings to avoid a performance hit in some environments.
33797           if (typeof value == 'string') {
33798             return value;
33799           }
33800
33801           if (isArray$1(value)) {
33802             // Recursively convert values (susceptible to call stack limits).
33803             return arrayMap(value, baseToString) + '';
33804           }
33805
33806           if (isSymbol(value)) {
33807             return symbolToString ? symbolToString.call(value) : '';
33808           }
33809
33810           var result = value + '';
33811           return result == '0' && 1 / value == -INFINITY ? '-0' : result;
33812         }
33813
33814         /** Used to match a single whitespace character. */
33815         var reWhitespace = /\s/;
33816         /**
33817          * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace
33818          * character of `string`.
33819          *
33820          * @private
33821          * @param {string} string The string to inspect.
33822          * @returns {number} Returns the index of the last non-whitespace character.
33823          */
33824
33825         function trimmedEndIndex(string) {
33826           var index = string.length;
33827
33828           while (index-- && reWhitespace.test(string.charAt(index))) {}
33829
33830           return index;
33831         }
33832
33833         /** Used to match leading whitespace. */
33834
33835         var reTrimStart = /^\s+/;
33836         /**
33837          * The base implementation of `_.trim`.
33838          *
33839          * @private
33840          * @param {string} string The string to trim.
33841          * @returns {string} Returns the trimmed string.
33842          */
33843
33844         function baseTrim(string) {
33845           return string ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') : string;
33846         }
33847
33848         /**
33849          * Checks if `value` is the
33850          * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
33851          * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
33852          *
33853          * @static
33854          * @memberOf _
33855          * @since 0.1.0
33856          * @category Lang
33857          * @param {*} value The value to check.
33858          * @returns {boolean} Returns `true` if `value` is an object, else `false`.
33859          * @example
33860          *
33861          * _.isObject({});
33862          * // => true
33863          *
33864          * _.isObject([1, 2, 3]);
33865          * // => true
33866          *
33867          * _.isObject(_.noop);
33868          * // => true
33869          *
33870          * _.isObject(null);
33871          * // => false
33872          */
33873         function isObject$2(value) {
33874           var type = _typeof(value);
33875
33876           return value != null && (type == 'object' || type == 'function');
33877         }
33878
33879         /** Used as references for various `Number` constants. */
33880
33881         var NAN = 0 / 0;
33882         /** Used to detect bad signed hexadecimal string values. */
33883
33884         var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
33885         /** Used to detect binary string values. */
33886
33887         var reIsBinary = /^0b[01]+$/i;
33888         /** Used to detect octal string values. */
33889
33890         var reIsOctal = /^0o[0-7]+$/i;
33891         /** Built-in method references without a dependency on `root`. */
33892
33893         var freeParseInt = parseInt;
33894         /**
33895          * Converts `value` to a number.
33896          *
33897          * @static
33898          * @memberOf _
33899          * @since 4.0.0
33900          * @category Lang
33901          * @param {*} value The value to process.
33902          * @returns {number} Returns the number.
33903          * @example
33904          *
33905          * _.toNumber(3.2);
33906          * // => 3.2
33907          *
33908          * _.toNumber(Number.MIN_VALUE);
33909          * // => 5e-324
33910          *
33911          * _.toNumber(Infinity);
33912          * // => Infinity
33913          *
33914          * _.toNumber('3.2');
33915          * // => 3.2
33916          */
33917
33918         function toNumber(value) {
33919           if (typeof value == 'number') {
33920             return value;
33921           }
33922
33923           if (isSymbol(value)) {
33924             return NAN;
33925           }
33926
33927           if (isObject$2(value)) {
33928             var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
33929             value = isObject$2(other) ? other + '' : other;
33930           }
33931
33932           if (typeof value != 'string') {
33933             return value === 0 ? value : +value;
33934           }
33935
33936           value = baseTrim(value);
33937           var isBinary = reIsBinary.test(value);
33938           return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value;
33939         }
33940
33941         /**
33942          * Converts `value` to a string. An empty string is returned for `null`
33943          * and `undefined` values. The sign of `-0` is preserved.
33944          *
33945          * @static
33946          * @memberOf _
33947          * @since 4.0.0
33948          * @category Lang
33949          * @param {*} value The value to convert.
33950          * @returns {string} Returns the converted string.
33951          * @example
33952          *
33953          * _.toString(null);
33954          * // => ''
33955          *
33956          * _.toString(-0);
33957          * // => '-0'
33958          *
33959          * _.toString([1, 2, 3]);
33960          * // => '1,2,3'
33961          */
33962
33963         function toString$3(value) {
33964           return value == null ? '' : baseToString(value);
33965         }
33966
33967         /**
33968          * The base implementation of `_.propertyOf` without support for deep paths.
33969          *
33970          * @private
33971          * @param {Object} object The object to query.
33972          * @returns {Function} Returns the new accessor function.
33973          */
33974         function basePropertyOf(object) {
33975           return function (key) {
33976             return object == null ? undefined : object[key];
33977           };
33978         }
33979
33980         /**
33981          * Gets the timestamp of the number of milliseconds that have elapsed since
33982          * the Unix epoch (1 January 1970 00:00:00 UTC).
33983          *
33984          * @static
33985          * @memberOf _
33986          * @since 2.4.0
33987          * @category Date
33988          * @returns {number} Returns the timestamp.
33989          * @example
33990          *
33991          * _.defer(function(stamp) {
33992          *   console.log(_.now() - stamp);
33993          * }, _.now());
33994          * // => Logs the number of milliseconds it took for the deferred invocation.
33995          */
33996
33997         var now = function now() {
33998           return root.Date.now();
33999         };
34000
34001         /** Error message constants. */
34002
34003         var FUNC_ERROR_TEXT$1 = 'Expected a function';
34004         /* Built-in method references for those with the same name as other `lodash` methods. */
34005
34006         var nativeMax = Math.max,
34007             nativeMin = Math.min;
34008         /**
34009          * Creates a debounced function that delays invoking `func` until after `wait`
34010          * milliseconds have elapsed since the last time the debounced function was
34011          * invoked. The debounced function comes with a `cancel` method to cancel
34012          * delayed `func` invocations and a `flush` method to immediately invoke them.
34013          * Provide `options` to indicate whether `func` should be invoked on the
34014          * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
34015          * with the last arguments provided to the debounced function. Subsequent
34016          * calls to the debounced function return the result of the last `func`
34017          * invocation.
34018          *
34019          * **Note:** If `leading` and `trailing` options are `true`, `func` is
34020          * invoked on the trailing edge of the timeout only if the debounced function
34021          * is invoked more than once during the `wait` timeout.
34022          *
34023          * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
34024          * until to the next tick, similar to `setTimeout` with a timeout of `0`.
34025          *
34026          * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
34027          * for details over the differences between `_.debounce` and `_.throttle`.
34028          *
34029          * @static
34030          * @memberOf _
34031          * @since 0.1.0
34032          * @category Function
34033          * @param {Function} func The function to debounce.
34034          * @param {number} [wait=0] The number of milliseconds to delay.
34035          * @param {Object} [options={}] The options object.
34036          * @param {boolean} [options.leading=false]
34037          *  Specify invoking on the leading edge of the timeout.
34038          * @param {number} [options.maxWait]
34039          *  The maximum time `func` is allowed to be delayed before it's invoked.
34040          * @param {boolean} [options.trailing=true]
34041          *  Specify invoking on the trailing edge of the timeout.
34042          * @returns {Function} Returns the new debounced function.
34043          * @example
34044          *
34045          * // Avoid costly calculations while the window size is in flux.
34046          * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
34047          *
34048          * // Invoke `sendMail` when clicked, debouncing subsequent calls.
34049          * jQuery(element).on('click', _.debounce(sendMail, 300, {
34050          *   'leading': true,
34051          *   'trailing': false
34052          * }));
34053          *
34054          * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
34055          * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
34056          * var source = new EventSource('/stream');
34057          * jQuery(source).on('message', debounced);
34058          *
34059          * // Cancel the trailing debounced invocation.
34060          * jQuery(window).on('popstate', debounced.cancel);
34061          */
34062
34063         function debounce(func, wait, options) {
34064           var lastArgs,
34065               lastThis,
34066               maxWait,
34067               result,
34068               timerId,
34069               lastCallTime,
34070               lastInvokeTime = 0,
34071               leading = false,
34072               maxing = false,
34073               trailing = true;
34074
34075           if (typeof func != 'function') {
34076             throw new TypeError(FUNC_ERROR_TEXT$1);
34077           }
34078
34079           wait = toNumber(wait) || 0;
34080
34081           if (isObject$2(options)) {
34082             leading = !!options.leading;
34083             maxing = 'maxWait' in options;
34084             maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
34085             trailing = 'trailing' in options ? !!options.trailing : trailing;
34086           }
34087
34088           function invokeFunc(time) {
34089             var args = lastArgs,
34090                 thisArg = lastThis;
34091             lastArgs = lastThis = undefined;
34092             lastInvokeTime = time;
34093             result = func.apply(thisArg, args);
34094             return result;
34095           }
34096
34097           function leadingEdge(time) {
34098             // Reset any `maxWait` timer.
34099             lastInvokeTime = time; // Start the timer for the trailing edge.
34100
34101             timerId = setTimeout(timerExpired, wait); // Invoke the leading edge.
34102
34103             return leading ? invokeFunc(time) : result;
34104           }
34105
34106           function remainingWait(time) {
34107             var timeSinceLastCall = time - lastCallTime,
34108                 timeSinceLastInvoke = time - lastInvokeTime,
34109                 timeWaiting = wait - timeSinceLastCall;
34110             return maxing ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting;
34111           }
34112
34113           function shouldInvoke(time) {
34114             var timeSinceLastCall = time - lastCallTime,
34115                 timeSinceLastInvoke = time - lastInvokeTime; // Either this is the first call, activity has stopped and we're at the
34116             // trailing edge, the system time has gone backwards and we're treating
34117             // it as the trailing edge, or we've hit the `maxWait` limit.
34118
34119             return lastCallTime === undefined || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait;
34120           }
34121
34122           function timerExpired() {
34123             var time = now();
34124
34125             if (shouldInvoke(time)) {
34126               return trailingEdge(time);
34127             } // Restart the timer.
34128
34129
34130             timerId = setTimeout(timerExpired, remainingWait(time));
34131           }
34132
34133           function trailingEdge(time) {
34134             timerId = undefined; // Only invoke if we have `lastArgs` which means `func` has been
34135             // debounced at least once.
34136
34137             if (trailing && lastArgs) {
34138               return invokeFunc(time);
34139             }
34140
34141             lastArgs = lastThis = undefined;
34142             return result;
34143           }
34144
34145           function cancel() {
34146             if (timerId !== undefined) {
34147               clearTimeout(timerId);
34148             }
34149
34150             lastInvokeTime = 0;
34151             lastArgs = lastCallTime = lastThis = timerId = undefined;
34152           }
34153
34154           function flush() {
34155             return timerId === undefined ? result : trailingEdge(now());
34156           }
34157
34158           function debounced() {
34159             var time = now(),
34160                 isInvoking = shouldInvoke(time);
34161             lastArgs = arguments;
34162             lastThis = this;
34163             lastCallTime = time;
34164
34165             if (isInvoking) {
34166               if (timerId === undefined) {
34167                 return leadingEdge(lastCallTime);
34168               }
34169
34170               if (maxing) {
34171                 // Handle invocations in a tight loop.
34172                 clearTimeout(timerId);
34173                 timerId = setTimeout(timerExpired, wait);
34174                 return invokeFunc(lastCallTime);
34175               }
34176             }
34177
34178             if (timerId === undefined) {
34179               timerId = setTimeout(timerExpired, wait);
34180             }
34181
34182             return result;
34183           }
34184
34185           debounced.cancel = cancel;
34186           debounced.flush = flush;
34187           return debounced;
34188         }
34189
34190         /** Used to map characters to HTML entities. */
34191
34192         var htmlEscapes = {
34193           '&': '&amp;',
34194           '<': '&lt;',
34195           '>': '&gt;',
34196           '"': '&quot;',
34197           "'": '&#39;'
34198         };
34199         /**
34200          * Used by `_.escape` to convert characters to HTML entities.
34201          *
34202          * @private
34203          * @param {string} chr The matched character to escape.
34204          * @returns {string} Returns the escaped character.
34205          */
34206
34207         var escapeHtmlChar = basePropertyOf(htmlEscapes);
34208
34209         /** Used to match HTML entities and HTML characters. */
34210
34211         var reUnescapedHtml = /[&<>"']/g,
34212             reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
34213         /**
34214          * Converts the characters "&", "<", ">", '"', and "'" in `string` to their
34215          * corresponding HTML entities.
34216          *
34217          * **Note:** No other characters are escaped. To escape additional
34218          * characters use a third-party library like [_he_](https://mths.be/he).
34219          *
34220          * Though the ">" character is escaped for symmetry, characters like
34221          * ">" and "/" don't need escaping in HTML and have no special meaning
34222          * unless they're part of a tag or unquoted attribute value. See
34223          * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
34224          * (under "semi-related fun fact") for more details.
34225          *
34226          * When working with HTML you should always
34227          * [quote attribute values](http://wonko.com/post/html-escaping) to reduce
34228          * XSS vectors.
34229          *
34230          * @static
34231          * @since 0.1.0
34232          * @memberOf _
34233          * @category String
34234          * @param {string} [string=''] The string to escape.
34235          * @returns {string} Returns the escaped string.
34236          * @example
34237          *
34238          * _.escape('fred, barney, & pebbles');
34239          * // => 'fred, barney, &amp; pebbles'
34240          */
34241
34242         function escape$4(string) {
34243           string = toString$3(string);
34244           return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string;
34245         }
34246
34247         /** Error message constants. */
34248
34249         var FUNC_ERROR_TEXT = 'Expected a function';
34250         /**
34251          * Creates a throttled function that only invokes `func` at most once per
34252          * every `wait` milliseconds. The throttled function comes with a `cancel`
34253          * method to cancel delayed `func` invocations and a `flush` method to
34254          * immediately invoke them. Provide `options` to indicate whether `func`
34255          * should be invoked on the leading and/or trailing edge of the `wait`
34256          * timeout. The `func` is invoked with the last arguments provided to the
34257          * throttled function. Subsequent calls to the throttled function return the
34258          * result of the last `func` invocation.
34259          *
34260          * **Note:** If `leading` and `trailing` options are `true`, `func` is
34261          * invoked on the trailing edge of the timeout only if the throttled function
34262          * is invoked more than once during the `wait` timeout.
34263          *
34264          * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
34265          * until to the next tick, similar to `setTimeout` with a timeout of `0`.
34266          *
34267          * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
34268          * for details over the differences between `_.throttle` and `_.debounce`.
34269          *
34270          * @static
34271          * @memberOf _
34272          * @since 0.1.0
34273          * @category Function
34274          * @param {Function} func The function to throttle.
34275          * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
34276          * @param {Object} [options={}] The options object.
34277          * @param {boolean} [options.leading=true]
34278          *  Specify invoking on the leading edge of the timeout.
34279          * @param {boolean} [options.trailing=true]
34280          *  Specify invoking on the trailing edge of the timeout.
34281          * @returns {Function} Returns the new throttled function.
34282          * @example
34283          *
34284          * // Avoid excessively updating the position while scrolling.
34285          * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
34286          *
34287          * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
34288          * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
34289          * jQuery(element).on('click', throttled);
34290          *
34291          * // Cancel the trailing throttled invocation.
34292          * jQuery(window).on('popstate', throttled.cancel);
34293          */
34294
34295         function throttle(func, wait, options) {
34296           var leading = true,
34297               trailing = true;
34298
34299           if (typeof func != 'function') {
34300             throw new TypeError(FUNC_ERROR_TEXT);
34301           }
34302
34303           if (isObject$2(options)) {
34304             leading = 'leading' in options ? !!options.leading : leading;
34305             trailing = 'trailing' in options ? !!options.trailing : trailing;
34306           }
34307
34308           return debounce(func, wait, {
34309             'leading': leading,
34310             'maxWait': wait,
34311             'trailing': trailing
34312           });
34313         }
34314
34315         var $$f = _export;
34316         var lastIndexOf = arrayLastIndexOf;
34317
34318         // `Array.prototype.lastIndexOf` method
34319         // https://tc39.es/ecma262/#sec-array.prototype.lastindexof
34320         // eslint-disable-next-line es/no-array-prototype-lastindexof -- required for testing
34321         $$f({ target: 'Array', proto: true, forced: lastIndexOf !== [].lastIndexOf }, {
34322           lastIndexOf: lastIndexOf
34323         });
34324
34325         var global$4 = global$1m;
34326         var isArray = isArray$8;
34327         var lengthOfArrayLike$1 = lengthOfArrayLike$g;
34328         var bind$3 = functionBindContext;
34329
34330         var TypeError$2 = global$4.TypeError;
34331
34332         // `FlattenIntoArray` abstract operation
34333         // https://tc39.github.io/proposal-flatMap/#sec-FlattenIntoArray
34334         var flattenIntoArray$1 = function (target, original, source, sourceLen, start, depth, mapper, thisArg) {
34335           var targetIndex = start;
34336           var sourceIndex = 0;
34337           var mapFn = mapper ? bind$3(mapper, thisArg) : false;
34338           var element, elementLen;
34339
34340           while (sourceIndex < sourceLen) {
34341             if (sourceIndex in source) {
34342               element = mapFn ? mapFn(source[sourceIndex], sourceIndex, original) : source[sourceIndex];
34343
34344               if (depth > 0 && isArray(element)) {
34345                 elementLen = lengthOfArrayLike$1(element);
34346                 targetIndex = flattenIntoArray$1(target, original, element, elementLen, targetIndex, depth - 1) - 1;
34347               } else {
34348                 if (targetIndex >= 0x1FFFFFFFFFFFFF) throw TypeError$2('Exceed the acceptable array length');
34349                 target[targetIndex] = element;
34350               }
34351
34352               targetIndex++;
34353             }
34354             sourceIndex++;
34355           }
34356           return targetIndex;
34357         };
34358
34359         var flattenIntoArray_1 = flattenIntoArray$1;
34360
34361         var $$e = _export;
34362         var flattenIntoArray = flattenIntoArray_1;
34363         var aCallable = aCallable$a;
34364         var toObject = toObject$j;
34365         var lengthOfArrayLike = lengthOfArrayLike$g;
34366         var arraySpeciesCreate = arraySpeciesCreate$4;
34367
34368         // `Array.prototype.flatMap` method
34369         // https://tc39.es/ecma262/#sec-array.prototype.flatmap
34370         $$e({ target: 'Array', proto: true }, {
34371           flatMap: function flatMap(callbackfn /* , thisArg */) {
34372             var O = toObject(this);
34373             var sourceLen = lengthOfArrayLike(O);
34374             var A;
34375             aCallable(callbackfn);
34376             A = arraySpeciesCreate(O, 0);
34377             A.length = flattenIntoArray(A, O, O, sourceLen, 0, 1, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
34378             return A;
34379           }
34380         });
34381
34382         // this method was added to unscopables after implementation
34383         // in popular engines, so it's moved to a separate module
34384         var addToUnscopables = addToUnscopables$6;
34385
34386         // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
34387         addToUnscopables('flatMap');
34388
34389         var $$d = _export;
34390         var uncurryThis$6 = functionUncurryThis;
34391         var getOwnPropertyDescriptor$1 = objectGetOwnPropertyDescriptor.f;
34392         var toLength$2 = toLength$c;
34393         var toString$2 = toString$k;
34394         var notARegExp$1 = notARegexp;
34395         var requireObjectCoercible$2 = requireObjectCoercible$e;
34396         var correctIsRegExpLogic$1 = correctIsRegexpLogic;
34397
34398         // eslint-disable-next-line es/no-string-prototype-endswith -- safe
34399         var un$EndsWith = uncurryThis$6(''.endsWith);
34400         var slice$2 = uncurryThis$6(''.slice);
34401         var min$1 = Math.min;
34402
34403         var CORRECT_IS_REGEXP_LOGIC$1 = correctIsRegExpLogic$1('endsWith');
34404         // https://github.com/zloirock/core-js/pull/702
34405         var MDN_POLYFILL_BUG$1 = !CORRECT_IS_REGEXP_LOGIC$1 && !!function () {
34406           var descriptor = getOwnPropertyDescriptor$1(String.prototype, 'endsWith');
34407           return descriptor && !descriptor.writable;
34408         }();
34409
34410         // `String.prototype.endsWith` method
34411         // https://tc39.es/ecma262/#sec-string.prototype.endswith
34412         $$d({ target: 'String', proto: true, forced: !MDN_POLYFILL_BUG$1 && !CORRECT_IS_REGEXP_LOGIC$1 }, {
34413           endsWith: function endsWith(searchString /* , endPosition = @length */) {
34414             var that = toString$2(requireObjectCoercible$2(this));
34415             notARegExp$1(searchString);
34416             var endPosition = arguments.length > 1 ? arguments[1] : undefined;
34417             var len = that.length;
34418             var end = endPosition === undefined ? len : min$1(toLength$2(endPosition), len);
34419             var search = toString$2(searchString);
34420             return un$EndsWith
34421               ? un$EndsWith(that, search, end)
34422               : slice$2(that, end - search.length, end) === search;
34423           }
34424         });
34425
34426         // https://github.com/tc39/proposal-string-pad-start-end
34427         var uncurryThis$5 = functionUncurryThis;
34428         var toLength$1 = toLength$c;
34429         var toString$1 = toString$k;
34430         var $repeat = stringRepeat;
34431         var requireObjectCoercible$1 = requireObjectCoercible$e;
34432
34433         var repeat$1 = uncurryThis$5($repeat);
34434         var stringSlice$2 = uncurryThis$5(''.slice);
34435         var ceil = Math.ceil;
34436
34437         // `String.prototype.{ padStart, padEnd }` methods implementation
34438         var createMethod = function (IS_END) {
34439           return function ($this, maxLength, fillString) {
34440             var S = toString$1(requireObjectCoercible$1($this));
34441             var intMaxLength = toLength$1(maxLength);
34442             var stringLength = S.length;
34443             var fillStr = fillString === undefined ? ' ' : toString$1(fillString);
34444             var fillLen, stringFiller;
34445             if (intMaxLength <= stringLength || fillStr == '') return S;
34446             fillLen = intMaxLength - stringLength;
34447             stringFiller = repeat$1(fillStr, ceil(fillLen / fillStr.length));
34448             if (stringFiller.length > fillLen) stringFiller = stringSlice$2(stringFiller, 0, fillLen);
34449             return IS_END ? S + stringFiller : stringFiller + S;
34450           };
34451         };
34452
34453         var stringPad = {
34454           // `String.prototype.padStart` method
34455           // https://tc39.es/ecma262/#sec-string.prototype.padstart
34456           start: createMethod(false),
34457           // `String.prototype.padEnd` method
34458           // https://tc39.es/ecma262/#sec-string.prototype.padend
34459           end: createMethod(true)
34460         };
34461
34462         // https://github.com/zloirock/core-js/issues/280
34463         var userAgent = engineUserAgent;
34464
34465         var stringPadWebkitBug = /Version\/10(?:\.\d+){1,2}(?: [\w./]+)?(?: Mobile\/\w+)? Safari\//.test(userAgent);
34466
34467         var $$c = _export;
34468         var $padEnd = stringPad.end;
34469         var WEBKIT_BUG$1 = stringPadWebkitBug;
34470
34471         // `String.prototype.padEnd` method
34472         // https://tc39.es/ecma262/#sec-string.prototype.padend
34473         $$c({ target: 'String', proto: true, forced: WEBKIT_BUG$1 }, {
34474           padEnd: function padEnd(maxLength /* , fillString = ' ' */) {
34475             return $padEnd(this, maxLength, arguments.length > 1 ? arguments[1] : undefined);
34476           }
34477         });
34478
34479         var $$b = _export;
34480         var $padStart = stringPad.start;
34481         var WEBKIT_BUG = stringPadWebkitBug;
34482
34483         // `String.prototype.padStart` method
34484         // https://tc39.es/ecma262/#sec-string.prototype.padstart
34485         $$b({ target: 'String', proto: true, forced: WEBKIT_BUG }, {
34486           padStart: function padStart(maxLength /* , fillString = ' ' */) {
34487             return $padStart(this, maxLength, arguments.length > 1 ? arguments[1] : undefined);
34488           }
34489         });
34490
34491         var $$a = _export;
34492         var $reduceRight = arrayReduce.right;
34493         var arrayMethodIsStrict = arrayMethodIsStrict$9;
34494         var CHROME_VERSION = engineV8Version;
34495         var IS_NODE = engineIsNode;
34496
34497         var STRICT_METHOD = arrayMethodIsStrict('reduceRight');
34498         // Chrome 80-82 has a critical bug
34499         // https://bugs.chromium.org/p/chromium/issues/detail?id=1049982
34500         var CHROME_BUG = !IS_NODE && CHROME_VERSION > 79 && CHROME_VERSION < 83;
34501
34502         // `Array.prototype.reduceRight` method
34503         // https://tc39.es/ecma262/#sec-array.prototype.reduceright
34504         $$a({ target: 'Array', proto: true, forced: !STRICT_METHOD || CHROME_BUG }, {
34505           reduceRight: function reduceRight(callbackfn /* , initialValue */) {
34506             return $reduceRight(this, callbackfn, arguments.length, arguments.length > 1 ? arguments[1] : undefined);
34507           }
34508         });
34509
34510         var $$9 = _export;
34511         var repeat = stringRepeat;
34512
34513         // `String.prototype.repeat` method
34514         // https://tc39.es/ecma262/#sec-string.prototype.repeat
34515         $$9({ target: 'String', proto: true }, {
34516           repeat: repeat
34517         });
34518
34519         var $$8 = _export;
34520         var uncurryThis$4 = functionUncurryThis;
34521         var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f;
34522         var toLength = toLength$c;
34523         var toString = toString$k;
34524         var notARegExp = notARegexp;
34525         var requireObjectCoercible = requireObjectCoercible$e;
34526         var correctIsRegExpLogic = correctIsRegexpLogic;
34527
34528         // eslint-disable-next-line es/no-string-prototype-startswith -- safe
34529         var un$StartsWith = uncurryThis$4(''.startsWith);
34530         var stringSlice$1 = uncurryThis$4(''.slice);
34531         var min = Math.min;
34532
34533         var CORRECT_IS_REGEXP_LOGIC = correctIsRegExpLogic('startsWith');
34534         // https://github.com/zloirock/core-js/pull/702
34535         var MDN_POLYFILL_BUG = !CORRECT_IS_REGEXP_LOGIC && !!function () {
34536           var descriptor = getOwnPropertyDescriptor(String.prototype, 'startsWith');
34537           return descriptor && !descriptor.writable;
34538         }();
34539
34540         // `String.prototype.startsWith` method
34541         // https://tc39.es/ecma262/#sec-string.prototype.startswith
34542         $$8({ target: 'String', proto: true, forced: !MDN_POLYFILL_BUG && !CORRECT_IS_REGEXP_LOGIC }, {
34543           startsWith: function startsWith(searchString /* , position = 0 */) {
34544             var that = toString(requireObjectCoercible(this));
34545             notARegExp(searchString);
34546             var index = toLength(min(arguments.length > 1 ? arguments[1] : undefined, that.length));
34547             var search = toString(searchString);
34548             return un$StartsWith
34549               ? un$StartsWith(that, search, index)
34550               : stringSlice$1(that, index, index + search.length) === search;
34551           }
34552         });
34553
34554         var $$7 = _export;
34555         var $trimEnd = stringTrim.end;
34556         var forcedStringTrimMethod$1 = stringTrimForced;
34557
34558         var FORCED$4 = forcedStringTrimMethod$1('trimEnd');
34559
34560         var trimEnd = FORCED$4 ? function trimEnd() {
34561           return $trimEnd(this);
34562         // eslint-disable-next-line es/no-string-prototype-trimstart-trimend -- safe
34563         } : ''.trimEnd;
34564
34565         // `String.prototype.{ trimEnd, trimRight }` methods
34566         // https://tc39.es/ecma262/#sec-string.prototype.trimend
34567         // https://tc39.es/ecma262/#String.prototype.trimright
34568         $$7({ target: 'String', proto: true, name: 'trimEnd', forced: FORCED$4 }, {
34569           trimEnd: trimEnd,
34570           trimRight: trimEnd
34571         });
34572
34573         var $$6 = _export;
34574         var $trimStart = stringTrim.start;
34575         var forcedStringTrimMethod = stringTrimForced;
34576
34577         var FORCED$3 = forcedStringTrimMethod('trimStart');
34578
34579         var trimStart = FORCED$3 ? function trimStart() {
34580           return $trimStart(this);
34581         // eslint-disable-next-line es/no-string-prototype-trimstart-trimend -- safe
34582         } : ''.trimStart;
34583
34584         // `String.prototype.{ trimStart, trimLeft }` methods
34585         // https://tc39.es/ecma262/#sec-string.prototype.trimstart
34586         // https://tc39.es/ecma262/#String.prototype.trimleft
34587         $$6({ target: 'String', proto: true, name: 'trimStart', forced: FORCED$3 }, {
34588           trimStart: trimStart,
34589           trimLeft: trimStart
34590         });
34591
34592         var _mainLocalizer = coreLocalizer(); // singleton
34593
34594
34595         var _t = _mainLocalizer.t;
34596         // coreLocalizer manages language and locale parameters including translated strings
34597         //
34598
34599         function coreLocalizer() {
34600           var localizer = {};
34601           var _dataLanguages = {}; // `_dataLocales` is an object containing all _supported_ locale codes -> language info.
34602           // * `rtl` - right-to-left or left-to-right text direction
34603           // * `pct` - the percent of strings translated; 1 = 100%, full coverage
34604           //
34605           // {
34606           // en: { rtl: false, pct: {…} },
34607           // de: { rtl: false, pct: {…} },
34608           // …
34609           // }
34610
34611           var _dataLocales = {}; // `localeStrings` is an object containing all _loaded_ locale codes -> string data.
34612           // {
34613           // en: { icons: {…}, toolbar: {…}, modes: {…}, operations: {…}, … },
34614           // de: { icons: {…}, toolbar: {…}, modes: {…}, operations: {…}, … },
34615           // …
34616           // }
34617
34618           var _localeStrings = {}; // the current locale
34619
34620           var _localeCode = 'en-US'; // `_localeCodes` must contain `_localeCode` first, optionally followed by fallbacks
34621
34622           var _localeCodes = ['en-US', 'en'];
34623           var _languageCode = 'en';
34624           var _textDirection = 'ltr';
34625           var _usesMetric = false;
34626           var _languageNames = {};
34627           var _scriptNames = {}; // getters for the current locale parameters
34628
34629           localizer.localeCode = function () {
34630             return _localeCode;
34631           };
34632
34633           localizer.localeCodes = function () {
34634             return _localeCodes;
34635           };
34636
34637           localizer.languageCode = function () {
34638             return _languageCode;
34639           };
34640
34641           localizer.textDirection = function () {
34642             return _textDirection;
34643           };
34644
34645           localizer.usesMetric = function () {
34646             return _usesMetric;
34647           };
34648
34649           localizer.languageNames = function () {
34650             return _languageNames;
34651           };
34652
34653           localizer.scriptNames = function () {
34654             return _scriptNames;
34655           }; // The client app may want to manually set the locale, regardless of the
34656           // settings provided by the browser
34657
34658
34659           var _preferredLocaleCodes = [];
34660
34661           localizer.preferredLocaleCodes = function (codes) {
34662             if (!arguments.length) return _preferredLocaleCodes;
34663
34664             if (typeof codes === 'string') {
34665               // be generous and accept delimited strings as input
34666               _preferredLocaleCodes = codes.split(/,|;| /gi).filter(Boolean);
34667             } else {
34668               _preferredLocaleCodes = codes;
34669             }
34670
34671             return localizer;
34672           };
34673
34674           var _loadPromise;
34675
34676           localizer.ensureLoaded = function () {
34677             if (_loadPromise) return _loadPromise;
34678             var filesToFetch = ['languages', // load the list of languages
34679             'locales' // load the list of supported locales
34680             ];
34681             var localeDirs = {
34682               general: 'locales',
34683               tagging: 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/translations'
34684             };
34685             var fileMap = _mainFileFetcher.fileMap();
34686
34687             for (var scopeId in localeDirs) {
34688               var key = "locales_index_".concat(scopeId);
34689
34690               if (!fileMap[key]) {
34691                 fileMap[key] = localeDirs[scopeId] + '/index.min.json';
34692               }
34693
34694               filesToFetch.push(key);
34695             }
34696
34697             return _loadPromise = Promise.all(filesToFetch.map(function (key) {
34698               return _mainFileFetcher.get(key);
34699             })).then(function (results) {
34700               _dataLanguages = results[0];
34701               _dataLocales = results[1];
34702               var indexes = results.slice(2);
34703
34704               var requestedLocales = (_preferredLocaleCodes || []).concat(utilDetect().browserLocales) // List of locales preferred by the browser in priority order.
34705               .concat(['en']); // fallback to English since it's the only guaranteed complete language
34706
34707
34708               _localeCodes = localesToUseFrom(requestedLocales);
34709               _localeCode = _localeCodes[0]; // Run iD in the highest-priority locale; the rest are fallbacks
34710
34711               var loadStringsPromises = [];
34712               indexes.forEach(function (index, i) {
34713                 // Will always return the index for `en` if nothing else
34714                 var fullCoverageIndex = _localeCodes.findIndex(function (locale) {
34715                   return index[locale] && index[locale].pct === 1;
34716                 }); // We only need to load locales up until we find one with full coverage
34717
34718
34719                 _localeCodes.slice(0, fullCoverageIndex + 1).forEach(function (code) {
34720                   var scopeId = Object.keys(localeDirs)[i];
34721                   var directory = Object.values(localeDirs)[i];
34722                   if (index[code]) loadStringsPromises.push(localizer.loadLocale(code, scopeId, directory));
34723                 });
34724               });
34725               return Promise.all(loadStringsPromises);
34726             }).then(function () {
34727               updateForCurrentLocale();
34728             })["catch"](function (err) {
34729               return console.error(err);
34730             }); // eslint-disable-line
34731           }; // Returns the locales from `requestedLocales` supported by iD that we should use
34732
34733
34734           function localesToUseFrom(requestedLocales) {
34735             var supportedLocales = _dataLocales;
34736             var toUse = [];
34737
34738             for (var i in requestedLocales) {
34739               var locale = requestedLocales[i];
34740               if (supportedLocales[locale]) toUse.push(locale);
34741
34742               if (locale.includes('-')) {
34743                 // Full locale ('es-ES'), add fallback to the base ('es')
34744                 var langPart = locale.split('-')[0];
34745                 if (supportedLocales[langPart]) toUse.push(langPart);
34746               }
34747             } // remove duplicates
34748
34749
34750             return utilArrayUniq(toUse);
34751           }
34752
34753           function updateForCurrentLocale() {
34754             if (!_localeCode) return;
34755             _languageCode = _localeCode.split('-')[0];
34756             var currentData = _dataLocales[_localeCode] || _dataLocales[_languageCode];
34757             var hash = utilStringQs(window.location.hash);
34758
34759             if (hash.rtl === 'true') {
34760               _textDirection = 'rtl';
34761             } else if (hash.rtl === 'false') {
34762               _textDirection = 'ltr';
34763             } else {
34764               _textDirection = currentData && currentData.rtl ? 'rtl' : 'ltr';
34765             }
34766
34767             var locale = _localeCode;
34768             if (locale.toLowerCase() === 'en-us') locale = 'en';
34769             _languageNames = _localeStrings.general[locale].languageNames;
34770             _scriptNames = _localeStrings.general[locale].scriptNames;
34771             _usesMetric = _localeCode.slice(-3).toLowerCase() !== '-us';
34772           }
34773           /* Locales */
34774           // Returns a Promise to load the strings for the requested locale
34775
34776
34777           localizer.loadLocale = function (locale, scopeId, directory) {
34778             // US English is the default
34779             if (locale.toLowerCase() === 'en-us') locale = 'en';
34780
34781             if (_localeStrings[scopeId] && _localeStrings[scopeId][locale]) {
34782               // already loaded
34783               return Promise.resolve(locale);
34784             }
34785
34786             var fileMap = _mainFileFetcher.fileMap();
34787             var key = "locale_".concat(scopeId, "_").concat(locale);
34788
34789             if (!fileMap[key]) {
34790               fileMap[key] = "".concat(directory, "/").concat(locale, ".min.json");
34791             }
34792
34793             return _mainFileFetcher.get(key).then(function (d) {
34794               if (!_localeStrings[scopeId]) _localeStrings[scopeId] = {};
34795               _localeStrings[scopeId][locale] = d[locale];
34796               return locale;
34797             });
34798           };
34799
34800           localizer.pluralRule = function (number) {
34801             return pluralRule(number, _localeCode);
34802           }; // Returns the plural rule for the given `number` with the given `localeCode`.
34803           // One of: `zero`, `one`, `two`, `few`, `many`, `other`
34804
34805
34806           function pluralRule(number, localeCode) {
34807             // modern browsers have this functionality built-in
34808             var rules = 'Intl' in window && Intl.PluralRules && new Intl.PluralRules(localeCode);
34809
34810             if (rules) {
34811               return rules.select(number);
34812             } // fallback to basic one/other, as in English
34813
34814
34815             if (number === 1) return 'one';
34816             return 'other';
34817           }
34818           /**
34819           * Try to find that string in `locale` or the current `_localeCode` matching
34820           * the given `stringId`. If no string can be found in the requested locale,
34821           * we'll recurse down all the `_localeCodes` until one is found.
34822           *
34823           * @param  {string}   stringId      string identifier
34824           * @param  {object?}  replacements  token replacements and default string
34825           * @param  {string?}  locale        locale to use (defaults to currentLocale)
34826           * @return {string?}  localized string
34827           */
34828
34829
34830           localizer.tInfo = function (origStringId, replacements, locale) {
34831             var stringId = origStringId.trim();
34832             var scopeId = 'general';
34833
34834             if (stringId[0] === '_') {
34835               var split = stringId.split('.');
34836               scopeId = split[0].slice(1);
34837               stringId = split.slice(1).join('.');
34838             }
34839
34840             locale = locale || _localeCode;
34841             var path = stringId.split('.').map(function (s) {
34842               return s.replace(/<TX_DOT>/g, '.');
34843             }).reverse();
34844             var stringsKey = locale; // US English is the default
34845
34846             if (stringsKey.toLowerCase() === 'en-us') stringsKey = 'en';
34847             var result = _localeStrings && _localeStrings[scopeId] && _localeStrings[scopeId][stringsKey];
34848
34849             while (result !== undefined && path.length) {
34850               result = result[path.pop()];
34851             }
34852
34853             if (result !== undefined) {
34854               if (replacements) {
34855                 if (_typeof(result) === 'object' && Object.keys(result).length) {
34856                   // If plural forms are provided, dig one level deeper based on the
34857                   // first numeric token replacement provided.
34858                   var number = Object.values(replacements).find(function (value) {
34859                     return typeof value === 'number';
34860                   });
34861
34862                   if (number !== undefined) {
34863                     var rule = pluralRule(number, locale);
34864
34865                     if (result[rule]) {
34866                       result = result[rule];
34867                     } else {
34868                       // We're pretty sure this should be a plural but no string
34869                       // could be found for the given rule. Just pick the first
34870                       // string and hope it makes sense.
34871                       result = Object.values(result)[0];
34872                     }
34873                   }
34874                 }
34875
34876                 if (typeof result === 'string') {
34877                   for (var key in replacements) {
34878                     var value = replacements[key];
34879
34880                     if (typeof value === 'number') {
34881                       if (value.toLocaleString) {
34882                         // format numbers for the locale
34883                         value = value.toLocaleString(locale, {
34884                           style: 'decimal',
34885                           useGrouping: true,
34886                           minimumFractionDigits: 0
34887                         });
34888                       } else {
34889                         value = value.toString();
34890                       }
34891                     }
34892
34893                     var token = "{".concat(key, "}");
34894                     var regex = new RegExp(token, 'g');
34895                     result = result.replace(regex, value);
34896                   }
34897                 }
34898               }
34899
34900               if (typeof result === 'string') {
34901                 // found a localized string!
34902                 return {
34903                   text: result,
34904                   locale: locale
34905                 };
34906               }
34907             } // no localized string found...
34908             // attempt to fallback to a lower-priority language
34909
34910
34911             var index = _localeCodes.indexOf(locale);
34912
34913             if (index >= 0 && index < _localeCodes.length - 1) {
34914               // eventually this will be 'en' or another locale with 100% coverage
34915               var fallback = _localeCodes[index + 1];
34916               return localizer.tInfo(origStringId, replacements, fallback);
34917             }
34918
34919             if (replacements && 'default' in replacements) {
34920               // Fallback to a default value if one is specified in `replacements`
34921               return {
34922                 text: replacements["default"],
34923                 locale: null
34924               };
34925             }
34926
34927             var missing = "Missing ".concat(locale, " translation: ").concat(origStringId);
34928             if (typeof console !== 'undefined') console.error(missing); // eslint-disable-line
34929
34930             return {
34931               text: missing,
34932               locale: 'en'
34933             };
34934           };
34935
34936           localizer.hasTextForStringId = function (stringId) {
34937             return !!localizer.tInfo(stringId, {
34938               "default": 'nothing found'
34939             }).locale;
34940           }; // Returns only the localized text, discarding the locale info
34941
34942
34943           localizer.t = function (stringId, replacements, locale) {
34944             return localizer.tInfo(stringId, replacements, locale).text;
34945           }; // Returns the localized text wrapped in an HTML element encoding the locale info
34946
34947           /**
34948            * @deprecated This method is considered deprecated. Instead, use the direct DOM manipulating
34949            *             method `t.append`.
34950            */
34951
34952
34953           localizer.t.html = function (stringId, replacements, locale) {
34954             // replacement string might be html unsafe, so we need to escape it except if it is explicitly marked as html code
34955             replacements = Object.assign({}, replacements);
34956
34957             for (var k in replacements) {
34958               if (typeof replacements[k] === 'string') {
34959                 replacements[k] = escape$4(replacements[k]);
34960               }
34961
34962               if (_typeof(replacements[k]) === 'object' && typeof replacements[k].html === 'string') {
34963                 replacements[k] = replacements[k].html;
34964               }
34965             }
34966
34967             var info = localizer.tInfo(stringId, replacements, locale); // text may be empty or undefined if `replacements.default` is
34968
34969             if (info.text) {
34970               return "<span class=\"localized-text\" lang=\"".concat(info.locale || 'und', "\">").concat(info.text, "</span>");
34971             } else {
34972               return '';
34973             }
34974           }; // Adds localized text wrapped as an HTML span element with locale info to the DOM
34975
34976
34977           localizer.t.append = function (stringId, replacements, locale) {
34978             return function (selection) {
34979               var info = localizer.tInfo(stringId, replacements, locale);
34980               return selection.append('span').attr('class', 'localized-text').attr('lang', info.locale || 'und').text((replacements && replacements.prefix || '') + info.text + (replacements && replacements.suffix || ''));
34981             };
34982           };
34983
34984           localizer.languageName = function (code, options) {
34985             if (_languageNames[code]) {
34986               // name in locale language
34987               // e.g. "German"
34988               return _languageNames[code];
34989             } // sometimes we only want the local name
34990
34991
34992             if (options && options.localOnly) return null;
34993             var langInfo = _dataLanguages[code];
34994
34995             if (langInfo) {
34996               if (langInfo.nativeName) {
34997                 // name in native language
34998                 // e.g. "Deutsch (de)"
34999                 return localizer.t('translate.language_and_code', {
35000                   language: langInfo.nativeName,
35001                   code: code
35002                 });
35003               } else if (langInfo.base && langInfo.script) {
35004                 var base = langInfo.base; // the code of the language this is based on
35005
35006                 if (_languageNames[base]) {
35007                   // base language name in locale language
35008                   var scriptCode = langInfo.script;
35009                   var script = _scriptNames[scriptCode] || scriptCode; // e.g. "Serbian (Cyrillic)"
35010
35011                   return localizer.t('translate.language_and_code', {
35012                     language: _languageNames[base],
35013                     code: script
35014                   });
35015                 } else if (_dataLanguages[base] && _dataLanguages[base].nativeName) {
35016                   // e.g. "српски (sr-Cyrl)"
35017                   return localizer.t('translate.language_and_code', {
35018                     language: _dataLanguages[base].nativeName,
35019                     code: code
35020                   });
35021                 }
35022               }
35023             }
35024
35025             return code; // if not found, use the code
35026           };
35027
35028           return localizer;
35029         }
35030
35031         // `presetCollection` is a wrapper around an `Array` of presets `collection`,
35032         // and decorated with some extra methods for searching and matching geometry
35033         //
35034
35035         function presetCollection(collection) {
35036           var MAXRESULTS = 50;
35037           var _this = {};
35038           var _memo = {};
35039           _this.collection = collection;
35040
35041           _this.item = function (id) {
35042             if (_memo[id]) return _memo[id];
35043
35044             var found = _this.collection.find(function (d) {
35045               return d.id === id;
35046             });
35047
35048             if (found) _memo[id] = found;
35049             return found;
35050           };
35051
35052           _this.index = function (id) {
35053             return _this.collection.findIndex(function (d) {
35054               return d.id === id;
35055             });
35056           };
35057
35058           _this.matchGeometry = function (geometry) {
35059             return presetCollection(_this.collection.filter(function (d) {
35060               return d.matchGeometry(geometry);
35061             }));
35062           };
35063
35064           _this.matchAllGeometry = function (geometries) {
35065             return presetCollection(_this.collection.filter(function (d) {
35066               return d && d.matchAllGeometry(geometries);
35067             }));
35068           };
35069
35070           _this.matchAnyGeometry = function (geometries) {
35071             return presetCollection(_this.collection.filter(function (d) {
35072               return geometries.some(function (geom) {
35073                 return d.matchGeometry(geom);
35074               });
35075             }));
35076           };
35077
35078           _this.fallback = function (geometry) {
35079             var id = geometry;
35080             if (id === 'vertex') id = 'point';
35081             return _this.item(id);
35082           };
35083
35084           _this.search = function (value, geometry, loc) {
35085             if (!value) return _this; // don't remove diacritical characters since we're assuming the user is being intentional
35086
35087             value = value.toLowerCase().trim(); // match at name beginning or just after a space (e.g. "office" -> match "Law Office")
35088
35089             function leading(a) {
35090               var index = a.indexOf(value);
35091               return index === 0 || a[index - 1] === ' ';
35092             } // match at name beginning only
35093
35094
35095             function leadingStrict(a) {
35096               var index = a.indexOf(value);
35097               return index === 0;
35098             }
35099
35100             function sortPresets(nameProp) {
35101               return function sortNames(a, b) {
35102                 var aCompare = a[nameProp]();
35103                 var bCompare = b[nameProp](); // priority if search string matches preset name exactly - #4325
35104
35105                 if (value === aCompare) return -1;
35106                 if (value === bCompare) return 1; // priority for higher matchScore
35107
35108                 var i = b.originalScore - a.originalScore;
35109                 if (i !== 0) return i; // priority if search string appears earlier in preset name
35110
35111                 i = aCompare.indexOf(value) - bCompare.indexOf(value);
35112                 if (i !== 0) return i; // priority for shorter preset names
35113
35114                 return aCompare.length - bCompare.length;
35115               };
35116             }
35117
35118             var pool = _this.collection;
35119
35120             if (Array.isArray(loc)) {
35121               var validLocations = _mainLocations.locationsAt(loc);
35122               pool = pool.filter(function (a) {
35123                 return !a.locationSetID || validLocations[a.locationSetID];
35124               });
35125             }
35126
35127             var searchable = pool.filter(function (a) {
35128               return a.searchable !== false && a.suggestion !== true;
35129             });
35130             var suggestions = pool.filter(function (a) {
35131               return a.suggestion === true;
35132             }); // matches value to preset.name
35133
35134             var leadingNames = searchable.filter(function (a) {
35135               return leading(a.searchName());
35136             }).sort(sortPresets('searchName')); // matches value to preset suggestion name
35137
35138             var leadingSuggestions = suggestions.filter(function (a) {
35139               return leadingStrict(a.searchName());
35140             }).sort(sortPresets('searchName'));
35141             var leadingNamesStripped = searchable.filter(function (a) {
35142               return leading(a.searchNameStripped());
35143             }).sort(sortPresets('searchNameStripped'));
35144             var leadingSuggestionsStripped = suggestions.filter(function (a) {
35145               return leadingStrict(a.searchNameStripped());
35146             }).sort(sortPresets('searchNameStripped')); // matches value to preset.terms values
35147
35148             var leadingTerms = searchable.filter(function (a) {
35149               return (a.terms() || []).some(leading);
35150             });
35151             var leadingSuggestionTerms = suggestions.filter(function (a) {
35152               return (a.terms() || []).some(leading);
35153             }); // matches value to preset.tags values
35154
35155             var leadingTagValues = searchable.filter(function (a) {
35156               return Object.values(a.tags || {}).filter(function (val) {
35157                 return val !== '*';
35158               }).some(leading);
35159             }); // finds close matches to value in preset.name
35160
35161             var similarName = searchable.map(function (a) {
35162               return {
35163                 preset: a,
35164                 dist: utilEditDistance(value, a.searchName())
35165               };
35166             }).filter(function (a) {
35167               return a.dist + Math.min(value.length - a.preset.searchName().length, 0) < 3;
35168             }).sort(function (a, b) {
35169               return a.dist - b.dist;
35170             }).map(function (a) {
35171               return a.preset;
35172             }); // finds close matches to value to preset suggestion name
35173
35174             var similarSuggestions = suggestions.map(function (a) {
35175               return {
35176                 preset: a,
35177                 dist: utilEditDistance(value, a.searchName())
35178               };
35179             }).filter(function (a) {
35180               return a.dist + Math.min(value.length - a.preset.searchName().length, 0) < 1;
35181             }).sort(function (a, b) {
35182               return a.dist - b.dist;
35183             }).map(function (a) {
35184               return a.preset;
35185             }); // finds close matches to value in preset.terms
35186
35187             var similarTerms = searchable.filter(function (a) {
35188               return (a.terms() || []).some(function (b) {
35189                 return utilEditDistance(value, b) + Math.min(value.length - b.length, 0) < 3;
35190               });
35191             });
35192             var results = leadingNames.concat(leadingSuggestions, leadingNamesStripped, leadingSuggestionsStripped, leadingTerms, leadingSuggestionTerms, leadingTagValues, similarName, similarSuggestions, similarTerms).slice(0, MAXRESULTS - 1);
35193
35194             if (geometry) {
35195               if (typeof geometry === 'string') {
35196                 results.push(_this.fallback(geometry));
35197               } else {
35198                 geometry.forEach(function (geom) {
35199                   return results.push(_this.fallback(geom));
35200                 });
35201               }
35202             }
35203
35204             return presetCollection(utilArrayUniq(results));
35205           };
35206
35207           return _this;
35208         }
35209
35210         // `presetCategory` builds a `presetCollection` of member presets,
35211         // decorated with some extra methods for searching and matching geometry
35212         //
35213
35214         function presetCategory(categoryID, category, allPresets) {
35215           var _this = Object.assign({}, category); // shallow copy
35216
35217
35218           var _searchName; // cache
35219
35220
35221           var _searchNameStripped; // cache
35222
35223
35224           _this.id = categoryID;
35225           _this.members = presetCollection((category.members || []).map(function (presetID) {
35226             return allPresets[presetID];
35227           }).filter(Boolean));
35228           _this.geometry = _this.members.collection.reduce(function (acc, preset) {
35229             for (var i in preset.geometry) {
35230               var geometry = preset.geometry[i];
35231
35232               if (acc.indexOf(geometry) === -1) {
35233                 acc.push(geometry);
35234               }
35235             }
35236
35237             return acc;
35238           }, []);
35239
35240           _this.matchGeometry = function (geom) {
35241             return _this.geometry.indexOf(geom) >= 0;
35242           };
35243
35244           _this.matchAllGeometry = function (geometries) {
35245             return _this.members.collection.some(function (preset) {
35246               return preset.matchAllGeometry(geometries);
35247             });
35248           };
35249
35250           _this.matchScore = function () {
35251             return -1;
35252           };
35253
35254           _this.name = function () {
35255             return _t("_tagging.presets.categories.".concat(categoryID, ".name"), {
35256               'default': categoryID
35257             });
35258           };
35259
35260           _this.nameLabel = function () {
35261             return _t.html("_tagging.presets.categories.".concat(categoryID, ".name"), {
35262               'default': categoryID
35263             });
35264           };
35265
35266           _this.terms = function () {
35267             return [];
35268           };
35269
35270           _this.searchName = function () {
35271             if (!_searchName) {
35272               _searchName = (_this.suggestion ? _this.originalName : _this.name()).toLowerCase();
35273             }
35274
35275             return _searchName;
35276           };
35277
35278           _this.searchNameStripped = function () {
35279             if (!_searchNameStripped) {
35280               _searchNameStripped = _this.searchName(); // split combined diacritical characters into their parts
35281
35282               if (_searchNameStripped.normalize) _searchNameStripped = _searchNameStripped.normalize('NFD'); // remove diacritics
35283
35284               _searchNameStripped = _searchNameStripped.replace(/[\u0300-\u036f]/g, '');
35285             }
35286
35287             return _searchNameStripped;
35288           };
35289
35290           return _this;
35291         }
35292
35293         // `presetField` decorates a given `field` Object
35294         // with some extra methods for searching and matching geometry
35295         //
35296
35297         function presetField(fieldID, field) {
35298           var _this = Object.assign({}, field); // shallow copy
35299
35300
35301           _this.id = fieldID; // for use in classes, element ids, css selectors
35302
35303           _this.safeid = utilSafeClassName(fieldID);
35304
35305           _this.matchGeometry = function (geom) {
35306             return !_this.geometry || _this.geometry.indexOf(geom) !== -1;
35307           };
35308
35309           _this.matchAllGeometry = function (geometries) {
35310             return !_this.geometry || geometries.every(function (geom) {
35311               return _this.geometry.indexOf(geom) !== -1;
35312             });
35313           };
35314
35315           _this.t = function (scope, options) {
35316             return _t("_tagging.presets.fields.".concat(fieldID, ".").concat(scope), options);
35317           };
35318
35319           _this.t.html = function (scope, options) {
35320             return _t.html("_tagging.presets.fields.".concat(fieldID, ".").concat(scope), options);
35321           };
35322
35323           _this.hasTextForStringId = function (scope) {
35324             return _mainLocalizer.hasTextForStringId("_tagging.presets.fields.".concat(fieldID, ".").concat(scope));
35325           };
35326
35327           _this.title = function () {
35328             return _this.overrideLabel || _this.t('label', {
35329               'default': fieldID
35330             });
35331           };
35332
35333           _this.label = function () {
35334             return _this.overrideLabel || _this.t.html('label', {
35335               'default': fieldID
35336             });
35337           };
35338
35339           var _placeholder = _this.placeholder;
35340
35341           _this.placeholder = function () {
35342             return _this.t('placeholder', {
35343               'default': _placeholder
35344             });
35345           };
35346
35347           _this.originalTerms = (_this.terms || []).join();
35348
35349           _this.terms = function () {
35350             return _this.t('terms', {
35351               'default': _this.originalTerms
35352             }).toLowerCase().trim().split(/\s*,+\s*/);
35353           };
35354
35355           _this.increment = _this.type === 'number' ? _this.increment || 1 : undefined;
35356           return _this;
35357         }
35358
35359         // `presetPreset` decorates a given `preset` Object
35360         // with some extra methods for searching and matching geometry
35361         //
35362
35363         function presetPreset(presetID, preset, addable, allFields, allPresets) {
35364           allFields = allFields || {};
35365           allPresets = allPresets || {};
35366
35367           var _this = Object.assign({}, preset); // shallow copy
35368
35369
35370           var _addable = addable || false;
35371
35372           var _resolvedFields; // cache
35373
35374
35375           var _resolvedMoreFields; // cache
35376
35377
35378           var _searchName; // cache
35379
35380
35381           var _searchNameStripped; // cache
35382
35383
35384           _this.id = presetID;
35385           _this.safeid = utilSafeClassName(presetID); // for use in css classes, selectors, element ids
35386
35387           _this.originalTerms = (_this.terms || []).join();
35388           _this.originalName = _this.name || '';
35389           _this.originalScore = _this.matchScore || 1;
35390           _this.originalReference = _this.reference || {};
35391           _this.originalFields = _this.fields || [];
35392           _this.originalMoreFields = _this.moreFields || [];
35393
35394           _this.fields = function () {
35395             return _resolvedFields || (_resolvedFields = resolve('fields'));
35396           };
35397
35398           _this.moreFields = function () {
35399             return _resolvedMoreFields || (_resolvedMoreFields = resolve('moreFields'));
35400           };
35401
35402           _this.resetFields = function () {
35403             return _resolvedFields = _resolvedMoreFields = null;
35404           };
35405
35406           _this.tags = _this.tags || {};
35407           _this.addTags = _this.addTags || _this.tags;
35408           _this.removeTags = _this.removeTags || _this.addTags;
35409           _this.geometry = _this.geometry || [];
35410
35411           _this.matchGeometry = function (geom) {
35412             return _this.geometry.indexOf(geom) >= 0;
35413           };
35414
35415           _this.matchAllGeometry = function (geoms) {
35416             return geoms.every(_this.matchGeometry);
35417           };
35418
35419           _this.matchScore = function (entityTags) {
35420             var tags = _this.tags;
35421             var seen = {};
35422             var score = 0; // match on tags
35423
35424             for (var k in tags) {
35425               seen[k] = true;
35426
35427               if (entityTags[k] === tags[k]) {
35428                 score += _this.originalScore;
35429               } else if (tags[k] === '*' && k in entityTags) {
35430                 score += _this.originalScore / 2;
35431               } else {
35432                 return -1;
35433               }
35434             } // boost score for additional matches in addTags - #6802
35435
35436
35437             var addTags = _this.addTags;
35438
35439             for (var _k in addTags) {
35440               if (!seen[_k] && entityTags[_k] === addTags[_k]) {
35441                 score += _this.originalScore;
35442               }
35443             }
35444
35445             return score;
35446           };
35447
35448           _this.t = function (scope, options) {
35449             var textID = "_tagging.presets.presets.".concat(presetID, ".").concat(scope);
35450             return _t(textID, options);
35451           };
35452
35453           _this.t.html = function (scope, options) {
35454             var textID = "_tagging.presets.presets.".concat(presetID, ".").concat(scope);
35455             return _t.html(textID, options);
35456           };
35457
35458           _this.name = function () {
35459             return _this.t('name', {
35460               'default': _this.originalName
35461             });
35462           };
35463
35464           _this.nameLabel = function () {
35465             return _this.t.html('name', {
35466               'default': _this.originalName
35467             });
35468           };
35469
35470           _this.subtitle = function () {
35471             if (_this.suggestion) {
35472               var path = presetID.split('/');
35473               path.pop(); // remove brand name
35474
35475               return _t('_tagging.presets.presets.' + path.join('/') + '.name');
35476             }
35477
35478             return null;
35479           };
35480
35481           _this.subtitleLabel = function () {
35482             if (_this.suggestion) {
35483               var path = presetID.split('/');
35484               path.pop(); // remove brand name
35485
35486               return _t.html('_tagging.presets.presets.' + path.join('/') + '.name');
35487             }
35488
35489             return null;
35490           };
35491
35492           _this.terms = function () {
35493             return _this.t('terms', {
35494               'default': _this.originalTerms
35495             }).toLowerCase().trim().split(/\s*,+\s*/);
35496           };
35497
35498           _this.searchName = function () {
35499             if (!_searchName) {
35500               _searchName = (_this.suggestion ? _this.originalName : _this.name()).toLowerCase();
35501             }
35502
35503             return _searchName;
35504           };
35505
35506           _this.searchNameStripped = function () {
35507             if (!_searchNameStripped) {
35508               _searchNameStripped = _this.searchName(); // split combined diacritical characters into their parts
35509
35510               if (_searchNameStripped.normalize) _searchNameStripped = _searchNameStripped.normalize('NFD'); // remove diacritics
35511
35512               _searchNameStripped = _searchNameStripped.replace(/[\u0300-\u036f]/g, '');
35513             }
35514
35515             return _searchNameStripped;
35516           };
35517
35518           _this.isFallback = function () {
35519             var tagCount = Object.keys(_this.tags).length;
35520             return tagCount === 0 || tagCount === 1 && _this.tags.hasOwnProperty('area');
35521           };
35522
35523           _this.addable = function (val) {
35524             if (!arguments.length) return _addable;
35525             _addable = val;
35526             return _this;
35527           };
35528
35529           _this.reference = function () {
35530             // Lookup documentation on Wikidata...
35531             var qid = _this.tags.wikidata || _this.tags['flag:wikidata'] || _this.tags['brand:wikidata'] || _this.tags['network:wikidata'] || _this.tags['operator:wikidata'];
35532
35533             if (qid) {
35534               return {
35535                 qid: qid
35536               };
35537             } // Lookup documentation on OSM Wikibase...
35538
35539
35540             var key = _this.originalReference.key || Object.keys(utilObjectOmit(_this.tags, 'name'))[0];
35541             var value = _this.originalReference.value || _this.tags[key];
35542
35543             if (value === '*') {
35544               return {
35545                 key: key
35546               };
35547             } else {
35548               return {
35549                 key: key,
35550                 value: value
35551               };
35552             }
35553           };
35554
35555           _this.unsetTags = function (tags, geometry, ignoringKeys, skipFieldDefaults) {
35556             // allow manually keeping some tags
35557             var removeTags = ignoringKeys ? utilObjectOmit(_this.removeTags, ignoringKeys) : _this.removeTags;
35558             tags = utilObjectOmit(tags, Object.keys(removeTags));
35559
35560             if (geometry && !skipFieldDefaults) {
35561               _this.fields().forEach(function (field) {
35562                 if (field.matchGeometry(geometry) && field.key && field["default"] === tags[field.key]) {
35563                   delete tags[field.key];
35564                 }
35565               });
35566             }
35567
35568             delete tags.area;
35569             return tags;
35570           };
35571
35572           _this.setTags = function (tags, geometry, skipFieldDefaults) {
35573             var addTags = _this.addTags;
35574             tags = Object.assign({}, tags); // shallow copy
35575
35576             for (var k in addTags) {
35577               if (addTags[k] === '*') {
35578                 // if this tag is ancillary, don't override an existing value since any value is okay
35579                 if (_this.tags[k] || !tags[k] || tags[k] === 'no') {
35580                   tags[k] = 'yes';
35581                 }
35582               } else {
35583                 tags[k] = addTags[k];
35584               }
35585             } // Add area=yes if necessary.
35586             // This is necessary if the geometry is already an area (e.g. user drew an area) AND any of:
35587             // 1. chosen preset could be either an area or a line (`barrier=city_wall`)
35588             // 2. chosen preset doesn't have a key in osmAreaKeys (`railway=station`)
35589
35590
35591             if (!addTags.hasOwnProperty('area')) {
35592               delete tags.area;
35593
35594               if (geometry === 'area') {
35595                 var needsAreaTag = true;
35596
35597                 if (_this.geometry.indexOf('line') === -1) {
35598                   for (var _k2 in addTags) {
35599                     if (_k2 in osmAreaKeys) {
35600                       needsAreaTag = false;
35601                       break;
35602                     }
35603                   }
35604                 }
35605
35606                 if (needsAreaTag) {
35607                   tags.area = 'yes';
35608                 }
35609               }
35610             }
35611
35612             if (geometry && !skipFieldDefaults) {
35613               _this.fields().forEach(function (field) {
35614                 if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field["default"]) {
35615                   tags[field.key] = field["default"];
35616                 }
35617               });
35618             }
35619
35620             return tags;
35621           }; // For a preset without fields, use the fields of the parent preset.
35622           // Replace {preset} placeholders with the fields of the specified presets.
35623
35624
35625           function resolve(which) {
35626             var fieldIDs = which === 'fields' ? _this.originalFields : _this.originalMoreFields;
35627             var resolved = [];
35628             fieldIDs.forEach(function (fieldID) {
35629               var match = fieldID.match(/\{(.*)\}/);
35630
35631               if (match !== null) {
35632                 // a presetID wrapped in braces {}
35633                 resolved = resolved.concat(inheritFields(match[1], which));
35634               } else if (allFields[fieldID]) {
35635                 // a normal fieldID
35636                 resolved.push(allFields[fieldID]);
35637               } else {
35638                 console.log("Cannot resolve \"".concat(fieldID, "\" found in ").concat(_this.id, ".").concat(which)); // eslint-disable-line no-console
35639               }
35640             }); // no fields resolved, so use the parent's if possible
35641
35642             if (!resolved.length) {
35643               var endIndex = _this.id.lastIndexOf('/');
35644
35645               var parentID = endIndex && _this.id.substring(0, endIndex);
35646
35647               if (parentID) {
35648                 resolved = inheritFields(parentID, which);
35649               }
35650             }
35651
35652             return utilArrayUniq(resolved); // returns an array of fields to inherit from the given presetID, if found
35653
35654             function inheritFields(presetID, which) {
35655               var parent = allPresets[presetID];
35656               if (!parent) return [];
35657
35658               if (which === 'fields') {
35659                 return parent.fields().filter(shouldInherit);
35660               } else if (which === 'moreFields') {
35661                 return parent.moreFields();
35662               } else {
35663                 return [];
35664               }
35665             } // Skip `fields` for the keys which define the preset.
35666             // These are usually `typeCombo` fields like `shop=*`
35667
35668
35669             function shouldInherit(f) {
35670               if (f.key && _this.tags[f.key] !== undefined && // inherit anyway if multiple values are allowed or just a checkbox
35671               f.type !== 'multiCombo' && f.type !== 'semiCombo' && f.type !== 'manyCombo' && f.type !== 'check') return false;
35672               return true;
35673             }
35674           }
35675
35676           return _this;
35677         }
35678
35679         var _mainPresetIndex = presetIndex(); // singleton
35680         // `presetIndex` wraps a `presetCollection`
35681         // with methods for loading new data and returning defaults
35682         //
35683
35684         function presetIndex() {
35685           var dispatch = dispatch$8('favoritePreset', 'recentsChange');
35686           var MAXRECENTS = 30; // seed the preset lists with geometry fallbacks
35687
35688           var POINT = presetPreset('point', {
35689             name: 'Point',
35690             tags: {},
35691             geometry: ['point', 'vertex'],
35692             matchScore: 0.1
35693           });
35694           var LINE = presetPreset('line', {
35695             name: 'Line',
35696             tags: {},
35697             geometry: ['line'],
35698             matchScore: 0.1
35699           });
35700           var AREA = presetPreset('area', {
35701             name: 'Area',
35702             tags: {
35703               area: 'yes'
35704             },
35705             geometry: ['area'],
35706             matchScore: 0.1
35707           });
35708           var RELATION = presetPreset('relation', {
35709             name: 'Relation',
35710             tags: {},
35711             geometry: ['relation'],
35712             matchScore: 0.1
35713           });
35714
35715           var _this = presetCollection([POINT, LINE, AREA, RELATION]);
35716
35717           var _presets = {
35718             point: POINT,
35719             line: LINE,
35720             area: AREA,
35721             relation: RELATION
35722           };
35723           var _defaults = {
35724             point: presetCollection([POINT]),
35725             vertex: presetCollection([POINT]),
35726             line: presetCollection([LINE]),
35727             area: presetCollection([AREA]),
35728             relation: presetCollection([RELATION])
35729           };
35730           var _fields = {};
35731           var _categories = {};
35732           var _universal = [];
35733           var _addablePresetIDs = null; // Set of preset IDs that the user can add
35734
35735           var _recents;
35736
35737           var _favorites; // Index of presets by (geometry, tag key).
35738
35739
35740           var _geometryIndex = {
35741             point: {},
35742             vertex: {},
35743             line: {},
35744             area: {},
35745             relation: {}
35746           };
35747
35748           var _loadPromise;
35749
35750           _this.ensureLoaded = function () {
35751             if (_loadPromise) return _loadPromise;
35752             return _loadPromise = Promise.all([_mainFileFetcher.get('preset_categories'), _mainFileFetcher.get('preset_defaults'), _mainFileFetcher.get('preset_presets'), _mainFileFetcher.get('preset_fields')]).then(function (vals) {
35753               _this.merge({
35754                 categories: vals[0],
35755                 defaults: vals[1],
35756                 presets: vals[2],
35757                 fields: vals[3]
35758               });
35759
35760               osmSetAreaKeys(_this.areaKeys());
35761               osmSetPointTags(_this.pointTags());
35762               osmSetVertexTags(_this.vertexTags());
35763             });
35764           }; // `merge` accepts an object containing new preset data (all properties optional):
35765           // {
35766           //   fields: {},
35767           //   presets: {},
35768           //   categories: {},
35769           //   defaults: {},
35770           //   featureCollection: {}
35771           //}
35772
35773
35774           _this.merge = function (d) {
35775             var newLocationSets = []; // Merge Fields
35776
35777             if (d.fields) {
35778               Object.keys(d.fields).forEach(function (fieldID) {
35779                 var f = d.fields[fieldID];
35780
35781                 if (f) {
35782                   // add or replace
35783                   f = presetField(fieldID, f);
35784                   if (f.locationSet) newLocationSets.push(f);
35785                   _fields[fieldID] = f;
35786                 } else {
35787                   // remove
35788                   delete _fields[fieldID];
35789                 }
35790               });
35791             } // Merge Presets
35792
35793
35794             if (d.presets) {
35795               Object.keys(d.presets).forEach(function (presetID) {
35796                 var p = d.presets[presetID];
35797
35798                 if (p) {
35799                   // add or replace
35800                   var isAddable = !_addablePresetIDs || _addablePresetIDs.has(presetID);
35801
35802                   p = presetPreset(presetID, p, isAddable, _fields, _presets);
35803                   if (p.locationSet) newLocationSets.push(p);
35804                   _presets[presetID] = p;
35805                 } else {
35806                   // remove (but not if it's a fallback)
35807                   var existing = _presets[presetID];
35808
35809                   if (existing && !existing.isFallback()) {
35810                     delete _presets[presetID];
35811                   }
35812                 }
35813               });
35814             } // Merge Categories
35815
35816
35817             if (d.categories) {
35818               Object.keys(d.categories).forEach(function (categoryID) {
35819                 var c = d.categories[categoryID];
35820
35821                 if (c) {
35822                   // add or replace
35823                   c = presetCategory(categoryID, c, _presets);
35824                   if (c.locationSet) newLocationSets.push(c);
35825                   _categories[categoryID] = c;
35826                 } else {
35827                   // remove
35828                   delete _categories[categoryID];
35829                 }
35830               });
35831             } // Rebuild _this.collection after changing presets and categories
35832
35833
35834             _this.collection = Object.values(_presets).concat(Object.values(_categories)); // Merge Defaults
35835
35836             if (d.defaults) {
35837               Object.keys(d.defaults).forEach(function (geometry) {
35838                 var def = d.defaults[geometry];
35839
35840                 if (Array.isArray(def)) {
35841                   // add or replace
35842                   _defaults[geometry] = presetCollection(def.map(function (id) {
35843                     return _presets[id] || _categories[id];
35844                   }).filter(Boolean));
35845                 } else {
35846                   // remove
35847                   delete _defaults[geometry];
35848                 }
35849               });
35850             } // Rebuild universal fields array
35851
35852
35853             _universal = Object.values(_fields).filter(function (field) {
35854               return field.universal;
35855             }); // Reset all the preset fields - they'll need to be resolved again
35856
35857             Object.values(_presets).forEach(function (preset) {
35858               return preset.resetFields();
35859             }); // Rebuild geometry index
35860
35861             _geometryIndex = {
35862               point: {},
35863               vertex: {},
35864               line: {},
35865               area: {},
35866               relation: {}
35867             };
35868
35869             _this.collection.forEach(function (preset) {
35870               (preset.geometry || []).forEach(function (geometry) {
35871                 var g = _geometryIndex[geometry];
35872
35873                 for (var key in preset.tags) {
35874                   g[key] = g[key] || {};
35875                   var value = preset.tags[key];
35876                   (g[key][value] = g[key][value] || []).push(preset);
35877                 }
35878               });
35879             }); // Merge Custom Features
35880
35881
35882             if (d.featureCollection && Array.isArray(d.featureCollection.features)) {
35883               _mainLocations.mergeCustomGeoJSON(d.featureCollection);
35884             } // Resolve all locationSet features.
35885
35886
35887             if (newLocationSets.length) {
35888               _mainLocations.mergeLocationSets(newLocationSets);
35889             }
35890
35891             return _this;
35892           };
35893
35894           _this.match = function (entity, resolver) {
35895             return resolver["transient"](entity, 'presetMatch', function () {
35896               var geometry = entity.geometry(resolver); // Treat entities on addr:interpolation lines as points, not vertices - #3241
35897
35898               if (geometry === 'vertex' && entity.isOnAddressLine(resolver)) {
35899                 geometry = 'point';
35900               }
35901
35902               var entityExtent = entity.extent(resolver);
35903               return _this.matchTags(entity.tags, geometry, entityExtent.center());
35904             });
35905           };
35906
35907           _this.matchTags = function (tags, geometry, loc) {
35908             var keyIndex = _geometryIndex[geometry];
35909             var bestScore = -1;
35910             var bestMatch;
35911             var matchCandidates = [];
35912
35913             for (var k in tags) {
35914               var indexMatches = [];
35915               var valueIndex = keyIndex[k];
35916               if (!valueIndex) continue;
35917               var keyValueMatches = valueIndex[tags[k]];
35918               if (keyValueMatches) indexMatches.push.apply(indexMatches, _toConsumableArray(keyValueMatches));
35919               var keyStarMatches = valueIndex['*'];
35920               if (keyStarMatches) indexMatches.push.apply(indexMatches, _toConsumableArray(keyStarMatches));
35921               if (indexMatches.length === 0) continue;
35922
35923               for (var i = 0; i < indexMatches.length; i++) {
35924                 var candidate = indexMatches[i];
35925                 var score = candidate.matchScore(tags);
35926
35927                 if (score === -1) {
35928                   continue;
35929                 }
35930
35931                 matchCandidates.push({
35932                   score: score,
35933                   candidate: candidate
35934                 });
35935
35936                 if (score > bestScore) {
35937                   bestScore = score;
35938                   bestMatch = candidate;
35939                 }
35940               }
35941             }
35942
35943             if (bestMatch && bestMatch.locationSetID && bestMatch.locationSetID !== '+[Q2]' && Array.isArray(loc)) {
35944               var validLocations = _mainLocations.locationsAt(loc);
35945
35946               if (!validLocations[bestMatch.locationSetID]) {
35947                 matchCandidates.sort(function (a, b) {
35948                   return a.score < b.score ? 1 : -1;
35949                 });
35950
35951                 for (var _i = 0; _i < matchCandidates.length; _i++) {
35952                   var candidateScore = matchCandidates[_i];
35953
35954                   if (!candidateScore.candidate.locationSetID || validLocations[candidateScore.candidate.locationSetID]) {
35955                     bestMatch = candidateScore.candidate;
35956                     bestScore = candidateScore.score;
35957                     break;
35958                   }
35959                 }
35960               }
35961             } // If any part of an address is present, allow fallback to "Address" preset - #4353
35962
35963
35964             if (!bestMatch || bestMatch.isFallback()) {
35965               for (var _k in tags) {
35966                 if (/^addr:/.test(_k) && keyIndex['addr:*'] && keyIndex['addr:*']['*']) {
35967                   bestMatch = keyIndex['addr:*']['*'][0];
35968                   break;
35969                 }
35970               }
35971             }
35972
35973             return bestMatch || _this.fallback(geometry);
35974           };
35975
35976           _this.allowsVertex = function (entity, resolver) {
35977             if (entity.type !== 'node') return false;
35978             if (Object.keys(entity.tags).length === 0) return true;
35979             return resolver["transient"](entity, 'vertexMatch', function () {
35980               // address lines allow vertices to act as standalone points
35981               if (entity.isOnAddressLine(resolver)) return true;
35982               var geometries = osmNodeGeometriesForTags(entity.tags);
35983               if (geometries.vertex) return true;
35984               if (geometries.point) return false; // allow vertices for unspecified points
35985
35986               return true;
35987             });
35988           }; // Because of the open nature of tagging, iD will never have a complete
35989           // list of tags used in OSM, so we want it to have logic like "assume
35990           // that a closed way with an amenity tag is an area, unless the amenity
35991           // is one of these specific types". This function computes a structure
35992           // that allows testing of such conditions, based on the presets designated
35993           // as as supporting (or not supporting) the area geometry.
35994           //
35995           // The returned object L is a keeplist/discardlist of tags. A closed way
35996           // with a tag (k, v) is considered to be an area if `k in L && !(v in L[k])`
35997           // (see `Way#isArea()`). In other words, the keys of L form the keeplist,
35998           // and the subkeys form the discardlist.
35999
36000
36001           _this.areaKeys = function () {
36002             // The ignore list is for keys that imply lines. (We always add `area=yes` for exceptions)
36003             var ignore = ['barrier', 'highway', 'footway', 'railway', 'junction', 'type'];
36004             var areaKeys = {}; // ignore name-suggestion-index and deprecated presets
36005
36006             var presets = _this.collection.filter(function (p) {
36007               return !p.suggestion && !p.replacement;
36008             }); // keeplist
36009
36010
36011             presets.forEach(function (p) {
36012               var keys = p.tags && Object.keys(p.tags);
36013               var key = keys && keys.length && keys[0]; // pick the first tag
36014
36015               if (!key) return;
36016               if (ignore.indexOf(key) !== -1) return;
36017
36018               if (p.geometry.indexOf('area') !== -1) {
36019                 // probably an area..
36020                 areaKeys[key] = areaKeys[key] || {};
36021               }
36022             }); // discardlist
36023
36024             presets.forEach(function (p) {
36025               var key;
36026
36027               for (key in p.addTags) {
36028                 // examine all addTags to get a better sense of what can be tagged on lines - #6800
36029                 var value = p.addTags[key];
36030
36031                 if (key in areaKeys && // probably an area...
36032                 p.geometry.indexOf('line') !== -1 && // but sometimes a line
36033                 value !== '*') {
36034                   areaKeys[key][value] = true;
36035                 }
36036               }
36037             });
36038             return areaKeys;
36039           };
36040
36041           _this.pointTags = function () {
36042             return _this.collection.reduce(function (pointTags, d) {
36043               // ignore name-suggestion-index, deprecated, and generic presets
36044               if (d.suggestion || d.replacement || d.searchable === false) return pointTags; // only care about the primary tag
36045
36046               var keys = d.tags && Object.keys(d.tags);
36047               var key = keys && keys.length && keys[0]; // pick the first tag
36048
36049               if (!key) return pointTags; // if this can be a point
36050
36051               if (d.geometry.indexOf('point') !== -1) {
36052                 pointTags[key] = pointTags[key] || {};
36053                 pointTags[key][d.tags[key]] = true;
36054               }
36055
36056               return pointTags;
36057             }, {});
36058           };
36059
36060           _this.vertexTags = function () {
36061             return _this.collection.reduce(function (vertexTags, d) {
36062               // ignore name-suggestion-index, deprecated, and generic presets
36063               if (d.suggestion || d.replacement || d.searchable === false) return vertexTags; // only care about the primary tag
36064
36065               var keys = d.tags && Object.keys(d.tags);
36066               var key = keys && keys.length && keys[0]; // pick the first tag
36067
36068               if (!key) return vertexTags; // if this can be a vertex
36069
36070               if (d.geometry.indexOf('vertex') !== -1) {
36071                 vertexTags[key] = vertexTags[key] || {};
36072                 vertexTags[key][d.tags[key]] = true;
36073               }
36074
36075               return vertexTags;
36076             }, {});
36077           };
36078
36079           _this.field = function (id) {
36080             return _fields[id];
36081           };
36082
36083           _this.universal = function () {
36084             return _universal;
36085           };
36086
36087           _this.defaults = function (geometry, n, startWithRecents, loc) {
36088             var recents = [];
36089
36090             if (startWithRecents) {
36091               recents = _this.recent().matchGeometry(geometry).collection.slice(0, 4);
36092             }
36093
36094             var defaults;
36095
36096             if (_addablePresetIDs) {
36097               defaults = Array.from(_addablePresetIDs).map(function (id) {
36098                 var preset = _this.item(id);
36099
36100                 if (preset && preset.matchGeometry(geometry)) return preset;
36101                 return null;
36102               }).filter(Boolean);
36103             } else {
36104               defaults = _defaults[geometry].collection.concat(_this.fallback(geometry));
36105             }
36106
36107             var result = presetCollection(utilArrayUniq(recents.concat(defaults)).slice(0, n - 1));
36108
36109             if (Array.isArray(loc)) {
36110               var validLocations = _mainLocations.locationsAt(loc);
36111               result.collection = result.collection.filter(function (a) {
36112                 return !a.locationSetID || validLocations[a.locationSetID];
36113               });
36114             }
36115
36116             return result;
36117           }; // pass a Set of addable preset ids
36118
36119
36120           _this.addablePresetIDs = function (val) {
36121             if (!arguments.length) return _addablePresetIDs; // accept and convert arrays
36122
36123             if (Array.isArray(val)) val = new Set(val);
36124             _addablePresetIDs = val;
36125
36126             if (_addablePresetIDs) {
36127               // reset all presets
36128               _this.collection.forEach(function (p) {
36129                 // categories aren't addable
36130                 if (p.addable) p.addable(_addablePresetIDs.has(p.id));
36131               });
36132             } else {
36133               _this.collection.forEach(function (p) {
36134                 if (p.addable) p.addable(true);
36135               });
36136             }
36137
36138             return _this;
36139           };
36140
36141           _this.recent = function () {
36142             return presetCollection(utilArrayUniq(_this.getRecents().map(function (d) {
36143               return d.preset;
36144             })));
36145           };
36146
36147           function RibbonItem(preset, source) {
36148             var item = {};
36149             item.preset = preset;
36150             item.source = source;
36151
36152             item.isFavorite = function () {
36153               return item.source === 'favorite';
36154             };
36155
36156             item.isRecent = function () {
36157               return item.source === 'recent';
36158             };
36159
36160             item.matches = function (preset) {
36161               return item.preset.id === preset.id;
36162             };
36163
36164             item.minified = function () {
36165               return {
36166                 pID: item.preset.id
36167               };
36168             };
36169
36170             return item;
36171           }
36172
36173           function ribbonItemForMinified(d, source) {
36174             if (d && d.pID) {
36175               var preset = _this.item(d.pID);
36176
36177               if (!preset) return null;
36178               return RibbonItem(preset, source);
36179             }
36180
36181             return null;
36182           }
36183
36184           _this.getGenericRibbonItems = function () {
36185             return ['point', 'line', 'area'].map(function (id) {
36186               return RibbonItem(_this.item(id), 'generic');
36187             });
36188           };
36189
36190           _this.getAddable = function () {
36191             if (!_addablePresetIDs) return [];
36192             return _addablePresetIDs.map(function (id) {
36193               var preset = _this.item(id);
36194
36195               if (preset) return RibbonItem(preset, 'addable');
36196               return null;
36197             }).filter(Boolean);
36198           };
36199
36200           function setRecents(items) {
36201             _recents = items;
36202             var minifiedItems = items.map(function (d) {
36203               return d.minified();
36204             });
36205             corePreferences('preset_recents', JSON.stringify(minifiedItems));
36206             dispatch.call('recentsChange');
36207           }
36208
36209           _this.getRecents = function () {
36210             if (!_recents) {
36211               // fetch from local storage
36212               _recents = (JSON.parse(corePreferences('preset_recents')) || []).reduce(function (acc, d) {
36213                 var item = ribbonItemForMinified(d, 'recent');
36214                 if (item && item.preset.addable()) acc.push(item);
36215                 return acc;
36216               }, []);
36217             }
36218
36219             return _recents;
36220           };
36221
36222           _this.addRecent = function (preset, besidePreset, after) {
36223             var recents = _this.getRecents();
36224
36225             var beforeItem = _this.recentMatching(besidePreset);
36226
36227             var toIndex = recents.indexOf(beforeItem);
36228             if (after) toIndex += 1;
36229             var newItem = RibbonItem(preset, 'recent');
36230             recents.splice(toIndex, 0, newItem);
36231             setRecents(recents);
36232           };
36233
36234           _this.removeRecent = function (preset) {
36235             var item = _this.recentMatching(preset);
36236
36237             if (item) {
36238               var items = _this.getRecents();
36239
36240               items.splice(items.indexOf(item), 1);
36241               setRecents(items);
36242             }
36243           };
36244
36245           _this.recentMatching = function (preset) {
36246             var items = _this.getRecents();
36247
36248             for (var i in items) {
36249               if (items[i].matches(preset)) {
36250                 return items[i];
36251               }
36252             }
36253
36254             return null;
36255           };
36256
36257           _this.moveItem = function (items, fromIndex, toIndex) {
36258             if (fromIndex === toIndex || fromIndex < 0 || toIndex < 0 || fromIndex >= items.length || toIndex >= items.length) return null;
36259             items.splice(toIndex, 0, items.splice(fromIndex, 1)[0]);
36260             return items;
36261           };
36262
36263           _this.moveRecent = function (item, beforeItem) {
36264             var recents = _this.getRecents();
36265
36266             var fromIndex = recents.indexOf(item);
36267             var toIndex = recents.indexOf(beforeItem);
36268
36269             var items = _this.moveItem(recents, fromIndex, toIndex);
36270
36271             if (items) setRecents(items);
36272           };
36273
36274           _this.setMostRecent = function (preset) {
36275             if (preset.searchable === false) return;
36276
36277             var items = _this.getRecents();
36278
36279             var item = _this.recentMatching(preset);
36280
36281             if (item) {
36282               items.splice(items.indexOf(item), 1);
36283             } else {
36284               item = RibbonItem(preset, 'recent');
36285             } // remove the last recent (first in, first out)
36286
36287
36288             while (items.length >= MAXRECENTS) {
36289               items.pop();
36290             } // prepend array
36291
36292
36293             items.unshift(item);
36294             setRecents(items);
36295           };
36296
36297           function setFavorites(items) {
36298             _favorites = items;
36299             var minifiedItems = items.map(function (d) {
36300               return d.minified();
36301             });
36302             corePreferences('preset_favorites', JSON.stringify(minifiedItems)); // call update
36303
36304             dispatch.call('favoritePreset');
36305           }
36306
36307           _this.addFavorite = function (preset, besidePreset, after) {
36308             var favorites = _this.getFavorites();
36309
36310             var beforeItem = _this.favoriteMatching(besidePreset);
36311
36312             var toIndex = favorites.indexOf(beforeItem);
36313             if (after) toIndex += 1;
36314             var newItem = RibbonItem(preset, 'favorite');
36315             favorites.splice(toIndex, 0, newItem);
36316             setFavorites(favorites);
36317           };
36318
36319           _this.toggleFavorite = function (preset) {
36320             var favs = _this.getFavorites();
36321
36322             var favorite = _this.favoriteMatching(preset);
36323
36324             if (favorite) {
36325               favs.splice(favs.indexOf(favorite), 1);
36326             } else {
36327               // only allow 10 favorites
36328               if (favs.length === 10) {
36329                 // remove the last favorite (last in, first out)
36330                 favs.pop();
36331               } // append array
36332
36333
36334               favs.push(RibbonItem(preset, 'favorite'));
36335             }
36336
36337             setFavorites(favs);
36338           };
36339
36340           _this.removeFavorite = function (preset) {
36341             var item = _this.favoriteMatching(preset);
36342
36343             if (item) {
36344               var items = _this.getFavorites();
36345
36346               items.splice(items.indexOf(item), 1);
36347               setFavorites(items);
36348             }
36349           };
36350
36351           _this.getFavorites = function () {
36352             if (!_favorites) {
36353               // fetch from local storage
36354               var rawFavorites = JSON.parse(corePreferences('preset_favorites'));
36355
36356               if (!rawFavorites) {
36357                 rawFavorites = [];
36358                 corePreferences('preset_favorites', JSON.stringify(rawFavorites));
36359               }
36360
36361               _favorites = rawFavorites.reduce(function (output, d) {
36362                 var item = ribbonItemForMinified(d, 'favorite');
36363                 if (item && item.preset.addable()) output.push(item);
36364                 return output;
36365               }, []);
36366             }
36367
36368             return _favorites;
36369           };
36370
36371           _this.favoriteMatching = function (preset) {
36372             var favs = _this.getFavorites();
36373
36374             for (var index in favs) {
36375               if (favs[index].matches(preset)) {
36376                 return favs[index];
36377               }
36378             }
36379
36380             return null;
36381           };
36382
36383           return utilRebind(_this, dispatch, 'on');
36384         }
36385
36386         function utilTagText(entity) {
36387           var obj = entity && entity.tags || {};
36388           return Object.keys(obj).map(function (k) {
36389             return k + '=' + obj[k];
36390           }).join(', ');
36391         }
36392         function utilTotalExtent(array, graph) {
36393           var extent = geoExtent();
36394           var val, entity;
36395
36396           for (var i = 0; i < array.length; i++) {
36397             val = array[i];
36398             entity = typeof val === 'string' ? graph.hasEntity(val) : val;
36399
36400             if (entity) {
36401               extent._extend(entity.extent(graph));
36402             }
36403           }
36404
36405           return extent;
36406         }
36407         function utilTagDiff(oldTags, newTags) {
36408           var tagDiff = [];
36409           var keys = utilArrayUnion(Object.keys(oldTags), Object.keys(newTags)).sort();
36410           keys.forEach(function (k) {
36411             var oldVal = oldTags[k];
36412             var newVal = newTags[k];
36413
36414             if ((oldVal || oldVal === '') && (newVal === undefined || newVal !== oldVal)) {
36415               tagDiff.push({
36416                 type: '-',
36417                 key: k,
36418                 oldVal: oldVal,
36419                 newVal: newVal,
36420                 display: '- ' + k + '=' + oldVal
36421               });
36422             }
36423
36424             if ((newVal || newVal === '') && (oldVal === undefined || newVal !== oldVal)) {
36425               tagDiff.push({
36426                 type: '+',
36427                 key: k,
36428                 oldVal: oldVal,
36429                 newVal: newVal,
36430                 display: '+ ' + k + '=' + newVal
36431               });
36432             }
36433           });
36434           return tagDiff;
36435         }
36436         function utilEntitySelector(ids) {
36437           return ids.length ? '.' + ids.join(',.') : 'nothing';
36438         } // returns an selector to select entity ids for:
36439         //  - entityIDs passed in
36440         //  - shallow descendant entityIDs for any of those entities that are relations
36441
36442         function utilEntityOrMemberSelector(ids, graph) {
36443           var seen = new Set(ids);
36444           ids.forEach(collectShallowDescendants);
36445           return utilEntitySelector(Array.from(seen));
36446
36447           function collectShallowDescendants(id) {
36448             var entity = graph.hasEntity(id);
36449             if (!entity || entity.type !== 'relation') return;
36450             entity.members.map(function (member) {
36451               return member.id;
36452             }).forEach(function (id) {
36453               seen.add(id);
36454             });
36455           }
36456         } // returns an selector to select entity ids for:
36457         //  - entityIDs passed in
36458         //  - deep descendant entityIDs for any of those entities that are relations
36459
36460         function utilEntityOrDeepMemberSelector(ids, graph) {
36461           return utilEntitySelector(utilEntityAndDeepMemberIDs(ids, graph));
36462         } // returns an selector to select entity ids for:
36463         //  - entityIDs passed in
36464         //  - deep descendant entityIDs for any of those entities that are relations
36465
36466         function utilEntityAndDeepMemberIDs(ids, graph) {
36467           var seen = new Set();
36468           ids.forEach(collectDeepDescendants);
36469           return Array.from(seen);
36470
36471           function collectDeepDescendants(id) {
36472             if (seen.has(id)) return;
36473             seen.add(id);
36474             var entity = graph.hasEntity(id);
36475             if (!entity || entity.type !== 'relation') return;
36476             entity.members.map(function (member) {
36477               return member.id;
36478             }).forEach(collectDeepDescendants); // recurse
36479           }
36480         } // returns an selector to select entity ids for:
36481         //  - deep descendant entityIDs for any of those entities that are relations
36482
36483         function utilDeepMemberSelector(ids, graph, skipMultipolgonMembers) {
36484           var idsSet = new Set(ids);
36485           var seen = new Set();
36486           var returners = new Set();
36487           ids.forEach(collectDeepDescendants);
36488           return utilEntitySelector(Array.from(returners));
36489
36490           function collectDeepDescendants(id) {
36491             if (seen.has(id)) return;
36492             seen.add(id);
36493
36494             if (!idsSet.has(id)) {
36495               returners.add(id);
36496             }
36497
36498             var entity = graph.hasEntity(id);
36499             if (!entity || entity.type !== 'relation') return;
36500             if (skipMultipolgonMembers && entity.isMultipolygon()) return;
36501             entity.members.map(function (member) {
36502               return member.id;
36503             }).forEach(collectDeepDescendants); // recurse
36504           }
36505         } // Adds or removes highlight styling for the specified entities
36506
36507         function utilHighlightEntities(ids, highlighted, context) {
36508           context.surface().selectAll(utilEntityOrDeepMemberSelector(ids, context.graph())).classed('highlighted', highlighted);
36509         } // returns an Array that is the union of:
36510         //  - nodes for any nodeIDs passed in
36511         //  - child nodes of any wayIDs passed in
36512         //  - descendant member and child nodes of relationIDs passed in
36513
36514         function utilGetAllNodes(ids, graph) {
36515           var seen = new Set();
36516           var nodes = new Set();
36517           ids.forEach(collectNodes);
36518           return Array.from(nodes);
36519
36520           function collectNodes(id) {
36521             if (seen.has(id)) return;
36522             seen.add(id);
36523             var entity = graph.hasEntity(id);
36524             if (!entity) return;
36525
36526             if (entity.type === 'node') {
36527               nodes.add(entity);
36528             } else if (entity.type === 'way') {
36529               entity.nodes.forEach(collectNodes);
36530             } else {
36531               entity.members.map(function (member) {
36532                 return member.id;
36533               }).forEach(collectNodes); // recurse
36534             }
36535           }
36536         }
36537         function utilDisplayName(entity) {
36538           var localizedNameKey = 'name:' + _mainLocalizer.languageCode().toLowerCase();
36539           var name = entity.tags[localizedNameKey] || entity.tags.name || '';
36540           if (name) return name;
36541           var tags = {
36542             direction: entity.tags.direction,
36543             from: entity.tags.from,
36544             network: entity.tags.cycle_network || entity.tags.network,
36545             ref: entity.tags.ref,
36546             to: entity.tags.to,
36547             via: entity.tags.via
36548           };
36549           var keyComponents = [];
36550
36551           if (tags.network) {
36552             keyComponents.push('network');
36553           }
36554
36555           if (tags.ref) {
36556             keyComponents.push('ref');
36557           } // Routes may need more disambiguation based on direction or destination
36558
36559
36560           if (entity.tags.route) {
36561             if (tags.direction) {
36562               keyComponents.push('direction');
36563             } else if (tags.from && tags.to) {
36564               keyComponents.push('from');
36565               keyComponents.push('to');
36566
36567               if (tags.via) {
36568                 keyComponents.push('via');
36569               }
36570             }
36571           }
36572
36573           if (keyComponents.length) {
36574             name = _t('inspector.display_name.' + keyComponents.join('_'), tags);
36575           }
36576
36577           return name;
36578         }
36579         function utilDisplayNameForPath(entity) {
36580           var name = utilDisplayName(entity);
36581           var isFirefox = utilDetect().browser.toLowerCase().indexOf('firefox') > -1;
36582           var isNewChromium = Number(utilDetect().version.split('.')[0]) >= 96.0;
36583
36584           if (!isFirefox && !isNewChromium && name && rtlRegex.test(name)) {
36585             name = fixRTLTextForSvg(name);
36586           }
36587
36588           return name;
36589         }
36590         function utilDisplayType(id) {
36591           return {
36592             n: _t('inspector.node'),
36593             w: _t('inspector.way'),
36594             r: _t('inspector.relation')
36595           }[id.charAt(0)];
36596         } // `utilDisplayLabel`
36597         // Returns a string suitable for display
36598         // By default returns something like name/ref, fallback to preset type, fallback to OSM type
36599         //   "Main Street" or "Tertiary Road"
36600         // If `verbose=true`, include both preset name and feature name.
36601         //   "Tertiary Road Main Street"
36602         //
36603
36604         function utilDisplayLabel(entity, graphOrGeometry, verbose) {
36605           var result;
36606           var displayName = utilDisplayName(entity);
36607           var preset = typeof graphOrGeometry === 'string' ? _mainPresetIndex.matchTags(entity.tags, graphOrGeometry) : _mainPresetIndex.match(entity, graphOrGeometry);
36608           var presetName = preset && (preset.suggestion ? preset.subtitle() : preset.name());
36609
36610           if (verbose) {
36611             result = [presetName, displayName].filter(Boolean).join(' ');
36612           } else {
36613             result = displayName || presetName;
36614           } // Fallback to the OSM type (node/way/relation)
36615
36616
36617           return result || utilDisplayType(entity.id);
36618         }
36619         function utilEntityRoot(entityType) {
36620           return {
36621             node: 'n',
36622             way: 'w',
36623             relation: 'r'
36624           }[entityType];
36625         } // Returns a single object containing the tags of all the given entities.
36626         // Example:
36627         // {
36628         //   highway: 'service',
36629         //   service: 'parking_aisle'
36630         // }
36631         //           +
36632         // {
36633         //   highway: 'service',
36634         //   service: 'driveway',
36635         //   width: '3'
36636         // }
36637         //           =
36638         // {
36639         //   highway: 'service',
36640         //   service: [ 'driveway', 'parking_aisle' ],
36641         //   width: [ '3', undefined ]
36642         // }
36643
36644         function utilCombinedTags(entityIDs, graph) {
36645           var tags = {};
36646           var tagCounts = {};
36647           var allKeys = new Set();
36648           var entities = entityIDs.map(function (entityID) {
36649             return graph.hasEntity(entityID);
36650           }).filter(Boolean); // gather the aggregate keys
36651
36652           entities.forEach(function (entity) {
36653             var keys = Object.keys(entity.tags).filter(Boolean);
36654             keys.forEach(function (key) {
36655               allKeys.add(key);
36656             });
36657           });
36658           entities.forEach(function (entity) {
36659             allKeys.forEach(function (key) {
36660               var value = entity.tags[key]; // purposely allow `undefined`
36661
36662               if (!tags.hasOwnProperty(key)) {
36663                 // first value, set as raw
36664                 tags[key] = value;
36665               } else {
36666                 if (!Array.isArray(tags[key])) {
36667                   if (tags[key] !== value) {
36668                     // first alternate value, replace single value with array
36669                     tags[key] = [tags[key], value];
36670                   }
36671                 } else {
36672                   // type is array
36673                   if (tags[key].indexOf(value) === -1) {
36674                     // subsequent alternate value, add to array
36675                     tags[key].push(value);
36676                   }
36677                 }
36678               }
36679
36680               var tagHash = key + '=' + value;
36681               if (!tagCounts[tagHash]) tagCounts[tagHash] = 0;
36682               tagCounts[tagHash] += 1;
36683             });
36684           });
36685
36686           for (var key in tags) {
36687             if (!Array.isArray(tags[key])) continue; // sort values by frequency then alphabetically
36688
36689             tags[key] = tags[key].sort(function (val1, val2) {
36690               var key = key; // capture
36691
36692               var count2 = tagCounts[key + '=' + val2];
36693               var count1 = tagCounts[key + '=' + val1];
36694
36695               if (count2 !== count1) {
36696                 return count2 - count1;
36697               }
36698
36699               if (val2 && val1) {
36700                 return val1.localeCompare(val2);
36701               }
36702
36703               return val1 ? 1 : -1;
36704             });
36705           }
36706
36707           return tags;
36708         }
36709         function utilStringQs(str) {
36710           var i = 0; // advance past any leading '?' or '#' characters
36711
36712           while (i < str.length && (str[i] === '?' || str[i] === '#')) {
36713             i++;
36714           }
36715
36716           str = str.slice(i);
36717           return str.split('&').reduce(function (obj, pair) {
36718             var parts = pair.split('=');
36719
36720             if (parts.length === 2) {
36721               obj[parts[0]] = null === parts[1] ? '' : decodeURIComponent(parts[1]);
36722             }
36723
36724             return obj;
36725           }, {});
36726         }
36727         function utilQsString(obj, noencode) {
36728           // encode everything except special characters used in certain hash parameters:
36729           // "/" in map states, ":", ",", {" and "}" in background
36730           function softEncode(s) {
36731             return encodeURIComponent(s).replace(/(%2F|%3A|%2C|%7B|%7D)/g, decodeURIComponent);
36732           }
36733
36734           return Object.keys(obj).sort().map(function (key) {
36735             return encodeURIComponent(key) + '=' + (noencode ? softEncode(obj[key]) : encodeURIComponent(obj[key]));
36736           }).join('&');
36737         }
36738         function utilPrefixDOMProperty(property) {
36739           var prefixes = ['webkit', 'ms', 'moz', 'o'];
36740           var i = -1;
36741           var n = prefixes.length;
36742           var s = document.body;
36743           if (property in s) return property;
36744           property = property.substr(0, 1).toUpperCase() + property.substr(1);
36745
36746           while (++i < n) {
36747             if (prefixes[i] + property in s) {
36748               return prefixes[i] + property;
36749             }
36750           }
36751
36752           return false;
36753         }
36754         function utilPrefixCSSProperty(property) {
36755           var prefixes = ['webkit', 'ms', 'Moz', 'O'];
36756           var i = -1;
36757           var n = prefixes.length;
36758           var s = document.body.style;
36759
36760           if (property.toLowerCase() in s) {
36761             return property.toLowerCase();
36762           }
36763
36764           while (++i < n) {
36765             if (prefixes[i] + property in s) {
36766               return '-' + prefixes[i].toLowerCase() + property.replace(/([A-Z])/g, '-$1').toLowerCase();
36767             }
36768           }
36769
36770           return false;
36771         }
36772         var transformProperty;
36773         function utilSetTransform(el, x, y, scale) {
36774           var prop = transformProperty = transformProperty || utilPrefixCSSProperty('Transform');
36775           var translate = utilDetect().opera ? 'translate(' + x + 'px,' + y + 'px)' : 'translate3d(' + x + 'px,' + y + 'px,0)';
36776           return el.style(prop, translate + (scale ? ' scale(' + scale + ')' : ''));
36777         } // Calculates Levenshtein distance between two strings
36778         // see:  https://en.wikipedia.org/wiki/Levenshtein_distance
36779         // first converts the strings to lowercase and replaces diacritic marks with ascii equivalents.
36780
36781         function utilEditDistance(a, b) {
36782           a = remove$6(a.toLowerCase());
36783           b = remove$6(b.toLowerCase());
36784           if (a.length === 0) return b.length;
36785           if (b.length === 0) return a.length;
36786           var matrix = [];
36787           var i, j;
36788
36789           for (i = 0; i <= b.length; i++) {
36790             matrix[i] = [i];
36791           }
36792
36793           for (j = 0; j <= a.length; j++) {
36794             matrix[0][j] = j;
36795           }
36796
36797           for (i = 1; i <= b.length; i++) {
36798             for (j = 1; j <= a.length; j++) {
36799               if (b.charAt(i - 1) === a.charAt(j - 1)) {
36800                 matrix[i][j] = matrix[i - 1][j - 1];
36801               } else {
36802                 matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution
36803                 Math.min(matrix[i][j - 1] + 1, // insertion
36804                 matrix[i - 1][j] + 1)); // deletion
36805               }
36806             }
36807           }
36808
36809           return matrix[b.length][a.length];
36810         } // a d3.mouse-alike which
36811         // 1. Only works on HTML elements, not SVG
36812         // 2. Does not cause style recalculation
36813
36814         function utilFastMouse(container) {
36815           var rect = container.getBoundingClientRect();
36816           var rectLeft = rect.left;
36817           var rectTop = rect.top;
36818           var clientLeft = +container.clientLeft;
36819           var clientTop = +container.clientTop;
36820           return function (e) {
36821             return [e.clientX - rectLeft - clientLeft, e.clientY - rectTop - clientTop];
36822           };
36823         }
36824         function utilAsyncMap(inputs, func, callback) {
36825           var remaining = inputs.length;
36826           var results = [];
36827           var errors = [];
36828           inputs.forEach(function (d, i) {
36829             func(d, function done(err, data) {
36830               errors[i] = err;
36831               results[i] = data;
36832               remaining--;
36833               if (!remaining) callback(errors, results);
36834             });
36835           });
36836         } // wraps an index to an interval [0..length-1]
36837
36838         function utilWrap(index, length) {
36839           if (index < 0) {
36840             index += Math.ceil(-index / length) * length;
36841           }
36842
36843           return index % length;
36844         }
36845         /**
36846          * a replacement for functor
36847          *
36848          * @param {*} value any value
36849          * @returns {Function} a function that returns that value or the value if it's a function
36850          */
36851
36852         function utilFunctor(value) {
36853           if (typeof value === 'function') return value;
36854           return function () {
36855             return value;
36856           };
36857         }
36858         function utilNoAuto(selection) {
36859           var isText = selection.size() && selection.node().tagName.toLowerCase() === 'textarea';
36860           return selection // assign 'new-password' even for non-password fields to prevent browsers (Chrome) ignoring 'off'
36861           .attr('autocomplete', 'new-password').attr('autocorrect', 'off').attr('autocapitalize', 'off').attr('spellcheck', isText ? 'true' : 'false');
36862         } // https://stackoverflow.com/questions/194846/is-there-any-kind-of-hash-code-function-in-javascript
36863         // https://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/
36864
36865         function utilHashcode(str) {
36866           var hash = 0;
36867
36868           if (str.length === 0) {
36869             return hash;
36870           }
36871
36872           for (var i = 0; i < str.length; i++) {
36873             var _char = str.charCodeAt(i);
36874
36875             hash = (hash << 5) - hash + _char;
36876             hash = hash & hash; // Convert to 32bit integer
36877           }
36878
36879           return hash;
36880         } // Returns version of `str` with all runs of special characters replaced by `_`;
36881         // suitable for HTML ids, classes, selectors, etc.
36882
36883         function utilSafeClassName(str) {
36884           return str.toLowerCase().replace(/[^a-z0-9]+/g, '_');
36885         } // Returns string based on `val` that is highly unlikely to collide with an id
36886         // used previously or that's present elsewhere in the document. Useful for preventing
36887         // browser-provided autofills or when embedding iD on pages with unknown elements.
36888
36889         function utilUniqueDomId(val) {
36890           return 'ideditor-' + utilSafeClassName(val.toString()) + '-' + new Date().getTime().toString();
36891         } // Returns the length of `str` in unicode characters. This can be less than
36892         // `String.length()` since a single unicode character can be composed of multiple
36893         // JavaScript UTF-16 code units.
36894
36895         function utilUnicodeCharsCount(str) {
36896           // Native ES2015 implementations of `Array.from` split strings into unicode characters
36897           return Array.from(str).length;
36898         } // Returns a new string representing `str` cut from its start to `limit` length
36899         // in unicode characters. Note that this runs the risk of splitting graphemes.
36900
36901         function utilUnicodeCharsTruncated(str, limit) {
36902           return Array.from(str).slice(0, limit).join('');
36903         }
36904
36905         function toNumericID(id) {
36906           var match = id.match(/^[cnwr](-?\d+)$/);
36907
36908           if (match) {
36909             return parseInt(match[1], 10);
36910           }
36911
36912           return NaN;
36913         }
36914
36915         function compareNumericIDs(left, right) {
36916           if (isNaN(left) && isNaN(right)) return -1;
36917           if (isNaN(left)) return 1;
36918           if (isNaN(right)) return -1;
36919           if (Math.sign(left) !== Math.sign(right)) return -Math.sign(left);
36920           if (Math.sign(left) < 0) return Math.sign(right - left);
36921           return Math.sign(left - right);
36922         } // Returns -1 if the first parameter ID is older than the second,
36923         // 1 if the second parameter is older, 0 if they are the same.
36924         // If both IDs are test IDs, the function returns -1.
36925
36926
36927         function utilCompareIDs(left, right) {
36928           return compareNumericIDs(toNumericID(left), toNumericID(right));
36929         } // Returns the chronologically oldest ID in the list.
36930         // Database IDs (with positive numbers) before editor ones (with negative numbers).
36931         // Among each category, the closest number to 0 is the oldest.
36932         // Test IDs (any string that does not conform to OSM's ID scheme) are taken last.
36933
36934         function utilOldestID(ids) {
36935           if (ids.length === 0) {
36936             return undefined;
36937           }
36938
36939           var oldestIDIndex = 0;
36940           var oldestID = toNumericID(ids[0]);
36941
36942           for (var i = 1; i < ids.length; i++) {
36943             var num = toNumericID(ids[i]);
36944
36945             if (compareNumericIDs(oldestID, num) === 1) {
36946               oldestIDIndex = i;
36947               oldestID = num;
36948             }
36949           }
36950
36951           return ids[oldestIDIndex];
36952         }
36953
36954         function osmEntity(attrs) {
36955           // For prototypal inheritance.
36956           if (this instanceof osmEntity) return; // Create the appropriate subtype.
36957
36958           if (attrs && attrs.type) {
36959             return osmEntity[attrs.type].apply(this, arguments);
36960           } else if (attrs && attrs.id) {
36961             return osmEntity[osmEntity.id.type(attrs.id)].apply(this, arguments);
36962           } // Initialize a generic Entity (used only in tests).
36963
36964
36965           return new osmEntity().initialize(arguments);
36966         }
36967
36968         osmEntity.id = function (type) {
36969           return osmEntity.id.fromOSM(type, osmEntity.id.next[type]--);
36970         };
36971
36972         osmEntity.id.next = {
36973           changeset: -1,
36974           node: -1,
36975           way: -1,
36976           relation: -1
36977         };
36978
36979         osmEntity.id.fromOSM = function (type, id) {
36980           return type[0] + id;
36981         };
36982
36983         osmEntity.id.toOSM = function (id) {
36984           var match = id.match(/^[cnwr](-?\d+)$/);
36985
36986           if (match) {
36987             return match[1];
36988           }
36989
36990           return '';
36991         };
36992
36993         osmEntity.id.type = function (id) {
36994           return {
36995             'c': 'changeset',
36996             'n': 'node',
36997             'w': 'way',
36998             'r': 'relation'
36999           }[id[0]];
37000         }; // A function suitable for use as the second argument to d3.selection#data().
37001
37002
37003         osmEntity.key = function (entity) {
37004           return entity.id + 'v' + (entity.v || 0);
37005         };
37006
37007         var _deprecatedTagValuesByKey;
37008
37009         osmEntity.deprecatedTagValuesByKey = function (dataDeprecated) {
37010           if (!_deprecatedTagValuesByKey) {
37011             _deprecatedTagValuesByKey = {};
37012             dataDeprecated.forEach(function (d) {
37013               var oldKeys = Object.keys(d.old);
37014
37015               if (oldKeys.length === 1) {
37016                 var oldKey = oldKeys[0];
37017                 var oldValue = d.old[oldKey];
37018
37019                 if (oldValue !== '*') {
37020                   if (!_deprecatedTagValuesByKey[oldKey]) {
37021                     _deprecatedTagValuesByKey[oldKey] = [oldValue];
37022                   } else {
37023                     _deprecatedTagValuesByKey[oldKey].push(oldValue);
37024                   }
37025                 }
37026               }
37027             });
37028           }
37029
37030           return _deprecatedTagValuesByKey;
37031         };
37032
37033         osmEntity.prototype = {
37034           tags: {},
37035           initialize: function initialize(sources) {
37036             for (var i = 0; i < sources.length; ++i) {
37037               var source = sources[i];
37038
37039               for (var prop in source) {
37040                 if (Object.prototype.hasOwnProperty.call(source, prop)) {
37041                   if (source[prop] === undefined) {
37042                     delete this[prop];
37043                   } else {
37044                     this[prop] = source[prop];
37045                   }
37046                 }
37047               }
37048             }
37049
37050             if (!this.id && this.type) {
37051               this.id = osmEntity.id(this.type);
37052             }
37053
37054             if (!this.hasOwnProperty('visible')) {
37055               this.visible = true;
37056             }
37057
37058             if (debug) {
37059               Object.freeze(this);
37060               Object.freeze(this.tags);
37061               if (this.loc) Object.freeze(this.loc);
37062               if (this.nodes) Object.freeze(this.nodes);
37063               if (this.members) Object.freeze(this.members);
37064             }
37065
37066             return this;
37067           },
37068           copy: function copy(resolver, copies) {
37069             if (copies[this.id]) return copies[this.id];
37070             var copy = osmEntity(this, {
37071               id: undefined,
37072               user: undefined,
37073               version: undefined
37074             });
37075             copies[this.id] = copy;
37076             return copy;
37077           },
37078           osmId: function osmId() {
37079             return osmEntity.id.toOSM(this.id);
37080           },
37081           isNew: function isNew() {
37082             var osmId = osmEntity.id.toOSM(this.id);
37083             return osmId.length === 0 || osmId[0] === '-';
37084           },
37085           update: function update(attrs) {
37086             return osmEntity(this, attrs, {
37087               v: 1 + (this.v || 0)
37088             });
37089           },
37090           mergeTags: function mergeTags(tags) {
37091             var merged = Object.assign({}, this.tags); // shallow copy
37092
37093             var changed = false;
37094
37095             for (var k in tags) {
37096               var t1 = merged[k];
37097               var t2 = tags[k];
37098
37099               if (!t1) {
37100                 changed = true;
37101                 merged[k] = t2;
37102               } else if (t1 !== t2) {
37103                 changed = true;
37104                 merged[k] = utilUnicodeCharsTruncated(utilArrayUnion(t1.split(/;\s*/), t2.split(/;\s*/)).join(';'), 255 // avoid exceeding character limit; see also services/osm.js -> maxCharsForTagValue()
37105                 );
37106               }
37107             }
37108
37109             return changed ? this.update({
37110               tags: merged
37111             }) : this;
37112           },
37113           intersects: function intersects(extent, resolver) {
37114             return this.extent(resolver).intersects(extent);
37115           },
37116           hasNonGeometryTags: function hasNonGeometryTags() {
37117             return Object.keys(this.tags).some(function (k) {
37118               return k !== 'area';
37119             });
37120           },
37121           hasParentRelations: function hasParentRelations(resolver) {
37122             return resolver.parentRelations(this).length > 0;
37123           },
37124           hasInterestingTags: function hasInterestingTags() {
37125             return Object.keys(this.tags).some(osmIsInterestingTag);
37126           },
37127           isHighwayIntersection: function isHighwayIntersection() {
37128             return false;
37129           },
37130           isDegenerate: function isDegenerate() {
37131             return true;
37132           },
37133           deprecatedTags: function deprecatedTags(dataDeprecated) {
37134             var tags = this.tags; // if there are no tags, none can be deprecated
37135
37136             if (Object.keys(tags).length === 0) return [];
37137             var deprecated = [];
37138             dataDeprecated.forEach(function (d) {
37139               var oldKeys = Object.keys(d.old);
37140
37141               if (d.replace) {
37142                 var hasExistingValues = Object.keys(d.replace).some(function (replaceKey) {
37143                   if (!tags[replaceKey] || d.old[replaceKey]) return false;
37144                   var replaceValue = d.replace[replaceKey];
37145                   if (replaceValue === '*') return false;
37146                   if (replaceValue === tags[replaceKey]) return false;
37147                   return true;
37148                 }); // don't flag deprecated tags if the upgrade path would overwrite existing data - #7843
37149
37150                 if (hasExistingValues) return;
37151               }
37152
37153               var matchesDeprecatedTags = oldKeys.every(function (oldKey) {
37154                 if (!tags[oldKey]) return false;
37155                 if (d.old[oldKey] === '*') return true;
37156                 if (d.old[oldKey] === tags[oldKey]) return true;
37157                 var vals = tags[oldKey].split(';').filter(Boolean);
37158
37159                 if (vals.length === 0) {
37160                   return false;
37161                 } else if (vals.length > 1) {
37162                   return vals.indexOf(d.old[oldKey]) !== -1;
37163                 } else {
37164                   if (tags[oldKey] === d.old[oldKey]) {
37165                     if (d.replace && d.old[oldKey] === d.replace[oldKey]) {
37166                       var replaceKeys = Object.keys(d.replace);
37167                       return !replaceKeys.every(function (replaceKey) {
37168                         return tags[replaceKey] === d.replace[replaceKey];
37169                       });
37170                     } else {
37171                       return true;
37172                     }
37173                   }
37174                 }
37175
37176                 return false;
37177               });
37178
37179               if (matchesDeprecatedTags) {
37180                 deprecated.push(d);
37181               }
37182             });
37183             return deprecated;
37184           }
37185         };
37186
37187         function osmLanes(entity) {
37188           if (entity.type !== 'way') return null;
37189           if (!entity.tags.highway) return null;
37190           var tags = entity.tags;
37191           var isOneWay = entity.isOneWay();
37192           var laneCount = getLaneCount(tags, isOneWay);
37193           var maxspeed = parseMaxspeed(tags);
37194           var laneDirections = parseLaneDirections(tags, isOneWay, laneCount);
37195           var forward = laneDirections.forward;
37196           var backward = laneDirections.backward;
37197           var bothways = laneDirections.bothways; // parse the piped string 'x|y|z' format
37198
37199           var turnLanes = {};
37200           turnLanes.unspecified = parseTurnLanes(tags['turn:lanes']);
37201           turnLanes.forward = parseTurnLanes(tags['turn:lanes:forward']);
37202           turnLanes.backward = parseTurnLanes(tags['turn:lanes:backward']);
37203           var maxspeedLanes = {};
37204           maxspeedLanes.unspecified = parseMaxspeedLanes(tags['maxspeed:lanes'], maxspeed);
37205           maxspeedLanes.forward = parseMaxspeedLanes(tags['maxspeed:lanes:forward'], maxspeed);
37206           maxspeedLanes.backward = parseMaxspeedLanes(tags['maxspeed:lanes:backward'], maxspeed);
37207           var psvLanes = {};
37208           psvLanes.unspecified = parseMiscLanes(tags['psv:lanes']);
37209           psvLanes.forward = parseMiscLanes(tags['psv:lanes:forward']);
37210           psvLanes.backward = parseMiscLanes(tags['psv:lanes:backward']);
37211           var busLanes = {};
37212           busLanes.unspecified = parseMiscLanes(tags['bus:lanes']);
37213           busLanes.forward = parseMiscLanes(tags['bus:lanes:forward']);
37214           busLanes.backward = parseMiscLanes(tags['bus:lanes:backward']);
37215           var taxiLanes = {};
37216           taxiLanes.unspecified = parseMiscLanes(tags['taxi:lanes']);
37217           taxiLanes.forward = parseMiscLanes(tags['taxi:lanes:forward']);
37218           taxiLanes.backward = parseMiscLanes(tags['taxi:lanes:backward']);
37219           var hovLanes = {};
37220           hovLanes.unspecified = parseMiscLanes(tags['hov:lanes']);
37221           hovLanes.forward = parseMiscLanes(tags['hov:lanes:forward']);
37222           hovLanes.backward = parseMiscLanes(tags['hov:lanes:backward']);
37223           var hgvLanes = {};
37224           hgvLanes.unspecified = parseMiscLanes(tags['hgv:lanes']);
37225           hgvLanes.forward = parseMiscLanes(tags['hgv:lanes:forward']);
37226           hgvLanes.backward = parseMiscLanes(tags['hgv:lanes:backward']);
37227           var bicyclewayLanes = {};
37228           bicyclewayLanes.unspecified = parseBicycleWay(tags['bicycleway:lanes']);
37229           bicyclewayLanes.forward = parseBicycleWay(tags['bicycleway:lanes:forward']);
37230           bicyclewayLanes.backward = parseBicycleWay(tags['bicycleway:lanes:backward']);
37231           var lanesObj = {
37232             forward: [],
37233             backward: [],
37234             unspecified: []
37235           }; // map forward/backward/unspecified of each lane type to lanesObj
37236
37237           mapToLanesObj(lanesObj, turnLanes, 'turnLane');
37238           mapToLanesObj(lanesObj, maxspeedLanes, 'maxspeed');
37239           mapToLanesObj(lanesObj, psvLanes, 'psv');
37240           mapToLanesObj(lanesObj, busLanes, 'bus');
37241           mapToLanesObj(lanesObj, taxiLanes, 'taxi');
37242           mapToLanesObj(lanesObj, hovLanes, 'hov');
37243           mapToLanesObj(lanesObj, hgvLanes, 'hgv');
37244           mapToLanesObj(lanesObj, bicyclewayLanes, 'bicycleway');
37245           return {
37246             metadata: {
37247               count: laneCount,
37248               oneway: isOneWay,
37249               forward: forward,
37250               backward: backward,
37251               bothways: bothways,
37252               turnLanes: turnLanes,
37253               maxspeed: maxspeed,
37254               maxspeedLanes: maxspeedLanes,
37255               psvLanes: psvLanes,
37256               busLanes: busLanes,
37257               taxiLanes: taxiLanes,
37258               hovLanes: hovLanes,
37259               hgvLanes: hgvLanes,
37260               bicyclewayLanes: bicyclewayLanes
37261             },
37262             lanes: lanesObj
37263           };
37264         }
37265
37266         function getLaneCount(tags, isOneWay) {
37267           var count;
37268
37269           if (tags.lanes) {
37270             count = parseInt(tags.lanes, 10);
37271
37272             if (count > 0) {
37273               return count;
37274             }
37275           }
37276
37277           switch (tags.highway) {
37278             case 'trunk':
37279             case 'motorway':
37280               count = isOneWay ? 2 : 4;
37281               break;
37282
37283             default:
37284               count = isOneWay ? 1 : 2;
37285               break;
37286           }
37287
37288           return count;
37289         }
37290
37291         function parseMaxspeed(tags) {
37292           var maxspeed = tags.maxspeed;
37293           if (!maxspeed) return;
37294           var maxspeedRegex = /^([0-9][\.0-9]+?)(?:[ ]?(?:km\/h|kmh|kph|mph|knots))?$/;
37295           if (!maxspeedRegex.test(maxspeed)) return;
37296           return parseInt(maxspeed, 10);
37297         }
37298
37299         function parseLaneDirections(tags, isOneWay, laneCount) {
37300           var forward = parseInt(tags['lanes:forward'], 10);
37301           var backward = parseInt(tags['lanes:backward'], 10);
37302           var bothways = parseInt(tags['lanes:both_ways'], 10) > 0 ? 1 : 0;
37303
37304           if (parseInt(tags.oneway, 10) === -1) {
37305             forward = 0;
37306             bothways = 0;
37307             backward = laneCount;
37308           } else if (isOneWay) {
37309             forward = laneCount;
37310             bothways = 0;
37311             backward = 0;
37312           } else if (isNaN(forward) && isNaN(backward)) {
37313             backward = Math.floor((laneCount - bothways) / 2);
37314             forward = laneCount - bothways - backward;
37315           } else if (isNaN(forward)) {
37316             if (backward > laneCount - bothways) {
37317               backward = laneCount - bothways;
37318             }
37319
37320             forward = laneCount - bothways - backward;
37321           } else if (isNaN(backward)) {
37322             if (forward > laneCount - bothways) {
37323               forward = laneCount - bothways;
37324             }
37325
37326             backward = laneCount - bothways - forward;
37327           }
37328
37329           return {
37330             forward: forward,
37331             backward: backward,
37332             bothways: bothways
37333           };
37334         }
37335
37336         function parseTurnLanes(tag) {
37337           if (!tag) return;
37338           var validValues = ['left', 'slight_left', 'sharp_left', 'through', 'right', 'slight_right', 'sharp_right', 'reverse', 'merge_to_left', 'merge_to_right', 'none'];
37339           return tag.split('|').map(function (s) {
37340             if (s === '') s = 'none';
37341             return s.split(';').map(function (d) {
37342               return validValues.indexOf(d) === -1 ? 'unknown' : d;
37343             });
37344           });
37345         }
37346
37347         function parseMaxspeedLanes(tag, maxspeed) {
37348           if (!tag) return;
37349           return tag.split('|').map(function (s) {
37350             if (s === 'none') return s;
37351             var m = parseInt(s, 10);
37352             if (s === '' || m === maxspeed) return null;
37353             return isNaN(m) ? 'unknown' : m;
37354           });
37355         }
37356
37357         function parseMiscLanes(tag) {
37358           if (!tag) return;
37359           var validValues = ['yes', 'no', 'designated'];
37360           return tag.split('|').map(function (s) {
37361             if (s === '') s = 'no';
37362             return validValues.indexOf(s) === -1 ? 'unknown' : s;
37363           });
37364         }
37365
37366         function parseBicycleWay(tag) {
37367           if (!tag) return;
37368           var validValues = ['yes', 'no', 'designated', 'lane'];
37369           return tag.split('|').map(function (s) {
37370             if (s === '') s = 'no';
37371             return validValues.indexOf(s) === -1 ? 'unknown' : s;
37372           });
37373         }
37374
37375         function mapToLanesObj(lanesObj, data, key) {
37376           if (data.forward) {
37377             data.forward.forEach(function (l, i) {
37378               if (!lanesObj.forward[i]) lanesObj.forward[i] = {};
37379               lanesObj.forward[i][key] = l;
37380             });
37381           }
37382
37383           if (data.backward) {
37384             data.backward.forEach(function (l, i) {
37385               if (!lanesObj.backward[i]) lanesObj.backward[i] = {};
37386               lanesObj.backward[i][key] = l;
37387             });
37388           }
37389
37390           if (data.unspecified) {
37391             data.unspecified.forEach(function (l, i) {
37392               if (!lanesObj.unspecified[i]) lanesObj.unspecified[i] = {};
37393               lanesObj.unspecified[i][key] = l;
37394             });
37395           }
37396         }
37397
37398         function osmWay() {
37399           if (!(this instanceof osmWay)) {
37400             return new osmWay().initialize(arguments);
37401           } else if (arguments.length) {
37402             this.initialize(arguments);
37403           }
37404         }
37405         osmEntity.way = osmWay;
37406         osmWay.prototype = Object.create(osmEntity.prototype);
37407         Object.assign(osmWay.prototype, {
37408           type: 'way',
37409           nodes: [],
37410           copy: function copy(resolver, copies) {
37411             if (copies[this.id]) return copies[this.id];
37412             var copy = osmEntity.prototype.copy.call(this, resolver, copies);
37413             var nodes = this.nodes.map(function (id) {
37414               return resolver.entity(id).copy(resolver, copies).id;
37415             });
37416             copy = copy.update({
37417               nodes: nodes
37418             });
37419             copies[this.id] = copy;
37420             return copy;
37421           },
37422           extent: function extent(resolver) {
37423             return resolver["transient"](this, 'extent', function () {
37424               var extent = geoExtent();
37425
37426               for (var i = 0; i < this.nodes.length; i++) {
37427                 var node = resolver.hasEntity(this.nodes[i]);
37428
37429                 if (node) {
37430                   extent._extend(node.extent());
37431                 }
37432               }
37433
37434               return extent;
37435             });
37436           },
37437           first: function first() {
37438             return this.nodes[0];
37439           },
37440           last: function last() {
37441             return this.nodes[this.nodes.length - 1];
37442           },
37443           contains: function contains(node) {
37444             return this.nodes.indexOf(node) >= 0;
37445           },
37446           affix: function affix(node) {
37447             if (this.nodes[0] === node) return 'prefix';
37448             if (this.nodes[this.nodes.length - 1] === node) return 'suffix';
37449           },
37450           layer: function layer() {
37451             // explicit layer tag, clamp between -10, 10..
37452             if (isFinite(this.tags.layer)) {
37453               return Math.max(-10, Math.min(+this.tags.layer, 10));
37454             } // implied layer tag..
37455
37456
37457             if (this.tags.covered === 'yes') return -1;
37458             if (this.tags.location === 'overground') return 1;
37459             if (this.tags.location === 'underground') return -1;
37460             if (this.tags.location === 'underwater') return -10;
37461             if (this.tags.power === 'line') return 10;
37462             if (this.tags.power === 'minor_line') return 10;
37463             if (this.tags.aerialway) return 10;
37464             if (this.tags.bridge) return 1;
37465             if (this.tags.cutting) return -1;
37466             if (this.tags.tunnel) return -1;
37467             if (this.tags.waterway) return -1;
37468             if (this.tags.man_made === 'pipeline') return -10;
37469             if (this.tags.boundary) return -10;
37470             return 0;
37471           },
37472           // the approximate width of the line based on its tags except its `width` tag
37473           impliedLineWidthMeters: function impliedLineWidthMeters() {
37474             var averageWidths = {
37475               highway: {
37476                 // width is for single lane
37477                 motorway: 5,
37478                 motorway_link: 5,
37479                 trunk: 4.5,
37480                 trunk_link: 4.5,
37481                 primary: 4,
37482                 secondary: 4,
37483                 tertiary: 4,
37484                 primary_link: 4,
37485                 secondary_link: 4,
37486                 tertiary_link: 4,
37487                 unclassified: 4,
37488                 road: 4,
37489                 living_street: 4,
37490                 bus_guideway: 4,
37491                 pedestrian: 4,
37492                 residential: 3.5,
37493                 service: 3.5,
37494                 track: 3,
37495                 cycleway: 2.5,
37496                 bridleway: 2,
37497                 corridor: 2,
37498                 steps: 2,
37499                 path: 1.5,
37500                 footway: 1.5
37501               },
37502               railway: {
37503                 // width includes ties and rail bed, not just track gauge
37504                 rail: 2.5,
37505                 light_rail: 2.5,
37506                 tram: 2.5,
37507                 subway: 2.5,
37508                 monorail: 2.5,
37509                 funicular: 2.5,
37510                 disused: 2.5,
37511                 preserved: 2.5,
37512                 miniature: 1.5,
37513                 narrow_gauge: 1.5
37514               },
37515               waterway: {
37516                 river: 50,
37517                 canal: 25,
37518                 stream: 5,
37519                 tidal_channel: 5,
37520                 fish_pass: 2.5,
37521                 drain: 2.5,
37522                 ditch: 1.5
37523               }
37524             };
37525
37526             for (var key in averageWidths) {
37527               if (this.tags[key] && averageWidths[key][this.tags[key]]) {
37528                 var width = averageWidths[key][this.tags[key]];
37529
37530                 if (key === 'highway') {
37531                   var laneCount = this.tags.lanes && parseInt(this.tags.lanes, 10);
37532                   if (!laneCount) laneCount = this.isOneWay() ? 1 : 2;
37533                   return width * laneCount;
37534                 }
37535
37536                 return width;
37537               }
37538             }
37539
37540             return null;
37541           },
37542           isOneWay: function isOneWay() {
37543             // explicit oneway tag..
37544             var values = {
37545               'yes': true,
37546               '1': true,
37547               '-1': true,
37548               'reversible': true,
37549               'alternating': true,
37550               'no': false,
37551               '0': false
37552             };
37553
37554             if (values[this.tags.oneway] !== undefined) {
37555               return values[this.tags.oneway];
37556             } // implied oneway tag..
37557
37558
37559             for (var key in this.tags) {
37560               if (key in osmOneWayTags && this.tags[key] in osmOneWayTags[key]) {
37561                 return true;
37562               }
37563             }
37564
37565             return false;
37566           },
37567           // Some identifier for tag that implies that this way is "sided",
37568           // i.e. the right side is the 'inside' (e.g. the right side of a
37569           // natural=cliff is lower).
37570           sidednessIdentifier: function sidednessIdentifier() {
37571             for (var key in this.tags) {
37572               var value = this.tags[key];
37573
37574               if (key in osmRightSideIsInsideTags && value in osmRightSideIsInsideTags[key]) {
37575                 if (osmRightSideIsInsideTags[key][value] === true) {
37576                   return key;
37577                 } else {
37578                   // if the map's value is something other than a
37579                   // literal true, we should use it so we can
37580                   // special case some keys (e.g. natural=coastline
37581                   // is handled differently to other naturals).
37582                   return osmRightSideIsInsideTags[key][value];
37583                 }
37584               }
37585             }
37586
37587             return null;
37588           },
37589           isSided: function isSided() {
37590             if (this.tags.two_sided === 'yes') {
37591               return false;
37592             }
37593
37594             return this.sidednessIdentifier() !== null;
37595           },
37596           lanes: function lanes() {
37597             return osmLanes(this);
37598           },
37599           isClosed: function isClosed() {
37600             return this.nodes.length > 1 && this.first() === this.last();
37601           },
37602           isConvex: function isConvex(resolver) {
37603             if (!this.isClosed() || this.isDegenerate()) return null;
37604             var nodes = utilArrayUniq(resolver.childNodes(this));
37605             var coords = nodes.map(function (n) {
37606               return n.loc;
37607             });
37608             var curr = 0;
37609             var prev = 0;
37610
37611             for (var i = 0; i < coords.length; i++) {
37612               var o = coords[(i + 1) % coords.length];
37613               var a = coords[i];
37614               var b = coords[(i + 2) % coords.length];
37615               var res = geoVecCross(a, b, o);
37616               curr = res > 0 ? 1 : res < 0 ? -1 : 0;
37617
37618               if (curr === 0) {
37619                 continue;
37620               } else if (prev && curr !== prev) {
37621                 return false;
37622               }
37623
37624               prev = curr;
37625             }
37626
37627             return true;
37628           },
37629           // returns an object with the tag that implies this is an area, if any
37630           tagSuggestingArea: function tagSuggestingArea() {
37631             return osmTagSuggestingArea(this.tags);
37632           },
37633           isArea: function isArea() {
37634             if (this.tags.area === 'yes') return true;
37635             if (!this.isClosed() || this.tags.area === 'no') return false;
37636             return this.tagSuggestingArea() !== null;
37637           },
37638           isDegenerate: function isDegenerate() {
37639             return new Set(this.nodes).size < (this.isArea() ? 3 : 2);
37640           },
37641           areAdjacent: function areAdjacent(n1, n2) {
37642             for (var i = 0; i < this.nodes.length; i++) {
37643               if (this.nodes[i] === n1) {
37644                 if (this.nodes[i - 1] === n2) return true;
37645                 if (this.nodes[i + 1] === n2) return true;
37646               }
37647             }
37648
37649             return false;
37650           },
37651           geometry: function geometry(graph) {
37652             return graph["transient"](this, 'geometry', function () {
37653               return this.isArea() ? 'area' : 'line';
37654             });
37655           },
37656           // returns an array of objects representing the segments between the nodes in this way
37657           segments: function segments(graph) {
37658             function segmentExtent(graph) {
37659               var n1 = graph.hasEntity(this.nodes[0]);
37660               var n2 = graph.hasEntity(this.nodes[1]);
37661               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])]]);
37662             }
37663
37664             return graph["transient"](this, 'segments', function () {
37665               var segments = [];
37666
37667               for (var i = 0; i < this.nodes.length - 1; i++) {
37668                 segments.push({
37669                   id: this.id + '-' + i,
37670                   wayId: this.id,
37671                   index: i,
37672                   nodes: [this.nodes[i], this.nodes[i + 1]],
37673                   extent: segmentExtent
37674                 });
37675               }
37676
37677               return segments;
37678             });
37679           },
37680           // If this way is not closed, append the beginning node to the end of the nodelist to close it.
37681           close: function close() {
37682             if (this.isClosed() || !this.nodes.length) return this;
37683             var nodes = this.nodes.slice();
37684             nodes = nodes.filter(noRepeatNodes);
37685             nodes.push(nodes[0]);
37686             return this.update({
37687               nodes: nodes
37688             });
37689           },
37690           // If this way is closed, remove any connector nodes from the end of the nodelist to unclose it.
37691           unclose: function unclose() {
37692             if (!this.isClosed()) return this;
37693             var nodes = this.nodes.slice();
37694             var connector = this.first();
37695             var i = nodes.length - 1; // remove trailing connectors..
37696
37697             while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
37698               nodes.splice(i, 1);
37699               i = nodes.length - 1;
37700             }
37701
37702             nodes = nodes.filter(noRepeatNodes);
37703             return this.update({
37704               nodes: nodes
37705             });
37706           },
37707           // Adds a node (id) in front of the node which is currently at position index.
37708           // If index is undefined, the node will be added to the end of the way for linear ways,
37709           //   or just before the final connecting node for circular ways.
37710           // Consecutive duplicates are eliminated including existing ones.
37711           // Circularity is always preserved when adding a node.
37712           addNode: function addNode(id, index) {
37713             var nodes = this.nodes.slice();
37714             var isClosed = this.isClosed();
37715             var max = isClosed ? nodes.length - 1 : nodes.length;
37716
37717             if (index === undefined) {
37718               index = max;
37719             }
37720
37721             if (index < 0 || index > max) {
37722               throw new RangeError('index ' + index + ' out of range 0..' + max);
37723             } // If this is a closed way, remove all connector nodes except the first one
37724             // (there may be duplicates) and adjust index if necessary..
37725
37726
37727             if (isClosed) {
37728               var connector = this.first(); // leading connectors..
37729
37730               var i = 1;
37731
37732               while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) {
37733                 nodes.splice(i, 1);
37734                 if (index > i) index--;
37735               } // trailing connectors..
37736
37737
37738               i = nodes.length - 1;
37739
37740               while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
37741                 nodes.splice(i, 1);
37742                 if (index > i) index--;
37743                 i = nodes.length - 1;
37744               }
37745             }
37746
37747             nodes.splice(index, 0, id);
37748             nodes = nodes.filter(noRepeatNodes); // If the way was closed before, append a connector node to keep it closed..
37749
37750             if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
37751               nodes.push(nodes[0]);
37752             }
37753
37754             return this.update({
37755               nodes: nodes
37756             });
37757           },
37758           // Replaces the node which is currently at position index with the given node (id).
37759           // Consecutive duplicates are eliminated including existing ones.
37760           // Circularity is preserved when updating a node.
37761           updateNode: function updateNode(id, index) {
37762             var nodes = this.nodes.slice();
37763             var isClosed = this.isClosed();
37764             var max = nodes.length - 1;
37765
37766             if (index === undefined || index < 0 || index > max) {
37767               throw new RangeError('index ' + index + ' out of range 0..' + max);
37768             } // If this is a closed way, remove all connector nodes except the first one
37769             // (there may be duplicates) and adjust index if necessary..
37770
37771
37772             if (isClosed) {
37773               var connector = this.first(); // leading connectors..
37774
37775               var i = 1;
37776
37777               while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) {
37778                 nodes.splice(i, 1);
37779                 if (index > i) index--;
37780               } // trailing connectors..
37781
37782
37783               i = nodes.length - 1;
37784
37785               while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
37786                 nodes.splice(i, 1);
37787                 if (index === i) index = 0; // update leading connector instead
37788
37789                 i = nodes.length - 1;
37790               }
37791             }
37792
37793             nodes.splice(index, 1, id);
37794             nodes = nodes.filter(noRepeatNodes); // If the way was closed before, append a connector node to keep it closed..
37795
37796             if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
37797               nodes.push(nodes[0]);
37798             }
37799
37800             return this.update({
37801               nodes: nodes
37802             });
37803           },
37804           // Replaces each occurrence of node id needle with replacement.
37805           // Consecutive duplicates are eliminated including existing ones.
37806           // Circularity is preserved.
37807           replaceNode: function replaceNode(needleID, replacementID) {
37808             var nodes = this.nodes.slice();
37809             var isClosed = this.isClosed();
37810
37811             for (var i = 0; i < nodes.length; i++) {
37812               if (nodes[i] === needleID) {
37813                 nodes[i] = replacementID;
37814               }
37815             }
37816
37817             nodes = nodes.filter(noRepeatNodes); // If the way was closed before, append a connector node to keep it closed..
37818
37819             if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
37820               nodes.push(nodes[0]);
37821             }
37822
37823             return this.update({
37824               nodes: nodes
37825             });
37826           },
37827           // Removes each occurrence of node id.
37828           // Consecutive duplicates are eliminated including existing ones.
37829           // Circularity is preserved.
37830           removeNode: function removeNode(id) {
37831             var nodes = this.nodes.slice();
37832             var isClosed = this.isClosed();
37833             nodes = nodes.filter(function (node) {
37834               return node !== id;
37835             }).filter(noRepeatNodes); // If the way was closed before, append a connector node to keep it closed..
37836
37837             if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
37838               nodes.push(nodes[0]);
37839             }
37840
37841             return this.update({
37842               nodes: nodes
37843             });
37844           },
37845           asJXON: function asJXON(changeset_id) {
37846             var r = {
37847               way: {
37848                 '@id': this.osmId(),
37849                 '@version': this.version || 0,
37850                 nd: this.nodes.map(function (id) {
37851                   return {
37852                     keyAttributes: {
37853                       ref: osmEntity.id.toOSM(id)
37854                     }
37855                   };
37856                 }, this),
37857                 tag: Object.keys(this.tags).map(function (k) {
37858                   return {
37859                     keyAttributes: {
37860                       k: k,
37861                       v: this.tags[k]
37862                     }
37863                   };
37864                 }, this)
37865               }
37866             };
37867
37868             if (changeset_id) {
37869               r.way['@changeset'] = changeset_id;
37870             }
37871
37872             return r;
37873           },
37874           asGeoJSON: function asGeoJSON(resolver) {
37875             return resolver["transient"](this, 'GeoJSON', function () {
37876               var coordinates = resolver.childNodes(this).map(function (n) {
37877                 return n.loc;
37878               });
37879
37880               if (this.isArea() && this.isClosed()) {
37881                 return {
37882                   type: 'Polygon',
37883                   coordinates: [coordinates]
37884                 };
37885               } else {
37886                 return {
37887                   type: 'LineString',
37888                   coordinates: coordinates
37889                 };
37890               }
37891             });
37892           },
37893           area: function area(resolver) {
37894             return resolver["transient"](this, 'area', function () {
37895               var nodes = resolver.childNodes(this);
37896               var json = {
37897                 type: 'Polygon',
37898                 coordinates: [nodes.map(function (n) {
37899                   return n.loc;
37900                 })]
37901               };
37902
37903               if (!this.isClosed() && nodes.length) {
37904                 json.coordinates[0].push(nodes[0].loc);
37905               }
37906
37907               var area = d3_geoArea(json); // Heuristic for detecting counterclockwise winding order. Assumes
37908               // that OpenStreetMap polygons are not hemisphere-spanning.
37909
37910               if (area > 2 * Math.PI) {
37911                 json.coordinates[0] = json.coordinates[0].reverse();
37912                 area = d3_geoArea(json);
37913               }
37914
37915               return isNaN(area) ? 0 : area;
37916             });
37917           }
37918         }); // Filter function to eliminate consecutive duplicates.
37919
37920         function noRepeatNodes(node, i, arr) {
37921           return i === 0 || node !== arr[i - 1];
37922         }
37923
37924         //
37925         // 1. Relation tagged with `type=multipolygon` and no interesting tags.
37926         // 2. One and only one member with the `outer` role. Must be a way with interesting tags.
37927         // 3. No members without a role.
37928         //
37929         // Old multipolygons are no longer recommended but are still rendered as areas by iD.
37930
37931         function osmOldMultipolygonOuterMemberOfRelation(entity, graph) {
37932           if (entity.type !== 'relation' || !entity.isMultipolygon() || Object.keys(entity.tags).filter(osmIsInterestingTag).length > 1) {
37933             return false;
37934           }
37935
37936           var outerMember;
37937
37938           for (var memberIndex in entity.members) {
37939             var member = entity.members[memberIndex];
37940
37941             if (!member.role || member.role === 'outer') {
37942               if (outerMember) return false;
37943               if (member.type !== 'way') return false;
37944               if (!graph.hasEntity(member.id)) return false;
37945               outerMember = graph.entity(member.id);
37946
37947               if (Object.keys(outerMember.tags).filter(osmIsInterestingTag).length === 0) {
37948                 return false;
37949               }
37950             }
37951           }
37952
37953           return outerMember;
37954         } // For fixing up rendering of multipolygons with tags on the outer member.
37955         // https://github.com/openstreetmap/iD/issues/613
37956
37957         function osmIsOldMultipolygonOuterMember(entity, graph) {
37958           if (entity.type !== 'way' || Object.keys(entity.tags).filter(osmIsInterestingTag).length === 0) {
37959             return false;
37960           }
37961
37962           var parents = graph.parentRelations(entity);
37963           if (parents.length !== 1) return false;
37964           var parent = parents[0];
37965
37966           if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1) {
37967             return false;
37968           }
37969
37970           var members = parent.members,
37971               member;
37972
37973           for (var i = 0; i < members.length; i++) {
37974             member = members[i];
37975
37976             if (member.id === entity.id && member.role && member.role !== 'outer') {
37977               // Not outer member
37978               return false;
37979             }
37980
37981             if (member.id !== entity.id && (!member.role || member.role === 'outer')) {
37982               // Not a simple multipolygon
37983               return false;
37984             }
37985           }
37986
37987           return parent;
37988         }
37989         function osmOldMultipolygonOuterMember(entity, graph) {
37990           if (entity.type !== 'way') return false;
37991           var parents = graph.parentRelations(entity);
37992           if (parents.length !== 1) return false;
37993           var parent = parents[0];
37994
37995           if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1) {
37996             return false;
37997           }
37998
37999           var members = parent.members,
38000               member,
38001               outerMember;
38002
38003           for (var i = 0; i < members.length; i++) {
38004             member = members[i];
38005
38006             if (!member.role || member.role === 'outer') {
38007               if (outerMember) return false; // Not a simple multipolygon
38008
38009               outerMember = member;
38010             }
38011           }
38012
38013           if (!outerMember) return false;
38014           var outerEntity = graph.hasEntity(outerMember.id);
38015
38016           if (!outerEntity || !Object.keys(outerEntity.tags).filter(osmIsInterestingTag).length) {
38017             return false;
38018           }
38019
38020           return outerEntity;
38021         } // Join `toJoin` array into sequences of connecting ways.
38022         // Segments which share identical start/end nodes will, as much as possible,
38023         // be connected with each other.
38024         //
38025         // The return value is a nested array. Each constituent array contains elements
38026         // of `toJoin` which have been determined to connect.
38027         //
38028         // Each consitituent array also has a `nodes` property whose value is an
38029         // ordered array of member nodes, with appropriate order reversal and
38030         // start/end coordinate de-duplication.
38031         //
38032         // Members of `toJoin` must have, at minimum, `type` and `id` properties.
38033         // Thus either an array of `osmWay`s or a relation member array may be used.
38034         //
38035         // If an member is an `osmWay`, its tags and childnodes may be reversed via
38036         // `actionReverse` in the output.
38037         //
38038         // The returned sequences array also has an `actions` array property, containing
38039         // any reversal actions that should be applied to the graph, should the calling
38040         // code attempt to actually join the given ways.
38041         //
38042         // Incomplete members (those for which `graph.hasEntity(element.id)` returns
38043         // false) and non-way members are ignored.
38044         //
38045
38046         function osmJoinWays(toJoin, graph) {
38047           function resolve(member) {
38048             return graph.childNodes(graph.entity(member.id));
38049           }
38050
38051           function reverse(item) {
38052             var action = actionReverse(item.id, {
38053               reverseOneway: true
38054             });
38055             sequences.actions.push(action);
38056             return item instanceof osmWay ? action(graph).entity(item.id) : item;
38057           } // make a copy containing only the items to join
38058
38059
38060           toJoin = toJoin.filter(function (member) {
38061             return member.type === 'way' && graph.hasEntity(member.id);
38062           }); // Are the things we are joining relation members or `osmWays`?
38063           // If `osmWays`, skip the "prefer a forward path" code below (see #4872)
38064
38065           var i;
38066           var joinAsMembers = true;
38067
38068           for (i = 0; i < toJoin.length; i++) {
38069             if (toJoin[i] instanceof osmWay) {
38070               joinAsMembers = false;
38071               break;
38072             }
38073           }
38074
38075           var sequences = [];
38076           sequences.actions = [];
38077
38078           while (toJoin.length) {
38079             // start a new sequence
38080             var item = toJoin.shift();
38081             var currWays = [item];
38082             var currNodes = resolve(item).slice(); // add to it
38083
38084             while (toJoin.length) {
38085               var start = currNodes[0];
38086               var end = currNodes[currNodes.length - 1];
38087               var fn = null;
38088               var nodes = null; // Find the next way/member to join.
38089
38090               for (i = 0; i < toJoin.length; i++) {
38091                 item = toJoin[i];
38092                 nodes = resolve(item); // (for member ordering only, not way ordering - see #4872)
38093                 // Strongly prefer to generate a forward path that preserves the order
38094                 // of the members array. For multipolygons and most relations, member
38095                 // order does not matter - but for routes, it does. (see #4589)
38096                 // If we started this sequence backwards (i.e. next member way attaches to
38097                 // the start node and not the end node), reverse the initial way before continuing.
38098
38099                 if (joinAsMembers && currWays.length === 1 && nodes[0] !== end && nodes[nodes.length - 1] !== end && (nodes[nodes.length - 1] === start || nodes[0] === start)) {
38100                   currWays[0] = reverse(currWays[0]);
38101                   currNodes.reverse();
38102                   start = currNodes[0];
38103                   end = currNodes[currNodes.length - 1];
38104                 }
38105
38106                 if (nodes[0] === end) {
38107                   fn = currNodes.push; // join to end
38108
38109                   nodes = nodes.slice(1);
38110                   break;
38111                 } else if (nodes[nodes.length - 1] === end) {
38112                   fn = currNodes.push; // join to end
38113
38114                   nodes = nodes.slice(0, -1).reverse();
38115                   item = reverse(item);
38116                   break;
38117                 } else if (nodes[nodes.length - 1] === start) {
38118                   fn = currNodes.unshift; // join to beginning
38119
38120                   nodes = nodes.slice(0, -1);
38121                   break;
38122                 } else if (nodes[0] === start) {
38123                   fn = currNodes.unshift; // join to beginning
38124
38125                   nodes = nodes.slice(1).reverse();
38126                   item = reverse(item);
38127                   break;
38128                 } else {
38129                   fn = nodes = null;
38130                 }
38131               }
38132
38133               if (!nodes) {
38134                 // couldn't find a joinable way/member
38135                 break;
38136               }
38137
38138               fn.apply(currWays, [item]);
38139               fn.apply(currNodes, nodes);
38140               toJoin.splice(i, 1);
38141             }
38142
38143             currWays.nodes = currNodes;
38144             sequences.push(currWays);
38145           }
38146
38147           return sequences;
38148         }
38149
38150         function actionAddMember(relationId, member, memberIndex, insertPair) {
38151           return function action(graph) {
38152             var relation = graph.entity(relationId); // There are some special rules for Public Transport v2 routes.
38153
38154             var isPTv2 = /stop|platform/.test(member.role);
38155
38156             if ((isNaN(memberIndex) || insertPair) && member.type === 'way' && !isPTv2) {
38157               // Try to perform sensible inserts based on how the ways join together
38158               graph = addWayMember(relation, graph);
38159             } else {
38160               // see https://wiki.openstreetmap.org/wiki/Public_transport#Service_routes
38161               // Stops and Platforms for PTv2 should be ordered first.
38162               // hack: We do not currently have the ability to place them in the exactly correct order.
38163               if (isPTv2 && isNaN(memberIndex)) {
38164                 memberIndex = 0;
38165               }
38166
38167               graph = graph.replace(relation.addMember(member, memberIndex));
38168             }
38169
38170             return graph;
38171           }; // Add a way member into the relation "wherever it makes sense".
38172           // In this situation we were not supplied a memberIndex.
38173
38174           function addWayMember(relation, graph) {
38175             var groups, tempWay, insertPairIsReversed, item, i, j, k; // remove PTv2 stops and platforms before doing anything.
38176
38177             var PTv2members = [];
38178             var members = [];
38179
38180             for (i = 0; i < relation.members.length; i++) {
38181               var m = relation.members[i];
38182
38183               if (/stop|platform/.test(m.role)) {
38184                 PTv2members.push(m);
38185               } else {
38186                 members.push(m);
38187               }
38188             }
38189
38190             relation = relation.update({
38191               members: members
38192             });
38193
38194             if (insertPair) {
38195               // We're adding a member that must stay paired with an existing member.
38196               // (This feature is used by `actionSplit`)
38197               //
38198               // This is tricky because the members may exist multiple times in the
38199               // member list, and with different A-B/B-A ordering and different roles.
38200               // (e.g. a bus route that loops out and back - #4589).
38201               //
38202               // Replace the existing member with a temporary way,
38203               // so that `osmJoinWays` can treat the pair like a single way.
38204               tempWay = osmWay({
38205                 id: 'wTemp',
38206                 nodes: insertPair.nodes
38207               });
38208               graph = graph.replace(tempWay);
38209               var tempMember = {
38210                 id: tempWay.id,
38211                 type: 'way',
38212                 role: member.role
38213               };
38214               var tempRelation = relation.replaceMember({
38215                 id: insertPair.originalID
38216               }, tempMember, true);
38217               groups = utilArrayGroupBy(tempRelation.members, 'type');
38218               groups.way = groups.way || []; // Insert pair is reversed if the inserted way comes before the original one.
38219               // (Except when they form a loop.)
38220
38221               var originalWay = graph.entity(insertPair.originalID);
38222               var insertedWay = graph.entity(insertPair.insertedID);
38223               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];
38224             } else {
38225               // Add the member anywhere, one time. Just push and let `osmJoinWays` decide where to put it.
38226               groups = utilArrayGroupBy(relation.members, 'type');
38227               groups.way = groups.way || [];
38228               groups.way.push(member);
38229             }
38230
38231             members = withIndex(groups.way);
38232             var joined = osmJoinWays(members, graph); // `joined` might not contain all of the way members,
38233             // But will contain only the completed (downloaded) members
38234
38235             for (i = 0; i < joined.length; i++) {
38236               var segment = joined[i];
38237               var nodes = segment.nodes.slice();
38238               var startIndex = segment[0].index; // j = array index in `members` where this segment starts
38239
38240               for (j = 0; j < members.length; j++) {
38241                 if (members[j].index === startIndex) {
38242                   break;
38243                 }
38244               } // k = each member in segment
38245
38246
38247               for (k = 0; k < segment.length; k++) {
38248                 item = segment[k];
38249                 var way = graph.entity(item.id); // If this is a paired item, generate members in correct order and role
38250
38251                 if (tempWay && item.id === tempWay.id) {
38252                   var reverse = nodes[0].id !== insertPair.nodes[0] ^ insertPairIsReversed;
38253
38254                   if (reverse) {
38255                     item.pair = [{
38256                       id: insertPair.insertedID,
38257                       type: 'way',
38258                       role: item.role
38259                     }, {
38260                       id: insertPair.originalID,
38261                       type: 'way',
38262                       role: item.role
38263                     }];
38264                   } else {
38265                     item.pair = [{
38266                       id: insertPair.originalID,
38267                       type: 'way',
38268                       role: item.role
38269                     }, {
38270                       id: insertPair.insertedID,
38271                       type: 'way',
38272                       role: item.role
38273                     }];
38274                   }
38275                 } // reorder `members` if necessary
38276
38277
38278                 if (k > 0) {
38279                   if (j + k >= members.length || item.index !== members[j + k].index) {
38280                     moveMember(members, item.index, j + k);
38281                   }
38282                 }
38283
38284                 nodes.splice(0, way.nodes.length - 1);
38285               }
38286             }
38287
38288             if (tempWay) {
38289               graph = graph.remove(tempWay);
38290             } // Final pass: skip dead items, split pairs, remove index properties
38291
38292
38293             var wayMembers = [];
38294
38295             for (i = 0; i < members.length; i++) {
38296               item = members[i];
38297               if (item.index === -1) continue;
38298
38299               if (item.pair) {
38300                 wayMembers.push(item.pair[0]);
38301                 wayMembers.push(item.pair[1]);
38302               } else {
38303                 wayMembers.push(utilObjectOmit(item, ['index']));
38304               }
38305             } // Put stops and platforms first, then nodes, ways, relations
38306             // This is recommended for Public Transport v2 routes:
38307             // see https://wiki.openstreetmap.org/wiki/Public_transport#Service_routes
38308
38309
38310             var newMembers = PTv2members.concat(groups.node || [], wayMembers, groups.relation || []);
38311             return graph.replace(relation.update({
38312               members: newMembers
38313             })); // `moveMember()` changes the `members` array in place by splicing
38314             // the item with `.index = findIndex` to where it belongs,
38315             // and marking the old position as "dead" with `.index = -1`
38316             //
38317             // j=5, k=0                jk
38318             // segment                 5 4 7 6
38319             // members       0 1 2 3 4 5 6 7 8 9        keep 5 in j+k
38320             //
38321             // j=5, k=1                j k
38322             // segment                 5 4 7 6
38323             // members       0 1 2 3 4 5 6 7 8 9        move 4 to j+k
38324             // members       0 1 2 3 x 5 4 6 7 8 9      moved
38325             //
38326             // j=5, k=2                j   k
38327             // segment                 5 4 7 6
38328             // members       0 1 2 3 x 5 4 6 7 8 9      move 7 to j+k
38329             // members       0 1 2 3 x 5 4 7 6 x 8 9    moved
38330             //
38331             // j=5, k=3                j     k
38332             // segment                 5 4 7 6
38333             // members       0 1 2 3 x 5 4 7 6 x 8 9    keep 6 in j+k
38334             //
38335
38336             function moveMember(arr, findIndex, toIndex) {
38337               var i;
38338
38339               for (i = 0; i < arr.length; i++) {
38340                 if (arr[i].index === findIndex) {
38341                   break;
38342                 }
38343               }
38344
38345               var item = Object.assign({}, arr[i]); // shallow copy
38346
38347               arr[i].index = -1; // mark as dead
38348
38349               item.index = toIndex;
38350               arr.splice(toIndex, 0, item);
38351             } // This is the same as `Relation.indexedMembers`,
38352             // Except we don't want to index all the members, only the ways
38353
38354
38355             function withIndex(arr) {
38356               var result = new Array(arr.length);
38357
38358               for (var i = 0; i < arr.length; i++) {
38359                 result[i] = Object.assign({}, arr[i]); // shallow copy
38360
38361                 result[i].index = i;
38362               }
38363
38364               return result;
38365             }
38366           }
38367         }
38368
38369         function actionAddMidpoint(midpoint, node) {
38370           return function (graph) {
38371             graph = graph.replace(node.move(midpoint.loc));
38372             var parents = utilArrayIntersection(graph.parentWays(graph.entity(midpoint.edge[0])), graph.parentWays(graph.entity(midpoint.edge[1])));
38373             parents.forEach(function (way) {
38374               for (var i = 0; i < way.nodes.length - 1; i++) {
38375                 if (geoEdgeEqual([way.nodes[i], way.nodes[i + 1]], midpoint.edge)) {
38376                   graph = graph.replace(graph.entity(way.id).addNode(node.id, i + 1)); // Add only one midpoint on doubled-back segments,
38377                   // turning them into self-intersections.
38378
38379                   return;
38380                 }
38381               }
38382             });
38383             return graph;
38384           };
38385         }
38386
38387         // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as
38388         function actionAddVertex(wayId, nodeId, index) {
38389           return function (graph) {
38390             return graph.replace(graph.entity(wayId).addNode(nodeId, index));
38391           };
38392         }
38393
38394         function actionChangeMember(relationId, member, memberIndex) {
38395           return function (graph) {
38396             return graph.replace(graph.entity(relationId).updateMember(member, memberIndex));
38397           };
38398         }
38399
38400         function actionChangePreset(entityID, oldPreset, newPreset, skipFieldDefaults) {
38401           return function action(graph) {
38402             var entity = graph.entity(entityID);
38403             var geometry = entity.geometry(graph);
38404             var tags = entity.tags; // preserve tags that the new preset might care about, if any
38405
38406             if (oldPreset) tags = oldPreset.unsetTags(tags, geometry, newPreset && newPreset.addTags ? Object.keys(newPreset.addTags) : null);
38407             if (newPreset) tags = newPreset.setTags(tags, geometry, skipFieldDefaults);
38408             return graph.replace(entity.update({
38409               tags: tags
38410             }));
38411           };
38412         }
38413
38414         function actionChangeTags(entityId, tags) {
38415           return function (graph) {
38416             var entity = graph.entity(entityId);
38417             return graph.replace(entity.update({
38418               tags: tags
38419             }));
38420           };
38421         }
38422
38423         function osmNode() {
38424           if (!(this instanceof osmNode)) {
38425             return new osmNode().initialize(arguments);
38426           } else if (arguments.length) {
38427             this.initialize(arguments);
38428           }
38429         }
38430         osmEntity.node = osmNode;
38431         osmNode.prototype = Object.create(osmEntity.prototype);
38432         Object.assign(osmNode.prototype, {
38433           type: 'node',
38434           loc: [9999, 9999],
38435           extent: function extent() {
38436             return new geoExtent(this.loc);
38437           },
38438           geometry: function geometry(graph) {
38439             return graph["transient"](this, 'geometry', function () {
38440               return graph.isPoi(this) ? 'point' : 'vertex';
38441             });
38442           },
38443           move: function move(loc) {
38444             return this.update({
38445               loc: loc
38446             });
38447           },
38448           isDegenerate: function isDegenerate() {
38449             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);
38450           },
38451           // Inspect tags and geometry to determine which direction(s) this node/vertex points
38452           directions: function directions(resolver, projection) {
38453             var val;
38454             var i; // which tag to use?
38455
38456             if (this.isHighwayIntersection(resolver) && (this.tags.stop || '').toLowerCase() === 'all') {
38457               // all-way stop tag on a highway intersection
38458               val = 'all';
38459             } else {
38460               // generic direction tag
38461               val = (this.tags.direction || '').toLowerCase(); // better suffix-style direction tag
38462
38463               var re = /:direction$/i;
38464               var keys = Object.keys(this.tags);
38465
38466               for (i = 0; i < keys.length; i++) {
38467                 if (re.test(keys[i])) {
38468                   val = this.tags[keys[i]].toLowerCase();
38469                   break;
38470                 }
38471               }
38472             }
38473
38474             if (val === '') return [];
38475             var cardinal = {
38476               north: 0,
38477               n: 0,
38478               northnortheast: 22,
38479               nne: 22,
38480               northeast: 45,
38481               ne: 45,
38482               eastnortheast: 67,
38483               ene: 67,
38484               east: 90,
38485               e: 90,
38486               eastsoutheast: 112,
38487               ese: 112,
38488               southeast: 135,
38489               se: 135,
38490               southsoutheast: 157,
38491               sse: 157,
38492               south: 180,
38493               s: 180,
38494               southsouthwest: 202,
38495               ssw: 202,
38496               southwest: 225,
38497               sw: 225,
38498               westsouthwest: 247,
38499               wsw: 247,
38500               west: 270,
38501               w: 270,
38502               westnorthwest: 292,
38503               wnw: 292,
38504               northwest: 315,
38505               nw: 315,
38506               northnorthwest: 337,
38507               nnw: 337
38508             };
38509             var values = val.split(';');
38510             var results = [];
38511             values.forEach(function (v) {
38512               // swap cardinal for numeric directions
38513               if (cardinal[v] !== undefined) {
38514                 v = cardinal[v];
38515               } // numeric direction - just add to results
38516
38517
38518               if (v !== '' && !isNaN(+v)) {
38519                 results.push(+v);
38520                 return;
38521               } // string direction - inspect parent ways
38522
38523
38524               var lookBackward = this.tags['traffic_sign:backward'] || v === 'backward' || v === 'both' || v === 'all';
38525               var lookForward = this.tags['traffic_sign:forward'] || v === 'forward' || v === 'both' || v === 'all';
38526               if (!lookForward && !lookBackward) return;
38527               var nodeIds = {};
38528               resolver.parentWays(this).forEach(function (parent) {
38529                 var nodes = parent.nodes;
38530
38531                 for (i = 0; i < nodes.length; i++) {
38532                   if (nodes[i] === this.id) {
38533                     // match current entity
38534                     if (lookForward && i > 0) {
38535                       nodeIds[nodes[i - 1]] = true; // look back to prev node
38536                     }
38537
38538                     if (lookBackward && i < nodes.length - 1) {
38539                       nodeIds[nodes[i + 1]] = true; // look ahead to next node
38540                     }
38541                   }
38542                 }
38543               }, this);
38544               Object.keys(nodeIds).forEach(function (nodeId) {
38545                 // +90 because geoAngle returns angle from X axis, not Y (north)
38546                 results.push(geoAngle(this, resolver.entity(nodeId), projection) * (180 / Math.PI) + 90);
38547               }, this);
38548             }, this);
38549             return utilArrayUniq(results);
38550           },
38551           isCrossing: function isCrossing() {
38552             return this.tags.highway === 'crossing' || this.tags.railway && this.tags.railway.indexOf('crossing') !== -1;
38553           },
38554           isEndpoint: function isEndpoint(resolver) {
38555             return resolver["transient"](this, 'isEndpoint', function () {
38556               var id = this.id;
38557               return resolver.parentWays(this).filter(function (parent) {
38558                 return !parent.isClosed() && !!parent.affix(id);
38559               }).length > 0;
38560             });
38561           },
38562           isConnected: function isConnected(resolver) {
38563             return resolver["transient"](this, 'isConnected', function () {
38564               var parents = resolver.parentWays(this);
38565
38566               if (parents.length > 1) {
38567                 // vertex is connected to multiple parent ways
38568                 for (var i in parents) {
38569                   if (parents[i].geometry(resolver) === 'line' && parents[i].hasInterestingTags()) return true;
38570                 }
38571               } else if (parents.length === 1) {
38572                 var way = parents[0];
38573                 var nodes = way.nodes.slice();
38574
38575                 if (way.isClosed()) {
38576                   nodes.pop();
38577                 } // ignore connecting node if closed
38578                 // return true if vertex appears multiple times (way is self intersecting)
38579
38580
38581                 return nodes.indexOf(this.id) !== nodes.lastIndexOf(this.id);
38582               }
38583
38584               return false;
38585             });
38586           },
38587           parentIntersectionWays: function parentIntersectionWays(resolver) {
38588             return resolver["transient"](this, 'parentIntersectionWays', function () {
38589               return resolver.parentWays(this).filter(function (parent) {
38590                 return (parent.tags.highway || parent.tags.waterway || parent.tags.railway || parent.tags.aeroway) && parent.geometry(resolver) === 'line';
38591               });
38592             });
38593           },
38594           isIntersection: function isIntersection(resolver) {
38595             return this.parentIntersectionWays(resolver).length > 1;
38596           },
38597           isHighwayIntersection: function isHighwayIntersection(resolver) {
38598             return resolver["transient"](this, 'isHighwayIntersection', function () {
38599               return resolver.parentWays(this).filter(function (parent) {
38600                 return parent.tags.highway && parent.geometry(resolver) === 'line';
38601               }).length > 1;
38602             });
38603           },
38604           isOnAddressLine: function isOnAddressLine(resolver) {
38605             return resolver["transient"](this, 'isOnAddressLine', function () {
38606               return resolver.parentWays(this).filter(function (parent) {
38607                 return parent.tags.hasOwnProperty('addr:interpolation') && parent.geometry(resolver) === 'line';
38608               }).length > 0;
38609             });
38610           },
38611           asJXON: function asJXON(changeset_id) {
38612             var r = {
38613               node: {
38614                 '@id': this.osmId(),
38615                 '@lon': this.loc[0],
38616                 '@lat': this.loc[1],
38617                 '@version': this.version || 0,
38618                 tag: Object.keys(this.tags).map(function (k) {
38619                   return {
38620                     keyAttributes: {
38621                       k: k,
38622                       v: this.tags[k]
38623                     }
38624                   };
38625                 }, this)
38626               }
38627             };
38628             if (changeset_id) r.node['@changeset'] = changeset_id;
38629             return r;
38630           },
38631           asGeoJSON: function asGeoJSON() {
38632             return {
38633               type: 'Point',
38634               coordinates: this.loc
38635             };
38636           }
38637         });
38638
38639         function actionCircularize(wayId, projection, maxAngle) {
38640           maxAngle = (maxAngle || 20) * Math.PI / 180;
38641
38642           var action = function action(graph, t) {
38643             if (t === null || !isFinite(t)) t = 1;
38644             t = Math.min(Math.max(+t, 0), 1);
38645             var way = graph.entity(wayId);
38646             var origNodes = {};
38647             graph.childNodes(way).forEach(function (node) {
38648               if (!origNodes[node.id]) origNodes[node.id] = node;
38649             });
38650
38651             if (!way.isConvex(graph)) {
38652               graph = action.makeConvex(graph);
38653             }
38654
38655             var nodes = utilArrayUniq(graph.childNodes(way));
38656             var keyNodes = nodes.filter(function (n) {
38657               return graph.parentWays(n).length !== 1;
38658             });
38659             var points = nodes.map(function (n) {
38660               return projection(n.loc);
38661             });
38662             var keyPoints = keyNodes.map(function (n) {
38663               return projection(n.loc);
38664             });
38665             var centroid = points.length === 2 ? geoVecInterp(points[0], points[1], 0.5) : d3_polygonCentroid(points);
38666             var radius = d3_median(points, function (p) {
38667               return geoVecLength(centroid, p);
38668             });
38669             var sign = d3_polygonArea(points) > 0 ? 1 : -1;
38670             var ids, i, j, k; // we need at least two key nodes for the algorithm to work
38671
38672             if (!keyNodes.length) {
38673               keyNodes = [nodes[0]];
38674               keyPoints = [points[0]];
38675             }
38676
38677             if (keyNodes.length === 1) {
38678               var index = nodes.indexOf(keyNodes[0]);
38679               var oppositeIndex = Math.floor((index + nodes.length / 2) % nodes.length);
38680               keyNodes.push(nodes[oppositeIndex]);
38681               keyPoints.push(points[oppositeIndex]);
38682             } // key points and nodes are those connected to the ways,
38683             // they are projected onto the circle, in between nodes are moved
38684             // to constant intervals between key nodes, extra in between nodes are
38685             // added if necessary.
38686
38687
38688             for (i = 0; i < keyPoints.length; i++) {
38689               var nextKeyNodeIndex = (i + 1) % keyNodes.length;
38690               var startNode = keyNodes[i];
38691               var endNode = keyNodes[nextKeyNodeIndex];
38692               var startNodeIndex = nodes.indexOf(startNode);
38693               var endNodeIndex = nodes.indexOf(endNode);
38694               var numberNewPoints = -1;
38695               var indexRange = endNodeIndex - startNodeIndex;
38696               var nearNodes = {};
38697               var inBetweenNodes = [];
38698               var startAngle, endAngle, totalAngle, eachAngle;
38699               var angle, loc, node, origNode;
38700
38701               if (indexRange < 0) {
38702                 indexRange += nodes.length;
38703               } // position this key node
38704
38705
38706               var distance = geoVecLength(centroid, keyPoints[i]) || 1e-4;
38707               keyPoints[i] = [centroid[0] + (keyPoints[i][0] - centroid[0]) / distance * radius, centroid[1] + (keyPoints[i][1] - centroid[1]) / distance * radius];
38708               loc = projection.invert(keyPoints[i]);
38709               node = keyNodes[i];
38710               origNode = origNodes[node.id];
38711               node = node.move(geoVecInterp(origNode.loc, loc, t));
38712               graph = graph.replace(node); // figure out the between delta angle we want to match to
38713
38714               startAngle = Math.atan2(keyPoints[i][1] - centroid[1], keyPoints[i][0] - centroid[0]);
38715               endAngle = Math.atan2(keyPoints[nextKeyNodeIndex][1] - centroid[1], keyPoints[nextKeyNodeIndex][0] - centroid[0]);
38716               totalAngle = endAngle - startAngle; // detects looping around -pi/pi
38717
38718               if (totalAngle * sign > 0) {
38719                 totalAngle = -sign * (2 * Math.PI - Math.abs(totalAngle));
38720               }
38721
38722               do {
38723                 numberNewPoints++;
38724                 eachAngle = totalAngle / (indexRange + numberNewPoints);
38725               } while (Math.abs(eachAngle) > maxAngle); // move existing nodes
38726
38727
38728               for (j = 1; j < indexRange; j++) {
38729                 angle = startAngle + j * eachAngle;
38730                 loc = projection.invert([centroid[0] + Math.cos(angle) * radius, centroid[1] + Math.sin(angle) * radius]);
38731                 node = nodes[(j + startNodeIndex) % nodes.length];
38732                 origNode = origNodes[node.id];
38733                 nearNodes[node.id] = angle;
38734                 node = node.move(geoVecInterp(origNode.loc, loc, t));
38735                 graph = graph.replace(node);
38736               } // add new in between nodes if necessary
38737
38738
38739               for (j = 0; j < numberNewPoints; j++) {
38740                 angle = startAngle + (indexRange + j) * eachAngle;
38741                 loc = projection.invert([centroid[0] + Math.cos(angle) * radius, centroid[1] + Math.sin(angle) * radius]); // choose a nearnode to use as the original
38742
38743                 var min = Infinity;
38744
38745                 for (var nodeId in nearNodes) {
38746                   var nearAngle = nearNodes[nodeId];
38747                   var dist = Math.abs(nearAngle - angle);
38748
38749                   if (dist < min) {
38750                     min = dist;
38751                     origNode = origNodes[nodeId];
38752                   }
38753                 }
38754
38755                 node = osmNode({
38756                   loc: geoVecInterp(origNode.loc, loc, t)
38757                 });
38758                 graph = graph.replace(node);
38759                 nodes.splice(endNodeIndex + j, 0, node);
38760                 inBetweenNodes.push(node.id);
38761               } // Check for other ways that share these keyNodes..
38762               // If keyNodes are adjacent in both ways,
38763               // we can add inBetweenNodes to that shared way too..
38764
38765
38766               if (indexRange === 1 && inBetweenNodes.length) {
38767                 var startIndex1 = way.nodes.lastIndexOf(startNode.id);
38768                 var endIndex1 = way.nodes.lastIndexOf(endNode.id);
38769                 var wayDirection1 = endIndex1 - startIndex1;
38770
38771                 if (wayDirection1 < -1) {
38772                   wayDirection1 = 1;
38773                 }
38774
38775                 var parentWays = graph.parentWays(keyNodes[i]);
38776
38777                 for (j = 0; j < parentWays.length; j++) {
38778                   var sharedWay = parentWays[j];
38779                   if (sharedWay === way) continue;
38780
38781                   if (sharedWay.areAdjacent(startNode.id, endNode.id)) {
38782                     var startIndex2 = sharedWay.nodes.lastIndexOf(startNode.id);
38783                     var endIndex2 = sharedWay.nodes.lastIndexOf(endNode.id);
38784                     var wayDirection2 = endIndex2 - startIndex2;
38785                     var insertAt = endIndex2;
38786
38787                     if (wayDirection2 < -1) {
38788                       wayDirection2 = 1;
38789                     }
38790
38791                     if (wayDirection1 !== wayDirection2) {
38792                       inBetweenNodes.reverse();
38793                       insertAt = startIndex2;
38794                     }
38795
38796                     for (k = 0; k < inBetweenNodes.length; k++) {
38797                       sharedWay = sharedWay.addNode(inBetweenNodes[k], insertAt + k);
38798                     }
38799
38800                     graph = graph.replace(sharedWay);
38801                   }
38802                 }
38803               }
38804             } // update the way to have all the new nodes
38805
38806
38807             ids = nodes.map(function (n) {
38808               return n.id;
38809             });
38810             ids.push(ids[0]);
38811             way = way.update({
38812               nodes: ids
38813             });
38814             graph = graph.replace(way);
38815             return graph;
38816           };
38817
38818           action.makeConvex = function (graph) {
38819             var way = graph.entity(wayId);
38820             var nodes = utilArrayUniq(graph.childNodes(way));
38821             var points = nodes.map(function (n) {
38822               return projection(n.loc);
38823             });
38824             var sign = d3_polygonArea(points) > 0 ? 1 : -1;
38825             var hull = d3_polygonHull(points);
38826             var i, j; // D3 convex hulls go counterclockwise..
38827
38828             if (sign === -1) {
38829               nodes.reverse();
38830               points.reverse();
38831             }
38832
38833             for (i = 0; i < hull.length - 1; i++) {
38834               var startIndex = points.indexOf(hull[i]);
38835               var endIndex = points.indexOf(hull[i + 1]);
38836               var indexRange = endIndex - startIndex;
38837
38838               if (indexRange < 0) {
38839                 indexRange += nodes.length;
38840               } // move interior nodes to the surface of the convex hull..
38841
38842
38843               for (j = 1; j < indexRange; j++) {
38844                 var point = geoVecInterp(hull[i], hull[i + 1], j / indexRange);
38845                 var node = nodes[(j + startIndex) % nodes.length].move(projection.invert(point));
38846                 graph = graph.replace(node);
38847               }
38848             }
38849
38850             return graph;
38851           };
38852
38853           action.disabled = function (graph) {
38854             if (!graph.entity(wayId).isClosed()) {
38855               return 'not_closed';
38856             } //disable when already circular
38857
38858
38859             var way = graph.entity(wayId);
38860             var nodes = utilArrayUniq(graph.childNodes(way));
38861             var points = nodes.map(function (n) {
38862               return projection(n.loc);
38863             });
38864             var hull = d3_polygonHull(points);
38865             var epsilonAngle = Math.PI / 180;
38866
38867             if (hull.length !== points.length || hull.length < 3) {
38868               return false;
38869             }
38870
38871             var centroid = d3_polygonCentroid(points);
38872             var radius = geoVecLengthSquare(centroid, points[0]);
38873             var i, actualPoint; // compare distances between centroid and points
38874
38875             for (i = 0; i < hull.length; i++) {
38876               actualPoint = hull[i];
38877               var actualDist = geoVecLengthSquare(actualPoint, centroid);
38878               var diff = Math.abs(actualDist - radius); //compare distances with epsilon-error (5%)
38879
38880               if (diff > 0.05 * radius) {
38881                 return false;
38882               }
38883             } //check if central angles are smaller than maxAngle
38884
38885
38886             for (i = 0; i < hull.length; i++) {
38887               actualPoint = hull[i];
38888               var nextPoint = hull[(i + 1) % hull.length];
38889               var startAngle = Math.atan2(actualPoint[1] - centroid[1], actualPoint[0] - centroid[0]);
38890               var endAngle = Math.atan2(nextPoint[1] - centroid[1], nextPoint[0] - centroid[0]);
38891               var angle = endAngle - startAngle;
38892
38893               if (angle < 0) {
38894                 angle = -angle;
38895               }
38896
38897               if (angle > Math.PI) {
38898                 angle = 2 * Math.PI - angle;
38899               }
38900
38901               if (angle > maxAngle + epsilonAngle) {
38902                 return false;
38903               }
38904             }
38905
38906             return 'already_circular';
38907           };
38908
38909           action.transitionable = true;
38910           return action;
38911         }
38912
38913         function actionDeleteWay(wayID) {
38914           function canDeleteNode(node, graph) {
38915             // don't delete nodes still attached to ways or relations
38916             if (graph.parentWays(node).length || graph.parentRelations(node).length) return false;
38917             var geometries = osmNodeGeometriesForTags(node.tags); // don't delete if this node can be a standalone point
38918
38919             if (geometries.point) return false; // delete if this node only be a vertex
38920
38921             if (geometries.vertex) return true; // iD doesn't know if this should be a point or vertex,
38922             // so only delete if there are no interesting tags
38923
38924             return !node.hasInterestingTags();
38925           }
38926
38927           var action = function action(graph) {
38928             var way = graph.entity(wayID);
38929             graph.parentRelations(way).forEach(function (parent) {
38930               parent = parent.removeMembersWithID(wayID);
38931               graph = graph.replace(parent);
38932
38933               if (parent.isDegenerate()) {
38934                 graph = actionDeleteRelation(parent.id)(graph);
38935               }
38936             });
38937             new Set(way.nodes).forEach(function (nodeID) {
38938               graph = graph.replace(way.removeNode(nodeID));
38939               var node = graph.entity(nodeID);
38940
38941               if (canDeleteNode(node, graph)) {
38942                 graph = graph.remove(node);
38943               }
38944             });
38945             return graph.remove(way);
38946           };
38947
38948           return action;
38949         }
38950
38951         function actionDeleteMultiple(ids) {
38952           var actions = {
38953             way: actionDeleteWay,
38954             node: actionDeleteNode,
38955             relation: actionDeleteRelation
38956           };
38957
38958           var action = function action(graph) {
38959             ids.forEach(function (id) {
38960               if (graph.hasEntity(id)) {
38961                 // It may have been deleted already.
38962                 graph = actions[graph.entity(id).type](id)(graph);
38963               }
38964             });
38965             return graph;
38966           };
38967
38968           return action;
38969         }
38970
38971         function actionDeleteRelation(relationID, allowUntaggedMembers) {
38972           function canDeleteEntity(entity, graph) {
38973             return !graph.parentWays(entity).length && !graph.parentRelations(entity).length && !entity.hasInterestingTags() && !allowUntaggedMembers;
38974           }
38975
38976           var action = function action(graph) {
38977             var relation = graph.entity(relationID);
38978             graph.parentRelations(relation).forEach(function (parent) {
38979               parent = parent.removeMembersWithID(relationID);
38980               graph = graph.replace(parent);
38981
38982               if (parent.isDegenerate()) {
38983                 graph = actionDeleteRelation(parent.id)(graph);
38984               }
38985             });
38986             var memberIDs = utilArrayUniq(relation.members.map(function (m) {
38987               return m.id;
38988             }));
38989             memberIDs.forEach(function (memberID) {
38990               graph = graph.replace(relation.removeMembersWithID(memberID));
38991               var entity = graph.entity(memberID);
38992
38993               if (canDeleteEntity(entity, graph)) {
38994                 graph = actionDeleteMultiple([memberID])(graph);
38995               }
38996             });
38997             return graph.remove(relation);
38998           };
38999
39000           return action;
39001         }
39002
39003         function actionDeleteNode(nodeId) {
39004           var action = function action(graph) {
39005             var node = graph.entity(nodeId);
39006             graph.parentWays(node).forEach(function (parent) {
39007               parent = parent.removeNode(nodeId);
39008               graph = graph.replace(parent);
39009
39010               if (parent.isDegenerate()) {
39011                 graph = actionDeleteWay(parent.id)(graph);
39012               }
39013             });
39014             graph.parentRelations(node).forEach(function (parent) {
39015               parent = parent.removeMembersWithID(nodeId);
39016               graph = graph.replace(parent);
39017
39018               if (parent.isDegenerate()) {
39019                 graph = actionDeleteRelation(parent.id)(graph);
39020               }
39021             });
39022             return graph.remove(node);
39023           };
39024
39025           return action;
39026         }
39027
39028         //
39029         // First choose a node to be the survivor, with preference given
39030         // to the oldest existing (not new) and "interesting" node.
39031         //
39032         // Tags and relation memberships of of non-surviving nodes are merged
39033         // to the survivor.
39034         //
39035         // This is the inverse of `iD.actionDisconnect`.
39036         //
39037         // Reference:
39038         //   https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeNodesAction.as
39039         //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/MergeNodesAction.java
39040         //
39041
39042         function actionConnect(nodeIDs) {
39043           var action = function action(graph) {
39044             var survivor;
39045             var node;
39046             var parents;
39047             var i, j; // Select the node with the ID passed as parameter if it is in the list,
39048             // otherwise select the node with the oldest ID as the survivor, or the
39049             // last one if there are only new nodes.
39050
39051             nodeIDs.reverse();
39052             var interestingIDs = [];
39053
39054             for (i = 0; i < nodeIDs.length; i++) {
39055               node = graph.entity(nodeIDs[i]);
39056
39057               if (node.hasInterestingTags()) {
39058                 if (!node.isNew()) {
39059                   interestingIDs.push(node.id);
39060                 }
39061               }
39062             }
39063
39064             survivor = graph.entity(utilOldestID(interestingIDs.length > 0 ? interestingIDs : nodeIDs)); // Replace all non-surviving nodes with the survivor and merge tags.
39065
39066             for (i = 0; i < nodeIDs.length; i++) {
39067               node = graph.entity(nodeIDs[i]);
39068               if (node.id === survivor.id) continue;
39069               parents = graph.parentWays(node);
39070
39071               for (j = 0; j < parents.length; j++) {
39072                 graph = graph.replace(parents[j].replaceNode(node.id, survivor.id));
39073               }
39074
39075               parents = graph.parentRelations(node);
39076
39077               for (j = 0; j < parents.length; j++) {
39078                 graph = graph.replace(parents[j].replaceMember(node, survivor));
39079               }
39080
39081               survivor = survivor.mergeTags(node.tags);
39082               graph = actionDeleteNode(node.id)(graph);
39083             }
39084
39085             graph = graph.replace(survivor); // find and delete any degenerate ways created by connecting adjacent vertices
39086
39087             parents = graph.parentWays(survivor);
39088
39089             for (i = 0; i < parents.length; i++) {
39090               if (parents[i].isDegenerate()) {
39091                 graph = actionDeleteWay(parents[i].id)(graph);
39092               }
39093             }
39094
39095             return graph;
39096           };
39097
39098           action.disabled = function (graph) {
39099             var seen = {};
39100             var restrictionIDs = [];
39101             var survivor;
39102             var node, way;
39103             var relations, relation, role;
39104             var i, j, k; // Select the node with the oldest ID as the survivor.
39105
39106             survivor = graph.entity(utilOldestID(nodeIDs)); // 1. disable if the nodes being connected have conflicting relation roles
39107
39108             for (i = 0; i < nodeIDs.length; i++) {
39109               node = graph.entity(nodeIDs[i]);
39110               relations = graph.parentRelations(node);
39111
39112               for (j = 0; j < relations.length; j++) {
39113                 relation = relations[j];
39114                 role = relation.memberById(node.id).role || ''; // if this node is a via node in a restriction, remember for later
39115
39116                 if (relation.hasFromViaTo()) {
39117                   restrictionIDs.push(relation.id);
39118                 }
39119
39120                 if (seen[relation.id] !== undefined && seen[relation.id] !== role) {
39121                   return 'relation';
39122                 } else {
39123                   seen[relation.id] = role;
39124                 }
39125               }
39126             } // gather restrictions for parent ways
39127
39128
39129             for (i = 0; i < nodeIDs.length; i++) {
39130               node = graph.entity(nodeIDs[i]);
39131               var parents = graph.parentWays(node);
39132
39133               for (j = 0; j < parents.length; j++) {
39134                 var parent = parents[j];
39135                 relations = graph.parentRelations(parent);
39136
39137                 for (k = 0; k < relations.length; k++) {
39138                   relation = relations[k];
39139
39140                   if (relation.hasFromViaTo()) {
39141                     restrictionIDs.push(relation.id);
39142                   }
39143                 }
39144               }
39145             } // test restrictions
39146
39147
39148             restrictionIDs = utilArrayUniq(restrictionIDs);
39149
39150             for (i = 0; i < restrictionIDs.length; i++) {
39151               relation = graph.entity(restrictionIDs[i]);
39152               if (!relation.isComplete(graph)) continue;
39153               var memberWays = relation.members.filter(function (m) {
39154                 return m.type === 'way';
39155               }).map(function (m) {
39156                 return graph.entity(m.id);
39157               });
39158               memberWays = utilArrayUniq(memberWays);
39159               var f = relation.memberByRole('from');
39160               var t = relation.memberByRole('to');
39161               var isUturn = f.id === t.id; // 2a. disable if connection would damage a restriction
39162               // (a key node is a node at the junction of ways)
39163
39164               var nodes = {
39165                 from: [],
39166                 via: [],
39167                 to: [],
39168                 keyfrom: [],
39169                 keyto: []
39170               };
39171
39172               for (j = 0; j < relation.members.length; j++) {
39173                 collectNodes(relation.members[j], nodes);
39174               }
39175
39176               nodes.keyfrom = utilArrayUniq(nodes.keyfrom.filter(hasDuplicates));
39177               nodes.keyto = utilArrayUniq(nodes.keyto.filter(hasDuplicates));
39178               var filter = keyNodeFilter(nodes.keyfrom, nodes.keyto);
39179               nodes.from = nodes.from.filter(filter);
39180               nodes.via = nodes.via.filter(filter);
39181               nodes.to = nodes.to.filter(filter);
39182               var connectFrom = false;
39183               var connectVia = false;
39184               var connectTo = false;
39185               var connectKeyFrom = false;
39186               var connectKeyTo = false;
39187
39188               for (j = 0; j < nodeIDs.length; j++) {
39189                 var n = nodeIDs[j];
39190
39191                 if (nodes.from.indexOf(n) !== -1) {
39192                   connectFrom = true;
39193                 }
39194
39195                 if (nodes.via.indexOf(n) !== -1) {
39196                   connectVia = true;
39197                 }
39198
39199                 if (nodes.to.indexOf(n) !== -1) {
39200                   connectTo = true;
39201                 }
39202
39203                 if (nodes.keyfrom.indexOf(n) !== -1) {
39204                   connectKeyFrom = true;
39205                 }
39206
39207                 if (nodes.keyto.indexOf(n) !== -1) {
39208                   connectKeyTo = true;
39209                 }
39210               }
39211
39212               if (connectFrom && connectTo && !isUturn) {
39213                 return 'restriction';
39214               }
39215
39216               if (connectFrom && connectVia) {
39217                 return 'restriction';
39218               }
39219
39220               if (connectTo && connectVia) {
39221                 return 'restriction';
39222               } // connecting to a key node -
39223               // if both nodes are on a member way (i.e. part of the turn restriction),
39224               // the connecting node must be adjacent to the key node.
39225
39226
39227               if (connectKeyFrom || connectKeyTo) {
39228                 if (nodeIDs.length !== 2) {
39229                   return 'restriction';
39230                 }
39231
39232                 var n0 = null;
39233                 var n1 = null;
39234
39235                 for (j = 0; j < memberWays.length; j++) {
39236                   way = memberWays[j];
39237
39238                   if (way.contains(nodeIDs[0])) {
39239                     n0 = nodeIDs[0];
39240                   }
39241
39242                   if (way.contains(nodeIDs[1])) {
39243                     n1 = nodeIDs[1];
39244                   }
39245                 }
39246
39247                 if (n0 && n1) {
39248                   // both nodes are part of the restriction
39249                   var ok = false;
39250
39251                   for (j = 0; j < memberWays.length; j++) {
39252                     way = memberWays[j];
39253
39254                     if (way.areAdjacent(n0, n1)) {
39255                       ok = true;
39256                       break;
39257                     }
39258                   }
39259
39260                   if (!ok) {
39261                     return 'restriction';
39262                   }
39263                 }
39264               } // 2b. disable if nodes being connected will destroy a member way in a restriction
39265               // (to test, make a copy and try actually connecting the nodes)
39266
39267
39268               for (j = 0; j < memberWays.length; j++) {
39269                 way = memberWays[j].update({}); // make copy
39270
39271                 for (k = 0; k < nodeIDs.length; k++) {
39272                   if (nodeIDs[k] === survivor.id) continue;
39273
39274                   if (way.areAdjacent(nodeIDs[k], survivor.id)) {
39275                     way = way.removeNode(nodeIDs[k]);
39276                   } else {
39277                     way = way.replaceNode(nodeIDs[k], survivor.id);
39278                   }
39279                 }
39280
39281                 if (way.isDegenerate()) {
39282                   return 'restriction';
39283                 }
39284               }
39285             }
39286
39287             return false; // if a key node appears multiple times (indexOf !== lastIndexOf) it's a FROM-VIA or TO-VIA junction
39288
39289             function hasDuplicates(n, i, arr) {
39290               return arr.indexOf(n) !== arr.lastIndexOf(n);
39291             }
39292
39293             function keyNodeFilter(froms, tos) {
39294               return function (n) {
39295                 return froms.indexOf(n) === -1 && tos.indexOf(n) === -1;
39296               };
39297             }
39298
39299             function collectNodes(member, collection) {
39300               var entity = graph.hasEntity(member.id);
39301               if (!entity) return;
39302               var role = member.role || '';
39303
39304               if (!collection[role]) {
39305                 collection[role] = [];
39306               }
39307
39308               if (member.type === 'node') {
39309                 collection[role].push(member.id);
39310
39311                 if (role === 'via') {
39312                   collection.keyfrom.push(member.id);
39313                   collection.keyto.push(member.id);
39314                 }
39315               } else if (member.type === 'way') {
39316                 collection[role].push.apply(collection[role], entity.nodes);
39317
39318                 if (role === 'from' || role === 'via') {
39319                   collection.keyfrom.push(entity.first());
39320                   collection.keyfrom.push(entity.last());
39321                 }
39322
39323                 if (role === 'to' || role === 'via') {
39324                   collection.keyto.push(entity.first());
39325                   collection.keyto.push(entity.last());
39326                 }
39327               }
39328             }
39329           };
39330
39331           return action;
39332         }
39333
39334         function actionCopyEntities(ids, fromGraph) {
39335           var _copies = {};
39336
39337           var action = function action(graph) {
39338             ids.forEach(function (id) {
39339               fromGraph.entity(id).copy(fromGraph, _copies);
39340             });
39341
39342             for (var id in _copies) {
39343               graph = graph.replace(_copies[id]);
39344             }
39345
39346             return graph;
39347           };
39348
39349           action.copies = function () {
39350             return _copies;
39351           };
39352
39353           return action;
39354         }
39355
39356         function actionDeleteMember(relationId, memberIndex) {
39357           return function (graph) {
39358             var relation = graph.entity(relationId).removeMember(memberIndex);
39359             graph = graph.replace(relation);
39360
39361             if (relation.isDegenerate()) {
39362               graph = actionDeleteRelation(relation.id)(graph);
39363             }
39364
39365             return graph;
39366           };
39367         }
39368
39369         function actionDiscardTags(difference, discardTags) {
39370           discardTags = discardTags || {};
39371           return function (graph) {
39372             difference.modified().forEach(checkTags);
39373             difference.created().forEach(checkTags);
39374             return graph;
39375
39376             function checkTags(entity) {
39377               var keys = Object.keys(entity.tags);
39378               var didDiscard = false;
39379               var tags = {};
39380
39381               for (var i = 0; i < keys.length; i++) {
39382                 var k = keys[i];
39383
39384                 if (discardTags[k] || !entity.tags[k]) {
39385                   didDiscard = true;
39386                 } else {
39387                   tags[k] = entity.tags[k];
39388                 }
39389               }
39390
39391               if (didDiscard) {
39392                 graph = graph.replace(entity.update({
39393                   tags: tags
39394                 }));
39395               }
39396             }
39397           };
39398         }
39399
39400         //
39401         // Optionally, disconnect only the given ways.
39402         //
39403         // For testing convenience, accepts an ID to assign to the (first) new node.
39404         // Normally, this will be undefined and the way will automatically
39405         // be assigned a new ID.
39406         //
39407         // This is the inverse of `iD.actionConnect`.
39408         //
39409         // Reference:
39410         //   https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as
39411         //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/UnGlueAction.java
39412         //
39413
39414         function actionDisconnect(nodeId, newNodeId) {
39415           var wayIds;
39416           var disconnectableRelationTypes = {
39417             'associatedStreet': true,
39418             'enforcement': true,
39419             'site': true
39420           };
39421
39422           var action = function action(graph) {
39423             var node = graph.entity(nodeId);
39424             var connections = action.connections(graph);
39425             connections.forEach(function (connection) {
39426               var way = graph.entity(connection.wayID);
39427               var newNode = osmNode({
39428                 id: newNodeId,
39429                 loc: node.loc,
39430                 tags: node.tags
39431               });
39432               graph = graph.replace(newNode);
39433
39434               if (connection.index === 0 && way.isArea()) {
39435                 // replace shared node with shared node..
39436                 graph = graph.replace(way.replaceNode(way.nodes[0], newNode.id));
39437               } else if (way.isClosed() && connection.index === way.nodes.length - 1) {
39438                 // replace closing node with new new node..
39439                 graph = graph.replace(way.unclose().addNode(newNode.id));
39440               } else {
39441                 // replace shared node with multiple new nodes..
39442                 graph = graph.replace(way.updateNode(newNode.id, connection.index));
39443               }
39444             });
39445             return graph;
39446           };
39447
39448           action.connections = function (graph) {
39449             var candidates = [];
39450             var keeping = false;
39451             var parentWays = graph.parentWays(graph.entity(nodeId));
39452             var way, waynode;
39453
39454             for (var i = 0; i < parentWays.length; i++) {
39455               way = parentWays[i];
39456
39457               if (wayIds && wayIds.indexOf(way.id) === -1) {
39458                 keeping = true;
39459                 continue;
39460               }
39461
39462               if (way.isArea() && way.nodes[0] === nodeId) {
39463                 candidates.push({
39464                   wayID: way.id,
39465                   index: 0
39466                 });
39467               } else {
39468                 for (var j = 0; j < way.nodes.length; j++) {
39469                   waynode = way.nodes[j];
39470
39471                   if (waynode === nodeId) {
39472                     if (way.isClosed() && parentWays.length > 1 && wayIds && wayIds.indexOf(way.id) !== -1 && j === way.nodes.length - 1) {
39473                       continue;
39474                     }
39475
39476                     candidates.push({
39477                       wayID: way.id,
39478                       index: j
39479                     });
39480                   }
39481                 }
39482               }
39483             }
39484
39485             return keeping ? candidates : candidates.slice(1);
39486           };
39487
39488           action.disabled = function (graph) {
39489             var connections = action.connections(graph);
39490             if (connections.length === 0) return 'not_connected';
39491             var parentWays = graph.parentWays(graph.entity(nodeId));
39492             var seenRelationIds = {};
39493             var sharedRelation;
39494             parentWays.forEach(function (way) {
39495               var relations = graph.parentRelations(way);
39496               relations.filter(function (relation) {
39497                 return !disconnectableRelationTypes[relation.tags.type];
39498               }).forEach(function (relation) {
39499                 if (relation.id in seenRelationIds) {
39500                   if (wayIds) {
39501                     if (wayIds.indexOf(way.id) !== -1 || wayIds.indexOf(seenRelationIds[relation.id]) !== -1) {
39502                       sharedRelation = relation;
39503                     }
39504                   } else {
39505                     sharedRelation = relation;
39506                   }
39507                 } else {
39508                   seenRelationIds[relation.id] = way.id;
39509                 }
39510               });
39511             });
39512             if (sharedRelation) return 'relation';
39513           };
39514
39515           action.limitWays = function (val) {
39516             if (!arguments.length) return wayIds;
39517             wayIds = val;
39518             return action;
39519           };
39520
39521           return action;
39522         }
39523
39524         function actionExtract(entityID, projection) {
39525           var extractedNodeID;
39526
39527           var action = function action(graph) {
39528             var entity = graph.entity(entityID);
39529
39530             if (entity.type === 'node') {
39531               return extractFromNode(entity, graph);
39532             }
39533
39534             return extractFromWayOrRelation(entity, graph);
39535           };
39536
39537           function extractFromNode(node, graph) {
39538             extractedNodeID = node.id; // Create a new node to replace the one we will detach
39539
39540             var replacement = osmNode({
39541               loc: node.loc
39542             });
39543             graph = graph.replace(replacement); // Process each way in turn, updating the graph as we go
39544
39545             graph = graph.parentWays(node).reduce(function (accGraph, parentWay) {
39546               return accGraph.replace(parentWay.replaceNode(entityID, replacement.id));
39547             }, graph); // Process any relations too
39548
39549             return graph.parentRelations(node).reduce(function (accGraph, parentRel) {
39550               return accGraph.replace(parentRel.replaceMember(node, replacement));
39551             }, graph);
39552           }
39553
39554           function extractFromWayOrRelation(entity, graph) {
39555             var fromGeometry = entity.geometry(graph);
39556             var keysToCopyAndRetain = ['source', 'wheelchair'];
39557             var keysToRetain = ['area'];
39558             var buildingKeysToRetain = ['architect', 'building', 'height', 'layer'];
39559             var extractedLoc = d3_geoPath(projection).centroid(entity.asGeoJSON(graph));
39560             extractedLoc = extractedLoc && projection.invert(extractedLoc);
39561
39562             if (!extractedLoc || !isFinite(extractedLoc[0]) || !isFinite(extractedLoc[1])) {
39563               extractedLoc = entity.extent(graph).center();
39564             }
39565
39566             var indoorAreaValues = {
39567               area: true,
39568               corridor: true,
39569               elevator: true,
39570               level: true,
39571               room: true
39572             };
39573             var isBuilding = entity.tags.building && entity.tags.building !== 'no' || entity.tags['building:part'] && entity.tags['building:part'] !== 'no';
39574             var isIndoorArea = fromGeometry === 'area' && entity.tags.indoor && indoorAreaValues[entity.tags.indoor];
39575             var entityTags = Object.assign({}, entity.tags); // shallow copy
39576
39577             var pointTags = {};
39578
39579             for (var key in entityTags) {
39580               if (entity.type === 'relation' && key === 'type') {
39581                 continue;
39582               }
39583
39584               if (keysToRetain.indexOf(key) !== -1) {
39585                 continue;
39586               }
39587
39588               if (isBuilding) {
39589                 // don't transfer building-related tags
39590                 if (buildingKeysToRetain.indexOf(key) !== -1 || key.match(/^building:.{1,}/) || key.match(/^roof:.{1,}/)) continue;
39591               } // leave `indoor` tag on the area
39592
39593
39594               if (isIndoorArea && key === 'indoor') {
39595                 continue;
39596               } // copy the tag from the entity to the point
39597
39598
39599               pointTags[key] = entityTags[key]; // leave addresses and some other tags so they're on both features
39600
39601               if (keysToCopyAndRetain.indexOf(key) !== -1 || key.match(/^addr:.{1,}/)) {
39602                 continue;
39603               } else if (isIndoorArea && key === 'level') {
39604                 // leave `level` on both features
39605                 continue;
39606               } // remove the tag from the entity
39607
39608
39609               delete entityTags[key];
39610             }
39611
39612             if (!isBuilding && !isIndoorArea && fromGeometry === 'area') {
39613               // ensure that areas keep area geometry
39614               entityTags.area = 'yes';
39615             }
39616
39617             var replacement = osmNode({
39618               loc: extractedLoc,
39619               tags: pointTags
39620             });
39621             graph = graph.replace(replacement);
39622             extractedNodeID = replacement.id;
39623             return graph.replace(entity.update({
39624               tags: entityTags
39625             }));
39626           }
39627
39628           action.getExtractedNodeID = function () {
39629             return extractedNodeID;
39630           };
39631
39632           return action;
39633         }
39634
39635         //
39636         // This is the inverse of `iD.actionSplit`.
39637         //
39638         // Reference:
39639         //   https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeWaysAction.as
39640         //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/CombineWayAction.java
39641         //
39642
39643         function actionJoin(ids) {
39644           function groupEntitiesByGeometry(graph) {
39645             var entities = ids.map(function (id) {
39646               return graph.entity(id);
39647             });
39648             return Object.assign({
39649               line: []
39650             }, utilArrayGroupBy(entities, function (entity) {
39651               return entity.geometry(graph);
39652             }));
39653           }
39654
39655           var action = function action(graph) {
39656             var ways = ids.map(graph.entity, graph); // Prefer to keep an existing way.
39657             // if there are multiple existing ways, keep the oldest one
39658             // the oldest way is determined by the ID of the way.
39659
39660             var survivorID = utilOldestID(ways.map(function (way) {
39661               return way.id;
39662             })); // if any of the ways are sided (e.g. coastline, cliff, kerb)
39663             // sort them first so they establish the overall order - #6033
39664
39665             ways.sort(function (a, b) {
39666               var aSided = a.isSided();
39667               var bSided = b.isSided();
39668               return aSided && !bSided ? -1 : bSided && !aSided ? 1 : 0;
39669             });
39670             var sequences = osmJoinWays(ways, graph);
39671             var joined = sequences[0]; // We might need to reverse some of these ways before joining them.  #4688
39672             // `joined.actions` property will contain any actions we need to apply.
39673
39674             graph = sequences.actions.reduce(function (g, action) {
39675               return action(g);
39676             }, graph);
39677             var survivor = graph.entity(survivorID);
39678             survivor = survivor.update({
39679               nodes: joined.nodes.map(function (n) {
39680                 return n.id;
39681               })
39682             });
39683             graph = graph.replace(survivor);
39684             joined.forEach(function (way) {
39685               if (way.id === survivorID) return;
39686               graph.parentRelations(way).forEach(function (parent) {
39687                 graph = graph.replace(parent.replaceMember(way, survivor));
39688               });
39689               survivor = survivor.mergeTags(way.tags);
39690               graph = graph.replace(survivor);
39691               graph = actionDeleteWay(way.id)(graph);
39692             }); // Finds if the join created a single-member multipolygon,
39693             // and if so turns it into a basic area instead
39694
39695             function checkForSimpleMultipolygon() {
39696               if (!survivor.isClosed()) return;
39697               var multipolygons = graph.parentMultipolygons(survivor).filter(function (multipolygon) {
39698                 // find multipolygons where the survivor is the only member
39699                 return multipolygon.members.length === 1;
39700               }); // skip if this is the single member of multiple multipolygons
39701
39702               if (multipolygons.length !== 1) return;
39703               var multipolygon = multipolygons[0];
39704
39705               for (var key in survivor.tags) {
39706                 if (multipolygon.tags[key] && // don't collapse if tags cannot be cleanly merged
39707                 multipolygon.tags[key] !== survivor.tags[key]) return;
39708               }
39709
39710               survivor = survivor.mergeTags(multipolygon.tags);
39711               graph = graph.replace(survivor);
39712               graph = actionDeleteRelation(multipolygon.id, true
39713               /* allow untagged members */
39714               )(graph);
39715               var tags = Object.assign({}, survivor.tags);
39716
39717               if (survivor.geometry(graph) !== 'area') {
39718                 // ensure the feature persists as an area
39719                 tags.area = 'yes';
39720               }
39721
39722               delete tags.type; // remove type=multipolygon
39723
39724               survivor = survivor.update({
39725                 tags: tags
39726               });
39727               graph = graph.replace(survivor);
39728             }
39729
39730             checkForSimpleMultipolygon();
39731             return graph;
39732           }; // Returns the number of nodes the resultant way is expected to have
39733
39734
39735           action.resultingWayNodesLength = function (graph) {
39736             return ids.reduce(function (count, id) {
39737               return count + graph.entity(id).nodes.length;
39738             }, 0) - ids.length - 1;
39739           };
39740
39741           action.disabled = function (graph) {
39742             var geometries = groupEntitiesByGeometry(graph);
39743
39744             if (ids.length < 2 || ids.length !== geometries.line.length) {
39745               return 'not_eligible';
39746             }
39747
39748             var joined = osmJoinWays(ids.map(graph.entity, graph), graph);
39749
39750             if (joined.length > 1) {
39751               return 'not_adjacent';
39752             }
39753
39754             var i; // All joined ways must belong to the same set of (non-restriction) relations.
39755             // Restriction relations have different logic, below, which allows some cases
39756             // this prohibits, and prohibits some cases this allows.
39757
39758             var sortedParentRelations = function sortedParentRelations(id) {
39759               return graph.parentRelations(graph.entity(id)).filter(function (rel) {
39760                 return !rel.isRestriction() && !rel.isConnectivity();
39761               }).sort(function (a, b) {
39762                 return a.id - b.id;
39763               });
39764             };
39765
39766             var relsA = sortedParentRelations(ids[0]);
39767
39768             for (i = 1; i < ids.length; i++) {
39769               var relsB = sortedParentRelations(ids[i]);
39770
39771               if (!utilArrayIdentical(relsA, relsB)) {
39772                 return 'conflicting_relations';
39773               }
39774             } // Loop through all combinations of path-pairs
39775             // to check potential intersections between all pairs
39776
39777
39778             for (i = 0; i < ids.length - 1; i++) {
39779               for (var j = i + 1; j < ids.length; j++) {
39780                 var path1 = graph.childNodes(graph.entity(ids[i])).map(function (e) {
39781                   return e.loc;
39782                 });
39783                 var path2 = graph.childNodes(graph.entity(ids[j])).map(function (e) {
39784                   return e.loc;
39785                 });
39786                 var intersections = geoPathIntersections(path1, path2); // Check if intersections are just nodes lying on top of
39787                 // each other/the line, as opposed to crossing it
39788
39789                 var common = utilArrayIntersection(joined[0].nodes.map(function (n) {
39790                   return n.loc.toString();
39791                 }), intersections.map(function (n) {
39792                   return n.toString();
39793                 }));
39794
39795                 if (common.length !== intersections.length) {
39796                   return 'paths_intersect';
39797                 }
39798               }
39799             }
39800
39801             var nodeIds = joined[0].nodes.map(function (n) {
39802               return n.id;
39803             }).slice(1, -1);
39804             var relation;
39805             var tags = {};
39806             var conflicting = false;
39807             joined[0].forEach(function (way) {
39808               var parents = graph.parentRelations(way);
39809               parents.forEach(function (parent) {
39810                 if ((parent.isRestriction() || parent.isConnectivity()) && parent.members.some(function (m) {
39811                   return nodeIds.indexOf(m.id) >= 0;
39812                 })) {
39813                   relation = parent;
39814                 }
39815               });
39816
39817               for (var k in way.tags) {
39818                 if (!(k in tags)) {
39819                   tags[k] = way.tags[k];
39820                 } else if (tags[k] && osmIsInterestingTag(k) && tags[k] !== way.tags[k]) {
39821                   conflicting = true;
39822                 }
39823               }
39824             });
39825
39826             if (relation) {
39827               return relation.isRestriction() ? 'restriction' : 'connectivity';
39828             }
39829
39830             if (conflicting) {
39831               return 'conflicting_tags';
39832             }
39833           };
39834
39835           return action;
39836         }
39837
39838         function actionMerge(ids) {
39839           function groupEntitiesByGeometry(graph) {
39840             var entities = ids.map(function (id) {
39841               return graph.entity(id);
39842             });
39843             return Object.assign({
39844               point: [],
39845               area: [],
39846               line: [],
39847               relation: []
39848             }, utilArrayGroupBy(entities, function (entity) {
39849               return entity.geometry(graph);
39850             }));
39851           }
39852
39853           var action = function action(graph) {
39854             var geometries = groupEntitiesByGeometry(graph);
39855             var target = geometries.area[0] || geometries.line[0];
39856             var points = geometries.point;
39857             points.forEach(function (point) {
39858               target = target.mergeTags(point.tags);
39859               graph = graph.replace(target);
39860               graph.parentRelations(point).forEach(function (parent) {
39861                 graph = graph.replace(parent.replaceMember(point, target));
39862               });
39863               var nodes = utilArrayUniq(graph.childNodes(target));
39864               var removeNode = point;
39865
39866               if (!point.isNew()) {
39867                 // Try to preserve the original point if it already has
39868                 // an ID in the database.
39869                 var inserted = false;
39870
39871                 var canBeReplaced = function canBeReplaced(node) {
39872                   return !(graph.parentWays(node).length > 1 || graph.parentRelations(node).length);
39873                 };
39874
39875                 var replaceNode = function replaceNode(node) {
39876                   graph = graph.replace(point.update({
39877                     tags: node.tags,
39878                     loc: node.loc
39879                   }));
39880                   target = target.replaceNode(node.id, point.id);
39881                   graph = graph.replace(target);
39882                   removeNode = node;
39883                   inserted = true;
39884                 };
39885
39886                 var i;
39887                 var node; // First, try to replace a new child node on the target way.
39888
39889                 for (i = 0; i < nodes.length; i++) {
39890                   node = nodes[i];
39891
39892                   if (canBeReplaced(node) && node.isNew()) {
39893                     replaceNode(node);
39894                     break;
39895                   }
39896                 }
39897
39898                 if (!inserted && point.hasInterestingTags()) {
39899                   // No new child node found, try to find an existing, but
39900                   // uninteresting child node instead.
39901                   for (i = 0; i < nodes.length; i++) {
39902                     node = nodes[i];
39903
39904                     if (canBeReplaced(node) && !node.hasInterestingTags()) {
39905                       replaceNode(node);
39906                       break;
39907                     }
39908                   }
39909
39910                   if (!inserted) {
39911                     // Still not inserted, try to find an existing, interesting,
39912                     // but more recent child node.
39913                     for (i = 0; i < nodes.length; i++) {
39914                       node = nodes[i];
39915
39916                       if (canBeReplaced(node) && utilCompareIDs(point.id, node.id) < 0) {
39917                         replaceNode(node);
39918                         break;
39919                       }
39920                     }
39921                   } // If the point still hasn't been inserted, we give up.
39922                   // There are more interesting or older nodes on the way.
39923
39924                 }
39925               }
39926
39927               graph = graph.remove(removeNode);
39928             });
39929
39930             if (target.tags.area === 'yes') {
39931               var tags = Object.assign({}, target.tags); // shallow copy
39932
39933               delete tags.area;
39934
39935               if (osmTagSuggestingArea(tags)) {
39936                 // remove the `area` tag if area geometry is now implied - #3851
39937                 target = target.update({
39938                   tags: tags
39939                 });
39940                 graph = graph.replace(target);
39941               }
39942             }
39943
39944             return graph;
39945           };
39946
39947           action.disabled = function (graph) {
39948             var geometries = groupEntitiesByGeometry(graph);
39949
39950             if (geometries.point.length === 0 || geometries.area.length + geometries.line.length !== 1 || geometries.relation.length !== 0) {
39951               return 'not_eligible';
39952             }
39953           };
39954
39955           return action;
39956         }
39957
39958         //
39959         // 1. move all the nodes to a common location
39960         // 2. `actionConnect` them
39961
39962         function actionMergeNodes(nodeIDs, loc) {
39963           // If there is a single "interesting" node, use that as the location.
39964           // Otherwise return the average location of all the nodes.
39965           function chooseLoc(graph) {
39966             if (!nodeIDs.length) return null;
39967             var sum = [0, 0];
39968             var interestingCount = 0;
39969             var interestingLoc;
39970
39971             for (var i = 0; i < nodeIDs.length; i++) {
39972               var node = graph.entity(nodeIDs[i]);
39973
39974               if (node.hasInterestingTags()) {
39975                 interestingLoc = ++interestingCount === 1 ? node.loc : null;
39976               }
39977
39978               sum = geoVecAdd(sum, node.loc);
39979             }
39980
39981             return interestingLoc || geoVecScale(sum, 1 / nodeIDs.length);
39982           }
39983
39984           var action = function action(graph) {
39985             if (nodeIDs.length < 2) return graph;
39986             var toLoc = loc;
39987
39988             if (!toLoc) {
39989               toLoc = chooseLoc(graph);
39990             }
39991
39992             for (var i = 0; i < nodeIDs.length; i++) {
39993               var node = graph.entity(nodeIDs[i]);
39994
39995               if (node.loc !== toLoc) {
39996                 graph = graph.replace(node.move(toLoc));
39997               }
39998             }
39999
40000             return actionConnect(nodeIDs)(graph);
40001           };
40002
40003           action.disabled = function (graph) {
40004             if (nodeIDs.length < 2) return 'not_eligible';
40005
40006             for (var i = 0; i < nodeIDs.length; i++) {
40007               var entity = graph.entity(nodeIDs[i]);
40008               if (entity.type !== 'node') return 'not_eligible';
40009             }
40010
40011             return actionConnect(nodeIDs).disabled(graph);
40012           };
40013
40014           return action;
40015         }
40016
40017         function osmChangeset() {
40018           if (!(this instanceof osmChangeset)) {
40019             return new osmChangeset().initialize(arguments);
40020           } else if (arguments.length) {
40021             this.initialize(arguments);
40022           }
40023         }
40024         osmEntity.changeset = osmChangeset;
40025         osmChangeset.prototype = Object.create(osmEntity.prototype);
40026         Object.assign(osmChangeset.prototype, {
40027           type: 'changeset',
40028           extent: function extent() {
40029             return new geoExtent();
40030           },
40031           geometry: function geometry() {
40032             return 'changeset';
40033           },
40034           asJXON: function asJXON() {
40035             return {
40036               osm: {
40037                 changeset: {
40038                   tag: Object.keys(this.tags).map(function (k) {
40039                     return {
40040                       '@k': k,
40041                       '@v': this.tags[k]
40042                     };
40043                   }, this),
40044                   '@version': 0.6,
40045                   '@generator': 'iD'
40046                 }
40047               }
40048             };
40049           },
40050           // Generate [osmChange](http://wiki.openstreetmap.org/wiki/OsmChange)
40051           // XML. Returns a string.
40052           osmChangeJXON: function osmChangeJXON(changes) {
40053             var changeset_id = this.id;
40054
40055             function nest(x, order) {
40056               var groups = {};
40057
40058               for (var i = 0; i < x.length; i++) {
40059                 var tagName = Object.keys(x[i])[0];
40060                 if (!groups[tagName]) groups[tagName] = [];
40061                 groups[tagName].push(x[i][tagName]);
40062               }
40063
40064               var ordered = {};
40065               order.forEach(function (o) {
40066                 if (groups[o]) ordered[o] = groups[o];
40067               });
40068               return ordered;
40069             } // sort relations in a changeset by dependencies
40070
40071
40072             function sort(changes) {
40073               // find a referenced relation in the current changeset
40074               function resolve(item) {
40075                 return relations.find(function (relation) {
40076                   return item.keyAttributes.type === 'relation' && item.keyAttributes.ref === relation['@id'];
40077                 });
40078               } // a new item is an item that has not been already processed
40079
40080
40081               function isNew(item) {
40082                 return !sorted[item['@id']] && !processing.find(function (proc) {
40083                   return proc['@id'] === item['@id'];
40084                 });
40085               }
40086
40087               var processing = [];
40088               var sorted = {};
40089               var relations = changes.relation;
40090               if (!relations) return changes;
40091
40092               for (var i = 0; i < relations.length; i++) {
40093                 var relation = relations[i]; // skip relation if already sorted
40094
40095                 if (!sorted[relation['@id']]) {
40096                   processing.push(relation);
40097                 }
40098
40099                 while (processing.length > 0) {
40100                   var next = processing[0],
40101                       deps = next.member.map(resolve).filter(Boolean).filter(isNew);
40102
40103                   if (deps.length === 0) {
40104                     sorted[next['@id']] = next;
40105                     processing.shift();
40106                   } else {
40107                     processing = deps.concat(processing);
40108                   }
40109                 }
40110               }
40111
40112               changes.relation = Object.values(sorted);
40113               return changes;
40114             }
40115
40116             function rep(entity) {
40117               return entity.asJXON(changeset_id);
40118             }
40119
40120             return {
40121               osmChange: {
40122                 '@version': 0.6,
40123                 '@generator': 'iD',
40124                 'create': sort(nest(changes.created.map(rep), ['node', 'way', 'relation'])),
40125                 'modify': nest(changes.modified.map(rep), ['node', 'way', 'relation']),
40126                 'delete': Object.assign(nest(changes.deleted.map(rep), ['relation', 'way', 'node']), {
40127                   '@if-unused': true
40128                 })
40129               }
40130             };
40131           },
40132           asGeoJSON: function asGeoJSON() {
40133             return {};
40134           }
40135         });
40136
40137         function osmNote() {
40138           if (!(this instanceof osmNote)) {
40139             return new osmNote().initialize(arguments);
40140           } else if (arguments.length) {
40141             this.initialize(arguments);
40142           }
40143         }
40144
40145         osmNote.id = function () {
40146           return osmNote.id.next--;
40147         };
40148
40149         osmNote.id.next = -1;
40150         Object.assign(osmNote.prototype, {
40151           type: 'note',
40152           initialize: function initialize(sources) {
40153             for (var i = 0; i < sources.length; ++i) {
40154               var source = sources[i];
40155
40156               for (var prop in source) {
40157                 if (Object.prototype.hasOwnProperty.call(source, prop)) {
40158                   if (source[prop] === undefined) {
40159                     delete this[prop];
40160                   } else {
40161                     this[prop] = source[prop];
40162                   }
40163                 }
40164               }
40165             }
40166
40167             if (!this.id) {
40168               this.id = osmNote.id().toString();
40169             }
40170
40171             return this;
40172           },
40173           extent: function extent() {
40174             return new geoExtent(this.loc);
40175           },
40176           update: function update(attrs) {
40177             return osmNote(this, attrs); // {v: 1 + (this.v || 0)}
40178           },
40179           isNew: function isNew() {
40180             return this.id < 0;
40181           },
40182           move: function move(loc) {
40183             return this.update({
40184               loc: loc
40185             });
40186           }
40187         });
40188
40189         function osmRelation() {
40190           if (!(this instanceof osmRelation)) {
40191             return new osmRelation().initialize(arguments);
40192           } else if (arguments.length) {
40193             this.initialize(arguments);
40194           }
40195         }
40196         osmEntity.relation = osmRelation;
40197         osmRelation.prototype = Object.create(osmEntity.prototype);
40198
40199         osmRelation.creationOrder = function (a, b) {
40200           var aId = parseInt(osmEntity.id.toOSM(a.id), 10);
40201           var bId = parseInt(osmEntity.id.toOSM(b.id), 10);
40202           if (aId < 0 || bId < 0) return aId - bId;
40203           return bId - aId;
40204         };
40205
40206         Object.assign(osmRelation.prototype, {
40207           type: 'relation',
40208           members: [],
40209           copy: function copy(resolver, copies) {
40210             if (copies[this.id]) return copies[this.id];
40211             var copy = osmEntity.prototype.copy.call(this, resolver, copies);
40212             var members = this.members.map(function (member) {
40213               return Object.assign({}, member, {
40214                 id: resolver.entity(member.id).copy(resolver, copies).id
40215               });
40216             });
40217             copy = copy.update({
40218               members: members
40219             });
40220             copies[this.id] = copy;
40221             return copy;
40222           },
40223           extent: function extent(resolver, memo) {
40224             return resolver["transient"](this, 'extent', function () {
40225               if (memo && memo[this.id]) return geoExtent();
40226               memo = memo || {};
40227               memo[this.id] = true;
40228               var extent = geoExtent();
40229
40230               for (var i = 0; i < this.members.length; i++) {
40231                 var member = resolver.hasEntity(this.members[i].id);
40232
40233                 if (member) {
40234                   extent._extend(member.extent(resolver, memo));
40235                 }
40236               }
40237
40238               return extent;
40239             });
40240           },
40241           geometry: function geometry(graph) {
40242             return graph["transient"](this, 'geometry', function () {
40243               return this.isMultipolygon() ? 'area' : 'relation';
40244             });
40245           },
40246           isDegenerate: function isDegenerate() {
40247             return this.members.length === 0;
40248           },
40249           // Return an array of members, each extended with an 'index' property whose value
40250           // is the member index.
40251           indexedMembers: function indexedMembers() {
40252             var result = new Array(this.members.length);
40253
40254             for (var i = 0; i < this.members.length; i++) {
40255               result[i] = Object.assign({}, this.members[i], {
40256                 index: i
40257               });
40258             }
40259
40260             return result;
40261           },
40262           // Return the first member with the given role. A copy of the member object
40263           // is returned, extended with an 'index' property whose value is the member index.
40264           memberByRole: function memberByRole(role) {
40265             for (var i = 0; i < this.members.length; i++) {
40266               if (this.members[i].role === role) {
40267                 return Object.assign({}, this.members[i], {
40268                   index: i
40269                 });
40270               }
40271             }
40272           },
40273           // Same as memberByRole, but returns all members with the given role
40274           membersByRole: function membersByRole(role) {
40275             var result = [];
40276
40277             for (var i = 0; i < this.members.length; i++) {
40278               if (this.members[i].role === role) {
40279                 result.push(Object.assign({}, this.members[i], {
40280                   index: i
40281                 }));
40282               }
40283             }
40284
40285             return result;
40286           },
40287           // Return the first member with the given id. A copy of the member object
40288           // is returned, extended with an 'index' property whose value is the member index.
40289           memberById: function memberById(id) {
40290             for (var i = 0; i < this.members.length; i++) {
40291               if (this.members[i].id === id) {
40292                 return Object.assign({}, this.members[i], {
40293                   index: i
40294                 });
40295               }
40296             }
40297           },
40298           // Return the first member with the given id and role. A copy of the member object
40299           // is returned, extended with an 'index' property whose value is the member index.
40300           memberByIdAndRole: function memberByIdAndRole(id, role) {
40301             for (var i = 0; i < this.members.length; i++) {
40302               if (this.members[i].id === id && this.members[i].role === role) {
40303                 return Object.assign({}, this.members[i], {
40304                   index: i
40305                 });
40306               }
40307             }
40308           },
40309           addMember: function addMember(member, index) {
40310             var members = this.members.slice();
40311             members.splice(index === undefined ? members.length : index, 0, member);
40312             return this.update({
40313               members: members
40314             });
40315           },
40316           updateMember: function updateMember(member, index) {
40317             var members = this.members.slice();
40318             members.splice(index, 1, Object.assign({}, members[index], member));
40319             return this.update({
40320               members: members
40321             });
40322           },
40323           removeMember: function removeMember(index) {
40324             var members = this.members.slice();
40325             members.splice(index, 1);
40326             return this.update({
40327               members: members
40328             });
40329           },
40330           removeMembersWithID: function removeMembersWithID(id) {
40331             var members = this.members.filter(function (m) {
40332               return m.id !== id;
40333             });
40334             return this.update({
40335               members: members
40336             });
40337           },
40338           moveMember: function moveMember(fromIndex, toIndex) {
40339             var members = this.members.slice();
40340             members.splice(toIndex, 0, members.splice(fromIndex, 1)[0]);
40341             return this.update({
40342               members: members
40343             });
40344           },
40345           // Wherever a member appears with id `needle.id`, replace it with a member
40346           // with id `replacement.id`, type `replacement.type`, and the original role,
40347           // By default, adding a duplicate member (by id and role) is prevented.
40348           // Return an updated relation.
40349           replaceMember: function replaceMember(needle, replacement, keepDuplicates) {
40350             if (!this.memberById(needle.id)) return this;
40351             var members = [];
40352
40353             for (var i = 0; i < this.members.length; i++) {
40354               var member = this.members[i];
40355
40356               if (member.id !== needle.id) {
40357                 members.push(member);
40358               } else if (keepDuplicates || !this.memberByIdAndRole(replacement.id, member.role)) {
40359                 members.push({
40360                   id: replacement.id,
40361                   type: replacement.type,
40362                   role: member.role
40363                 });
40364               }
40365             }
40366
40367             return this.update({
40368               members: members
40369             });
40370           },
40371           asJXON: function asJXON(changeset_id) {
40372             var r = {
40373               relation: {
40374                 '@id': this.osmId(),
40375                 '@version': this.version || 0,
40376                 member: this.members.map(function (member) {
40377                   return {
40378                     keyAttributes: {
40379                       type: member.type,
40380                       role: member.role,
40381                       ref: osmEntity.id.toOSM(member.id)
40382                     }
40383                   };
40384                 }, this),
40385                 tag: Object.keys(this.tags).map(function (k) {
40386                   return {
40387                     keyAttributes: {
40388                       k: k,
40389                       v: this.tags[k]
40390                     }
40391                   };
40392                 }, this)
40393               }
40394             };
40395
40396             if (changeset_id) {
40397               r.relation['@changeset'] = changeset_id;
40398             }
40399
40400             return r;
40401           },
40402           asGeoJSON: function asGeoJSON(resolver) {
40403             return resolver["transient"](this, 'GeoJSON', function () {
40404               if (this.isMultipolygon()) {
40405                 return {
40406                   type: 'MultiPolygon',
40407                   coordinates: this.multipolygon(resolver)
40408                 };
40409               } else {
40410                 return {
40411                   type: 'FeatureCollection',
40412                   properties: this.tags,
40413                   features: this.members.map(function (member) {
40414                     return Object.assign({
40415                       role: member.role
40416                     }, resolver.entity(member.id).asGeoJSON(resolver));
40417                   })
40418                 };
40419               }
40420             });
40421           },
40422           area: function area(resolver) {
40423             return resolver["transient"](this, 'area', function () {
40424               return d3_geoArea(this.asGeoJSON(resolver));
40425             });
40426           },
40427           isMultipolygon: function isMultipolygon() {
40428             return this.tags.type === 'multipolygon';
40429           },
40430           isComplete: function isComplete(resolver) {
40431             for (var i = 0; i < this.members.length; i++) {
40432               if (!resolver.hasEntity(this.members[i].id)) {
40433                 return false;
40434               }
40435             }
40436
40437             return true;
40438           },
40439           hasFromViaTo: function hasFromViaTo() {
40440             return this.members.some(function (m) {
40441               return m.role === 'from';
40442             }) && this.members.some(function (m) {
40443               return m.role === 'via';
40444             }) && this.members.some(function (m) {
40445               return m.role === 'to';
40446             });
40447           },
40448           isRestriction: function isRestriction() {
40449             return !!(this.tags.type && this.tags.type.match(/^restriction:?/));
40450           },
40451           isValidRestriction: function isValidRestriction() {
40452             if (!this.isRestriction()) return false;
40453             var froms = this.members.filter(function (m) {
40454               return m.role === 'from';
40455             });
40456             var vias = this.members.filter(function (m) {
40457               return m.role === 'via';
40458             });
40459             var tos = this.members.filter(function (m) {
40460               return m.role === 'to';
40461             });
40462             if (froms.length !== 1 && this.tags.restriction !== 'no_entry') return false;
40463             if (froms.some(function (m) {
40464               return m.type !== 'way';
40465             })) return false;
40466             if (tos.length !== 1 && this.tags.restriction !== 'no_exit') return false;
40467             if (tos.some(function (m) {
40468               return m.type !== 'way';
40469             })) return false;
40470             if (vias.length === 0) return false;
40471             if (vias.length > 1 && vias.some(function (m) {
40472               return m.type !== 'way';
40473             })) return false;
40474             return true;
40475           },
40476           isConnectivity: function isConnectivity() {
40477             return !!(this.tags.type && this.tags.type.match(/^connectivity:?/));
40478           },
40479           // Returns an array [A0, ... An], each Ai being an array of node arrays [Nds0, ... Ndsm],
40480           // where Nds0 is an outer ring and subsequent Ndsi's (if any i > 0) being inner rings.
40481           //
40482           // This corresponds to the structure needed for rendering a multipolygon path using a
40483           // `evenodd` fill rule, as well as the structure of a GeoJSON MultiPolygon geometry.
40484           //
40485           // In the case of invalid geometries, this function will still return a result which
40486           // includes the nodes of all way members, but some Nds may be unclosed and some inner
40487           // rings not matched with the intended outer ring.
40488           //
40489           multipolygon: function multipolygon(resolver) {
40490             var outers = this.members.filter(function (m) {
40491               return 'outer' === (m.role || 'outer');
40492             });
40493             var inners = this.members.filter(function (m) {
40494               return 'inner' === m.role;
40495             });
40496             outers = osmJoinWays(outers, resolver);
40497             inners = osmJoinWays(inners, resolver);
40498
40499             var sequenceToLineString = function sequenceToLineString(sequence) {
40500               if (sequence.nodes.length > 2 && sequence.nodes[0] !== sequence.nodes[sequence.nodes.length - 1]) {
40501                 // close unclosed parts to ensure correct area rendering - #2945
40502                 sequence.nodes.push(sequence.nodes[0]);
40503               }
40504
40505               return sequence.nodes.map(function (node) {
40506                 return node.loc;
40507               });
40508             };
40509
40510             outers = outers.map(sequenceToLineString);
40511             inners = inners.map(sequenceToLineString);
40512             var result = outers.map(function (o) {
40513               // Heuristic for detecting counterclockwise winding order. Assumes
40514               // that OpenStreetMap polygons are not hemisphere-spanning.
40515               return [d3_geoArea({
40516                 type: 'Polygon',
40517                 coordinates: [o]
40518               }) > 2 * Math.PI ? o.reverse() : o];
40519             });
40520
40521             function findOuter(inner) {
40522               var o, outer;
40523
40524               for (o = 0; o < outers.length; o++) {
40525                 outer = outers[o];
40526
40527                 if (geoPolygonContainsPolygon(outer, inner)) {
40528                   return o;
40529                 }
40530               }
40531
40532               for (o = 0; o < outers.length; o++) {
40533                 outer = outers[o];
40534
40535                 if (geoPolygonIntersectsPolygon(outer, inner, false)) {
40536                   return o;
40537                 }
40538               }
40539             }
40540
40541             for (var i = 0; i < inners.length; i++) {
40542               var inner = inners[i];
40543
40544               if (d3_geoArea({
40545                 type: 'Polygon',
40546                 coordinates: [inner]
40547               }) < 2 * Math.PI) {
40548                 inner = inner.reverse();
40549               }
40550
40551               var o = findOuter(inners[i]);
40552
40553               if (o !== undefined) {
40554                 result[o].push(inners[i]);
40555               } else {
40556                 result.push([inners[i]]); // Invalid geometry
40557               }
40558             }
40559
40560             return result;
40561           }
40562         });
40563
40564         var QAItem = /*#__PURE__*/function () {
40565           function QAItem(loc, service, itemType, id, props) {
40566             _classCallCheck$1(this, QAItem);
40567
40568             // Store required properties
40569             this.loc = loc;
40570             this.service = service.title;
40571             this.itemType = itemType; // All issues must have an ID for selection, use generic if none specified
40572
40573             this.id = id ? id : "".concat(QAItem.id());
40574             this.update(props); // Some QA services have marker icons to differentiate issues
40575
40576             if (service && typeof service.getIcon === 'function') {
40577               this.icon = service.getIcon(itemType);
40578             }
40579           }
40580
40581           _createClass$1(QAItem, [{
40582             key: "update",
40583             value: function update(props) {
40584               var _this = this;
40585
40586               // You can't override this initial information
40587               var loc = this.loc,
40588                   service = this.service,
40589                   itemType = this.itemType,
40590                   id = this.id;
40591               Object.keys(props).forEach(function (prop) {
40592                 return _this[prop] = props[prop];
40593               });
40594               this.loc = loc;
40595               this.service = service;
40596               this.itemType = itemType;
40597               this.id = id;
40598               return this;
40599             } // Generic handling for newly created QAItems
40600
40601           }], [{
40602             key: "id",
40603             value: function id() {
40604               return this.nextId--;
40605             }
40606           }]);
40607
40608           return QAItem;
40609         }();
40610         QAItem.nextId = -1;
40611
40612         //
40613         // Optionally, split only the given ways, if multiple ways share
40614         // the given node.
40615         //
40616         // This is the inverse of `iD.actionJoin`.
40617         //
40618         // For testing convenience, accepts an ID to assign to the new way.
40619         // Normally, this will be undefined and the way will automatically
40620         // be assigned a new ID.
40621         //
40622         // Reference:
40623         //   https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/SplitWayAction.as
40624         //
40625
40626         function actionSplit(nodeIds, newWayIds) {
40627           // accept single ID for backwards-compatiblity
40628           if (typeof nodeIds === 'string') nodeIds = [nodeIds];
40629
40630           var _wayIDs; // the strategy for picking which way will have a new version and which way is newly created
40631
40632
40633           var _keepHistoryOn = 'longest'; // 'longest', 'first'
40634           // The IDs of the ways actually created by running this action
40635
40636           var _createdWayIDs = [];
40637
40638           function dist(graph, nA, nB) {
40639             var locA = graph.entity(nA).loc;
40640             var locB = graph.entity(nB).loc;
40641             var epsilon = 1e-6;
40642             return locA && locB ? geoSphericalDistance(locA, locB) : epsilon;
40643           } // If the way is closed, we need to search for a partner node
40644           // to split the way at.
40645           //
40646           // The following looks for a node that is both far away from
40647           // the initial node in terms of way segment length and nearby
40648           // in terms of beeline-distance. This assures that areas get
40649           // split on the most "natural" points (independent of the number
40650           // of nodes).
40651           // For example: bone-shaped areas get split across their waist
40652           // line, circles across the diameter.
40653
40654
40655           function splitArea(nodes, idxA, graph) {
40656             var lengths = new Array(nodes.length);
40657             var length;
40658             var i;
40659             var best = 0;
40660             var idxB;
40661
40662             function wrap(index) {
40663               return utilWrap(index, nodes.length);
40664             } // calculate lengths
40665
40666
40667             length = 0;
40668
40669             for (i = wrap(idxA + 1); i !== idxA; i = wrap(i + 1)) {
40670               length += dist(graph, nodes[i], nodes[wrap(i - 1)]);
40671               lengths[i] = length;
40672             }
40673
40674             length = 0;
40675
40676             for (i = wrap(idxA - 1); i !== idxA; i = wrap(i - 1)) {
40677               length += dist(graph, nodes[i], nodes[wrap(i + 1)]);
40678
40679               if (length < lengths[i]) {
40680                 lengths[i] = length;
40681               }
40682             } // determine best opposite node to split
40683
40684
40685             for (i = 0; i < nodes.length; i++) {
40686               var cost = lengths[i] / dist(graph, nodes[idxA], nodes[i]);
40687
40688               if (cost > best) {
40689                 idxB = i;
40690                 best = cost;
40691               }
40692             }
40693
40694             return idxB;
40695           }
40696
40697           function totalLengthBetweenNodes(graph, nodes) {
40698             var totalLength = 0;
40699
40700             for (var i = 0; i < nodes.length - 1; i++) {
40701               totalLength += dist(graph, nodes[i], nodes[i + 1]);
40702             }
40703
40704             return totalLength;
40705           }
40706
40707           function split(graph, nodeId, wayA, newWayId) {
40708             var wayB = osmWay({
40709               id: newWayId,
40710               tags: wayA.tags
40711             }); // `wayB` is the NEW way
40712
40713             var origNodes = wayA.nodes.slice();
40714             var nodesA;
40715             var nodesB;
40716             var isArea = wayA.isArea();
40717             var isOuter = osmIsOldMultipolygonOuterMember(wayA, graph);
40718
40719             if (wayA.isClosed()) {
40720               var nodes = wayA.nodes.slice(0, -1);
40721               var idxA = nodes.indexOf(nodeId);
40722               var idxB = splitArea(nodes, idxA, graph);
40723
40724               if (idxB < idxA) {
40725                 nodesA = nodes.slice(idxA).concat(nodes.slice(0, idxB + 1));
40726                 nodesB = nodes.slice(idxB, idxA + 1);
40727               } else {
40728                 nodesA = nodes.slice(idxA, idxB + 1);
40729                 nodesB = nodes.slice(idxB).concat(nodes.slice(0, idxA + 1));
40730               }
40731             } else {
40732               var idx = wayA.nodes.indexOf(nodeId, 1);
40733               nodesA = wayA.nodes.slice(0, idx + 1);
40734               nodesB = wayA.nodes.slice(idx);
40735             }
40736
40737             var lengthA = totalLengthBetweenNodes(graph, nodesA);
40738             var lengthB = totalLengthBetweenNodes(graph, nodesB);
40739
40740             if (_keepHistoryOn === 'longest' && lengthB > lengthA) {
40741               // keep the history on the longer way, regardless of the node count
40742               wayA = wayA.update({
40743                 nodes: nodesB
40744               });
40745               wayB = wayB.update({
40746                 nodes: nodesA
40747               });
40748               var temp = lengthA;
40749               lengthA = lengthB;
40750               lengthB = temp;
40751             } else {
40752               wayA = wayA.update({
40753                 nodes: nodesA
40754               });
40755               wayB = wayB.update({
40756                 nodes: nodesB
40757               });
40758             }
40759
40760             if (wayA.tags.step_count) {
40761               // divide up the the step count proportionally between the two ways
40762               var stepCount = parseFloat(wayA.tags.step_count);
40763
40764               if (stepCount && // ensure a number
40765               isFinite(stepCount) && // ensure positive
40766               stepCount > 0 && // ensure integer
40767               Math.round(stepCount) === stepCount) {
40768                 var tagsA = Object.assign({}, wayA.tags);
40769                 var tagsB = Object.assign({}, wayB.tags);
40770                 var ratioA = lengthA / (lengthA + lengthB);
40771                 var countA = Math.round(stepCount * ratioA);
40772                 tagsA.step_count = countA.toString();
40773                 tagsB.step_count = (stepCount - countA).toString();
40774                 wayA = wayA.update({
40775                   tags: tagsA
40776                 });
40777                 wayB = wayB.update({
40778                   tags: tagsB
40779                 });
40780               }
40781             }
40782
40783             graph = graph.replace(wayA);
40784             graph = graph.replace(wayB);
40785             graph.parentRelations(wayA).forEach(function (relation) {
40786               var member; // Turn restrictions - make sure:
40787               // 1. Splitting a FROM/TO way - only `wayA` OR `wayB` remains in relation
40788               //    (whichever one is connected to the VIA node/ways)
40789               // 2. Splitting a VIA way - `wayB` remains in relation as a VIA way
40790
40791               if (relation.hasFromViaTo()) {
40792                 var f = relation.memberByRole('from');
40793                 var v = relation.membersByRole('via');
40794                 var t = relation.memberByRole('to');
40795                 var i; // 1. split a FROM/TO
40796
40797                 if (f.id === wayA.id || t.id === wayA.id) {
40798                   var keepB = false;
40799
40800                   if (v.length === 1 && v[0].type === 'node') {
40801                     // check via node
40802                     keepB = wayB.contains(v[0].id);
40803                   } else {
40804                     // check via way(s)
40805                     for (i = 0; i < v.length; i++) {
40806                       if (v[i].type === 'way') {
40807                         var wayVia = graph.hasEntity(v[i].id);
40808
40809                         if (wayVia && utilArrayIntersection(wayB.nodes, wayVia.nodes).length) {
40810                           keepB = true;
40811                           break;
40812                         }
40813                       }
40814                     }
40815                   }
40816
40817                   if (keepB) {
40818                     relation = relation.replaceMember(wayA, wayB);
40819                     graph = graph.replace(relation);
40820                   } // 2. split a VIA
40821
40822                 } else {
40823                   for (i = 0; i < v.length; i++) {
40824                     if (v[i].type === 'way' && v[i].id === wayA.id) {
40825                       member = {
40826                         id: wayB.id,
40827                         type: 'way',
40828                         role: 'via'
40829                       };
40830                       graph = actionAddMember(relation.id, member, v[i].index + 1)(graph);
40831                       break;
40832                     }
40833                   }
40834                 } // All other relations (Routes, Multipolygons, etc):
40835                 // 1. Both `wayA` and `wayB` remain in the relation
40836                 // 2. But must be inserted as a pair (see `actionAddMember` for details)
40837
40838               } else {
40839                 if (relation === isOuter) {
40840                   graph = graph.replace(relation.mergeTags(wayA.tags));
40841                   graph = graph.replace(wayA.update({
40842                     tags: {}
40843                   }));
40844                   graph = graph.replace(wayB.update({
40845                     tags: {}
40846                   }));
40847                 }
40848
40849                 member = {
40850                   id: wayB.id,
40851                   type: 'way',
40852                   role: relation.memberById(wayA.id).role
40853                 };
40854                 var insertPair = {
40855                   originalID: wayA.id,
40856                   insertedID: wayB.id,
40857                   nodes: origNodes
40858                 };
40859                 graph = actionAddMember(relation.id, member, undefined, insertPair)(graph);
40860               }
40861             });
40862
40863             if (!isOuter && isArea) {
40864               var multipolygon = osmRelation({
40865                 tags: Object.assign({}, wayA.tags, {
40866                   type: 'multipolygon'
40867                 }),
40868                 members: [{
40869                   id: wayA.id,
40870                   role: 'outer',
40871                   type: 'way'
40872                 }, {
40873                   id: wayB.id,
40874                   role: 'outer',
40875                   type: 'way'
40876                 }]
40877               });
40878               graph = graph.replace(multipolygon);
40879               graph = graph.replace(wayA.update({
40880                 tags: {}
40881               }));
40882               graph = graph.replace(wayB.update({
40883                 tags: {}
40884               }));
40885             }
40886
40887             _createdWayIDs.push(wayB.id);
40888
40889             return graph;
40890           }
40891
40892           var action = function action(graph) {
40893             _createdWayIDs = [];
40894             var newWayIndex = 0;
40895
40896             for (var i = 0; i < nodeIds.length; i++) {
40897               var nodeId = nodeIds[i];
40898               var candidates = action.waysForNode(nodeId, graph);
40899
40900               for (var j = 0; j < candidates.length; j++) {
40901                 graph = split(graph, nodeId, candidates[j], newWayIds && newWayIds[newWayIndex]);
40902                 newWayIndex += 1;
40903               }
40904             }
40905
40906             return graph;
40907           };
40908
40909           action.getCreatedWayIDs = function () {
40910             return _createdWayIDs;
40911           };
40912
40913           action.waysForNode = function (nodeId, graph) {
40914             var node = graph.entity(nodeId);
40915             var splittableParents = graph.parentWays(node).filter(isSplittable);
40916
40917             if (!_wayIDs) {
40918               // If the ways to split aren't specified, only split the lines.
40919               // If there are no lines to split, split the areas.
40920               var hasLine = splittableParents.some(function (parent) {
40921                 return parent.geometry(graph) === 'line';
40922               });
40923
40924               if (hasLine) {
40925                 return splittableParents.filter(function (parent) {
40926                   return parent.geometry(graph) === 'line';
40927                 });
40928               }
40929             }
40930
40931             return splittableParents;
40932
40933             function isSplittable(parent) {
40934               // If the ways to split are specified, ignore everything else.
40935               if (_wayIDs && _wayIDs.indexOf(parent.id) === -1) return false; // We can fake splitting closed ways at their endpoints...
40936
40937               if (parent.isClosed()) return true; // otherwise, we can't split nodes at their endpoints.
40938
40939               for (var i = 1; i < parent.nodes.length - 1; i++) {
40940                 if (parent.nodes[i] === nodeId) return true;
40941               }
40942
40943               return false;
40944             }
40945           };
40946
40947           action.ways = function (graph) {
40948             return utilArrayUniq([].concat.apply([], nodeIds.map(function (nodeId) {
40949               return action.waysForNode(nodeId, graph);
40950             })));
40951           };
40952
40953           action.disabled = function (graph) {
40954             for (var i = 0; i < nodeIds.length; i++) {
40955               var nodeId = nodeIds[i];
40956               var candidates = action.waysForNode(nodeId, graph);
40957
40958               if (candidates.length === 0 || _wayIDs && _wayIDs.length !== candidates.length) {
40959                 return 'not_eligible';
40960               }
40961             }
40962           };
40963
40964           action.limitWays = function (val) {
40965             if (!arguments.length) return _wayIDs;
40966             _wayIDs = val;
40967             return action;
40968           };
40969
40970           action.keepHistoryOn = function (val) {
40971             if (!arguments.length) return _keepHistoryOn;
40972             _keepHistoryOn = val;
40973             return action;
40974           };
40975
40976           return action;
40977         }
40978
40979         function coreGraph(other, mutable) {
40980           if (!(this instanceof coreGraph)) return new coreGraph(other, mutable);
40981
40982           if (other instanceof coreGraph) {
40983             var base = other.base();
40984             this.entities = Object.assign(Object.create(base.entities), other.entities);
40985             this._parentWays = Object.assign(Object.create(base.parentWays), other._parentWays);
40986             this._parentRels = Object.assign(Object.create(base.parentRels), other._parentRels);
40987           } else {
40988             this.entities = Object.create({});
40989             this._parentWays = Object.create({});
40990             this._parentRels = Object.create({});
40991             this.rebase(other || [], [this]);
40992           }
40993
40994           this.transients = {};
40995           this._childNodes = {};
40996           this.frozen = !mutable;
40997         }
40998         coreGraph.prototype = {
40999           hasEntity: function hasEntity(id) {
41000             return this.entities[id];
41001           },
41002           entity: function entity(id) {
41003             var entity = this.entities[id]; //https://github.com/openstreetmap/iD/issues/3973#issuecomment-307052376
41004
41005             if (!entity) {
41006               entity = this.entities.__proto__[id]; // eslint-disable-line no-proto
41007             }
41008
41009             if (!entity) {
41010               throw new Error('entity ' + id + ' not found');
41011             }
41012
41013             return entity;
41014           },
41015           geometry: function geometry(id) {
41016             return this.entity(id).geometry(this);
41017           },
41018           "transient": function transient(entity, key, fn) {
41019             var id = entity.id;
41020             var transients = this.transients[id] || (this.transients[id] = {});
41021
41022             if (transients[key] !== undefined) {
41023               return transients[key];
41024             }
41025
41026             transients[key] = fn.call(entity);
41027             return transients[key];
41028           },
41029           parentWays: function parentWays(entity) {
41030             var parents = this._parentWays[entity.id];
41031             var result = [];
41032
41033             if (parents) {
41034               parents.forEach(function (id) {
41035                 result.push(this.entity(id));
41036               }, this);
41037             }
41038
41039             return result;
41040           },
41041           isPoi: function isPoi(entity) {
41042             var parents = this._parentWays[entity.id];
41043             return !parents || parents.size === 0;
41044           },
41045           isShared: function isShared(entity) {
41046             var parents = this._parentWays[entity.id];
41047             return parents && parents.size > 1;
41048           },
41049           parentRelations: function parentRelations(entity) {
41050             var parents = this._parentRels[entity.id];
41051             var result = [];
41052
41053             if (parents) {
41054               parents.forEach(function (id) {
41055                 result.push(this.entity(id));
41056               }, this);
41057             }
41058
41059             return result;
41060           },
41061           parentMultipolygons: function parentMultipolygons(entity) {
41062             return this.parentRelations(entity).filter(function (relation) {
41063               return relation.isMultipolygon();
41064             });
41065           },
41066           childNodes: function childNodes(entity) {
41067             if (this._childNodes[entity.id]) return this._childNodes[entity.id];
41068             if (!entity.nodes) return [];
41069             var nodes = [];
41070
41071             for (var i = 0; i < entity.nodes.length; i++) {
41072               nodes[i] = this.entity(entity.nodes[i]);
41073             }
41074             this._childNodes[entity.id] = nodes;
41075             return this._childNodes[entity.id];
41076           },
41077           base: function base() {
41078             return {
41079               'entities': Object.getPrototypeOf(this.entities),
41080               'parentWays': Object.getPrototypeOf(this._parentWays),
41081               'parentRels': Object.getPrototypeOf(this._parentRels)
41082             };
41083           },
41084           // Unlike other graph methods, rebase mutates in place. This is because it
41085           // is used only during the history operation that merges newly downloaded
41086           // data into each state. To external consumers, it should appear as if the
41087           // graph always contained the newly downloaded data.
41088           rebase: function rebase(entities, stack, force) {
41089             var base = this.base();
41090             var i, j, k, id;
41091
41092             for (i = 0; i < entities.length; i++) {
41093               var entity = entities[i];
41094               if (!entity.visible || !force && base.entities[entity.id]) continue; // Merging data into the base graph
41095
41096               base.entities[entity.id] = entity;
41097
41098               this._updateCalculated(undefined, entity, base.parentWays, base.parentRels); // Restore provisionally-deleted nodes that are discovered to have an extant parent
41099
41100
41101               if (entity.type === 'way') {
41102                 for (j = 0; j < entity.nodes.length; j++) {
41103                   id = entity.nodes[j];
41104
41105                   for (k = 1; k < stack.length; k++) {
41106                     var ents = stack[k].entities;
41107
41108                     if (ents.hasOwnProperty(id) && ents[id] === undefined) {
41109                       delete ents[id];
41110                     }
41111                   }
41112                 }
41113               }
41114             }
41115
41116             for (i = 0; i < stack.length; i++) {
41117               stack[i]._updateRebased();
41118             }
41119           },
41120           _updateRebased: function _updateRebased() {
41121             var base = this.base();
41122             Object.keys(this._parentWays).forEach(function (child) {
41123               if (base.parentWays[child]) {
41124                 base.parentWays[child].forEach(function (id) {
41125                   if (!this.entities.hasOwnProperty(id)) {
41126                     this._parentWays[child].add(id);
41127                   }
41128                 }, this);
41129               }
41130             }, this);
41131             Object.keys(this._parentRels).forEach(function (child) {
41132               if (base.parentRels[child]) {
41133                 base.parentRels[child].forEach(function (id) {
41134                   if (!this.entities.hasOwnProperty(id)) {
41135                     this._parentRels[child].add(id);
41136                   }
41137                 }, this);
41138               }
41139             }, this);
41140             this.transients = {}; // this._childNodes is not updated, under the assumption that
41141             // ways are always downloaded with their child nodes.
41142           },
41143           // Updates calculated properties (parentWays, parentRels) for the specified change
41144           _updateCalculated: function _updateCalculated(oldentity, entity, parentWays, parentRels) {
41145             parentWays = parentWays || this._parentWays;
41146             parentRels = parentRels || this._parentRels;
41147             var type = entity && entity.type || oldentity && oldentity.type;
41148             var removed, added, i;
41149
41150             if (type === 'way') {
41151               // Update parentWays
41152               if (oldentity && entity) {
41153                 removed = utilArrayDifference(oldentity.nodes, entity.nodes);
41154                 added = utilArrayDifference(entity.nodes, oldentity.nodes);
41155               } else if (oldentity) {
41156                 removed = oldentity.nodes;
41157                 added = [];
41158               } else if (entity) {
41159                 removed = [];
41160                 added = entity.nodes;
41161               }
41162
41163               for (i = 0; i < removed.length; i++) {
41164                 // make a copy of prototype property, store as own property, and update..
41165                 parentWays[removed[i]] = new Set(parentWays[removed[i]]);
41166                 parentWays[removed[i]]["delete"](oldentity.id);
41167               }
41168
41169               for (i = 0; i < added.length; i++) {
41170                 // make a copy of prototype property, store as own property, and update..
41171                 parentWays[added[i]] = new Set(parentWays[added[i]]);
41172                 parentWays[added[i]].add(entity.id);
41173               }
41174             } else if (type === 'relation') {
41175               // Update parentRels
41176               // diff only on the IDs since the same entity can be a member multiple times with different roles
41177               var oldentityMemberIDs = oldentity ? oldentity.members.map(function (m) {
41178                 return m.id;
41179               }) : [];
41180               var entityMemberIDs = entity ? entity.members.map(function (m) {
41181                 return m.id;
41182               }) : [];
41183
41184               if (oldentity && entity) {
41185                 removed = utilArrayDifference(oldentityMemberIDs, entityMemberIDs);
41186                 added = utilArrayDifference(entityMemberIDs, oldentityMemberIDs);
41187               } else if (oldentity) {
41188                 removed = oldentityMemberIDs;
41189                 added = [];
41190               } else if (entity) {
41191                 removed = [];
41192                 added = entityMemberIDs;
41193               }
41194
41195               for (i = 0; i < removed.length; i++) {
41196                 // make a copy of prototype property, store as own property, and update..
41197                 parentRels[removed[i]] = new Set(parentRels[removed[i]]);
41198                 parentRels[removed[i]]["delete"](oldentity.id);
41199               }
41200
41201               for (i = 0; i < added.length; i++) {
41202                 // make a copy of prototype property, store as own property, and update..
41203                 parentRels[added[i]] = new Set(parentRels[added[i]]);
41204                 parentRels[added[i]].add(entity.id);
41205               }
41206             }
41207           },
41208           replace: function replace(entity) {
41209             if (this.entities[entity.id] === entity) return this;
41210             return this.update(function () {
41211               this._updateCalculated(this.entities[entity.id], entity);
41212
41213               this.entities[entity.id] = entity;
41214             });
41215           },
41216           remove: function remove(entity) {
41217             return this.update(function () {
41218               this._updateCalculated(entity, undefined);
41219
41220               this.entities[entity.id] = undefined;
41221             });
41222           },
41223           revert: function revert(id) {
41224             var baseEntity = this.base().entities[id];
41225             var headEntity = this.entities[id];
41226             if (headEntity === baseEntity) return this;
41227             return this.update(function () {
41228               this._updateCalculated(headEntity, baseEntity);
41229
41230               delete this.entities[id];
41231             });
41232           },
41233           update: function update() {
41234             var graph = this.frozen ? coreGraph(this, true) : this;
41235
41236             for (var i = 0; i < arguments.length; i++) {
41237               arguments[i].call(graph, graph);
41238             }
41239
41240             if (this.frozen) graph.frozen = true;
41241             return graph;
41242           },
41243           // Obliterates any existing entities
41244           load: function load(entities) {
41245             var base = this.base();
41246             this.entities = Object.create(base.entities);
41247
41248             for (var i in entities) {
41249               this.entities[i] = entities[i];
41250
41251               this._updateCalculated(base.entities[i], this.entities[i]);
41252             }
41253
41254             return this;
41255           }
41256         };
41257
41258         function osmTurn(turn) {
41259           if (!(this instanceof osmTurn)) {
41260             return new osmTurn(turn);
41261           }
41262
41263           Object.assign(this, turn);
41264         }
41265         function osmIntersection(graph, startVertexId, maxDistance) {
41266           maxDistance = maxDistance || 30; // in meters
41267
41268           var vgraph = coreGraph(); // virtual graph
41269
41270           var i, j, k;
41271
41272           function memberOfRestriction(entity) {
41273             return graph.parentRelations(entity).some(function (r) {
41274               return r.isRestriction();
41275             });
41276           }
41277
41278           function isRoad(way) {
41279             if (way.isArea() || way.isDegenerate()) return false;
41280             var roads = {
41281               'motorway': true,
41282               'motorway_link': true,
41283               'trunk': true,
41284               'trunk_link': true,
41285               'primary': true,
41286               'primary_link': true,
41287               'secondary': true,
41288               'secondary_link': true,
41289               'tertiary': true,
41290               'tertiary_link': true,
41291               'residential': true,
41292               'unclassified': true,
41293               'living_street': true,
41294               'service': true,
41295               'road': true,
41296               'track': true
41297             };
41298             return roads[way.tags.highway];
41299           }
41300
41301           var startNode = graph.entity(startVertexId);
41302           var checkVertices = [startNode];
41303           var checkWays;
41304           var vertices = [];
41305           var vertexIds = [];
41306           var vertex;
41307           var ways = [];
41308           var wayIds = [];
41309           var way;
41310           var nodes = [];
41311           var node;
41312           var parents = [];
41313           var parent; // `actions` will store whatever actions must be performed to satisfy
41314           // preconditions for adding a turn restriction to this intersection.
41315           //  - Remove any existing degenerate turn restrictions (missing from/to, etc)
41316           //  - Reverse oneways so that they are drawn in the forward direction
41317           //  - Split ways on key vertices
41318
41319           var actions = []; // STEP 1:  walk the graph outwards from starting vertex to search
41320           //  for more key vertices and ways to include in the intersection..
41321
41322           while (checkVertices.length) {
41323             vertex = checkVertices.pop(); // check this vertex for parent ways that are roads
41324
41325             checkWays = graph.parentWays(vertex);
41326             var hasWays = false;
41327
41328             for (i = 0; i < checkWays.length; i++) {
41329               way = checkWays[i];
41330               if (!isRoad(way) && !memberOfRestriction(way)) continue;
41331               ways.push(way); // it's a road, or it's already in a turn restriction
41332
41333               hasWays = true; // check the way's children for more key vertices
41334
41335               nodes = utilArrayUniq(graph.childNodes(way));
41336
41337               for (j = 0; j < nodes.length; j++) {
41338                 node = nodes[j];
41339                 if (node === vertex) continue; // same thing
41340
41341                 if (vertices.indexOf(node) !== -1) continue; // seen it already
41342
41343                 if (geoSphericalDistance(node.loc, startNode.loc) > maxDistance) continue; // too far from start
41344                 // a key vertex will have parents that are also roads
41345
41346                 var hasParents = false;
41347                 parents = graph.parentWays(node);
41348
41349                 for (k = 0; k < parents.length; k++) {
41350                   parent = parents[k];
41351                   if (parent === way) continue; // same thing
41352
41353                   if (ways.indexOf(parent) !== -1) continue; // seen it already
41354
41355                   if (!isRoad(parent)) continue; // not a road
41356
41357                   hasParents = true;
41358                   break;
41359                 }
41360
41361                 if (hasParents) {
41362                   checkVertices.push(node);
41363                 }
41364               }
41365             }
41366
41367             if (hasWays) {
41368               vertices.push(vertex);
41369             }
41370           }
41371
41372           vertices = utilArrayUniq(vertices);
41373           ways = utilArrayUniq(ways); // STEP 2:  Build a virtual graph containing only the entities in the intersection..
41374           // Everything done after this step should act on the virtual graph
41375           // Any actions that must be performed later to the main graph go in `actions` array
41376
41377           ways.forEach(function (way) {
41378             graph.childNodes(way).forEach(function (node) {
41379               vgraph = vgraph.replace(node);
41380             });
41381             vgraph = vgraph.replace(way);
41382             graph.parentRelations(way).forEach(function (relation) {
41383               if (relation.isRestriction()) {
41384                 if (relation.isValidRestriction(graph)) {
41385                   vgraph = vgraph.replace(relation);
41386                 } else if (relation.isComplete(graph)) {
41387                   actions.push(actionDeleteRelation(relation.id));
41388                 }
41389               }
41390             });
41391           }); // STEP 3:  Force all oneways to be drawn in the forward direction
41392
41393           ways.forEach(function (w) {
41394             var way = vgraph.entity(w.id);
41395
41396             if (way.tags.oneway === '-1') {
41397               var action = actionReverse(way.id, {
41398                 reverseOneway: true
41399               });
41400               actions.push(action);
41401               vgraph = action(vgraph);
41402             }
41403           }); // STEP 4:  Split ways on key vertices
41404
41405           var origCount = osmEntity.id.next.way;
41406           vertices.forEach(function (v) {
41407             // This is an odd way to do it, but we need to find all the ways that
41408             // will be split here, then split them one at a time to ensure that these
41409             // actions can be replayed on the main graph exactly in the same order.
41410             // (It is unintuitive, but the order of ways returned from graph.parentWays()
41411             // is arbitrary, depending on how the main graph and vgraph were built)
41412             var splitAll = actionSplit([v.id]).keepHistoryOn('first');
41413
41414             if (!splitAll.disabled(vgraph)) {
41415               splitAll.ways(vgraph).forEach(function (way) {
41416                 var splitOne = actionSplit([v.id]).limitWays([way.id]).keepHistoryOn('first');
41417                 actions.push(splitOne);
41418                 vgraph = splitOne(vgraph);
41419               });
41420             }
41421           }); // In here is where we should also split the intersection at nearby junction.
41422           //   for https://github.com/mapbox/iD-internal/issues/31
41423           // nearbyVertices.forEach(function(v) {
41424           // });
41425           // Reasons why we reset the way id count here:
41426           //  1. Continuity with way ids created by the splits so that we can replay
41427           //     these actions later if the user decides to create a turn restriction
41428           //  2. Avoids churning way ids just by hovering over a vertex
41429           //     and displaying the turn restriction editor
41430
41431           osmEntity.id.next.way = origCount; // STEP 5:  Update arrays to point to vgraph entities
41432
41433           vertexIds = vertices.map(function (v) {
41434             return v.id;
41435           });
41436           vertices = [];
41437           ways = [];
41438           vertexIds.forEach(function (id) {
41439             var vertex = vgraph.entity(id);
41440             var parents = vgraph.parentWays(vertex);
41441             vertices.push(vertex);
41442             ways = ways.concat(parents);
41443           });
41444           vertices = utilArrayUniq(vertices);
41445           ways = utilArrayUniq(ways);
41446           vertexIds = vertices.map(function (v) {
41447             return v.id;
41448           });
41449           wayIds = ways.map(function (w) {
41450             return w.id;
41451           }); // STEP 6:  Update the ways with some metadata that will be useful for
41452           // walking the intersection graph later and rendering turn arrows.
41453
41454           function withMetadata(way, vertexIds) {
41455             var __oneWay = way.isOneWay(); // which affixes are key vertices?
41456
41457
41458             var __first = vertexIds.indexOf(way.first()) !== -1;
41459
41460             var __last = vertexIds.indexOf(way.last()) !== -1; // what roles is this way eligible for?
41461
41462
41463             var __via = __first && __last;
41464
41465             var __from = __first && !__oneWay || __last;
41466
41467             var __to = __first || __last && !__oneWay;
41468
41469             return way.update({
41470               __first: __first,
41471               __last: __last,
41472               __from: __from,
41473               __via: __via,
41474               __to: __to,
41475               __oneWay: __oneWay
41476             });
41477           }
41478
41479           ways = [];
41480           wayIds.forEach(function (id) {
41481             var way = withMetadata(vgraph.entity(id), vertexIds);
41482             vgraph = vgraph.replace(way);
41483             ways.push(way);
41484           }); // STEP 7:  Simplify - This is an iterative process where we:
41485           //  1. Find trivial vertices with only 2 parents
41486           //  2. trim off the leaf way from those vertices and remove from vgraph
41487
41488           var keepGoing;
41489           var removeWayIds = [];
41490           var removeVertexIds = [];
41491
41492           do {
41493             keepGoing = false;
41494             checkVertices = vertexIds.slice();
41495
41496             for (i = 0; i < checkVertices.length; i++) {
41497               var vertexId = checkVertices[i];
41498               vertex = vgraph.hasEntity(vertexId);
41499
41500               if (!vertex) {
41501                 if (vertexIds.indexOf(vertexId) !== -1) {
41502                   vertexIds.splice(vertexIds.indexOf(vertexId), 1); // stop checking this one
41503                 }
41504
41505                 removeVertexIds.push(vertexId);
41506                 continue;
41507               }
41508
41509               parents = vgraph.parentWays(vertex);
41510
41511               if (parents.length < 3) {
41512                 if (vertexIds.indexOf(vertexId) !== -1) {
41513                   vertexIds.splice(vertexIds.indexOf(vertexId), 1); // stop checking this one
41514                 }
41515               }
41516
41517               if (parents.length === 2) {
41518                 // vertex with 2 parents is trivial
41519                 var a = parents[0];
41520                 var b = parents[1];
41521                 var aIsLeaf = a && !a.__via;
41522                 var bIsLeaf = b && !b.__via;
41523                 var leaf, survivor;
41524
41525                 if (aIsLeaf && !bIsLeaf) {
41526                   leaf = a;
41527                   survivor = b;
41528                 } else if (!aIsLeaf && bIsLeaf) {
41529                   leaf = b;
41530                   survivor = a;
41531                 }
41532
41533                 if (leaf && survivor) {
41534                   survivor = withMetadata(survivor, vertexIds); // update survivor way
41535
41536                   vgraph = vgraph.replace(survivor).remove(leaf); // update graph
41537
41538                   removeWayIds.push(leaf.id);
41539                   keepGoing = true;
41540                 }
41541               }
41542
41543               parents = vgraph.parentWays(vertex);
41544
41545               if (parents.length < 2) {
41546                 // vertex is no longer a key vertex
41547                 if (vertexIds.indexOf(vertexId) !== -1) {
41548                   vertexIds.splice(vertexIds.indexOf(vertexId), 1); // stop checking this one
41549                 }
41550
41551                 removeVertexIds.push(vertexId);
41552                 keepGoing = true;
41553               }
41554
41555               if (parents.length < 1) {
41556                 // vertex is no longer attached to anything
41557                 vgraph = vgraph.remove(vertex);
41558               }
41559             }
41560           } while (keepGoing);
41561
41562           vertices = vertices.filter(function (vertex) {
41563             return removeVertexIds.indexOf(vertex.id) === -1;
41564           }).map(function (vertex) {
41565             return vgraph.entity(vertex.id);
41566           });
41567           ways = ways.filter(function (way) {
41568             return removeWayIds.indexOf(way.id) === -1;
41569           }).map(function (way) {
41570             return vgraph.entity(way.id);
41571           }); // OK!  Here is our intersection..
41572
41573           var intersection = {
41574             graph: vgraph,
41575             actions: actions,
41576             vertices: vertices,
41577             ways: ways
41578           }; // Get all the valid turns through this intersection given a starting way id.
41579           // This operates on the virtual graph for everything.
41580           //
41581           // Basically, walk through all possible paths from starting way,
41582           //   honoring the existing turn restrictions as we go (watch out for loops!)
41583           //
41584           // For each path found, generate and return a `osmTurn` datastructure.
41585           //
41586
41587           intersection.turns = function (fromWayId, maxViaWay) {
41588             if (!fromWayId) return [];
41589             if (!maxViaWay) maxViaWay = 0;
41590             var vgraph = intersection.graph;
41591             var keyVertexIds = intersection.vertices.map(function (v) {
41592               return v.id;
41593             });
41594             var start = vgraph.entity(fromWayId);
41595             if (!start || !(start.__from || start.__via)) return []; // maxViaWay=0   from-*-to              (0 vias)
41596             // maxViaWay=1   from-*-via-*-to        (1 via max)
41597             // maxViaWay=2   from-*-via-*-via-*-to  (2 vias max)
41598
41599             var maxPathLength = maxViaWay * 2 + 3;
41600             var turns = [];
41601             step(start);
41602             return turns; // traverse the intersection graph and find all the valid paths
41603
41604             function step(entity, currPath, currRestrictions, matchedRestriction) {
41605               currPath = (currPath || []).slice(); // shallow copy
41606
41607               if (currPath.length >= maxPathLength) return;
41608               currPath.push(entity.id);
41609               currRestrictions = (currRestrictions || []).slice(); // shallow copy
41610
41611               var i, j;
41612
41613               if (entity.type === 'node') {
41614                 var parents = vgraph.parentWays(entity);
41615                 var nextWays = []; // which ways can we step into?
41616
41617                 for (i = 0; i < parents.length; i++) {
41618                   var way = parents[i]; // if next way is a oneway incoming to this vertex, skip
41619
41620                   if (way.__oneWay && way.nodes[0] !== entity.id) continue; // if we have seen it before (allowing for an initial u-turn), skip
41621
41622                   if (currPath.indexOf(way.id) !== -1 && currPath.length >= 3) continue; // Check all "current" restrictions (where we've already walked the `FROM`)
41623
41624                   var restrict = null;
41625
41626                   for (j = 0; j < currRestrictions.length; j++) {
41627                     var restriction = currRestrictions[j];
41628                     var f = restriction.memberByRole('from');
41629                     var v = restriction.membersByRole('via');
41630                     var t = restriction.memberByRole('to');
41631                     var isOnly = /^only_/.test(restriction.tags.restriction); // Does the current path match this turn restriction?
41632
41633                     var matchesFrom = f.id === fromWayId;
41634                     var matchesViaTo = false;
41635                     var isAlongOnlyPath = false;
41636
41637                     if (t.id === way.id) {
41638                       // match TO
41639                       if (v.length === 1 && v[0].type === 'node') {
41640                         // match VIA node
41641                         matchesViaTo = v[0].id === entity.id && (matchesFrom && currPath.length === 2 || !matchesFrom && currPath.length > 2);
41642                       } else {
41643                         // match all VIA ways
41644                         var pathVias = [];
41645
41646                         for (k = 2; k < currPath.length; k += 2) {
41647                           // k = 2 skips FROM
41648                           pathVias.push(currPath[k]); // (path goes way-node-way...)
41649                         }
41650
41651                         var restrictionVias = [];
41652
41653                         for (k = 0; k < v.length; k++) {
41654                           if (v[k].type === 'way') {
41655                             restrictionVias.push(v[k].id);
41656                           }
41657                         }
41658
41659                         var diff = utilArrayDifference(pathVias, restrictionVias);
41660                         matchesViaTo = !diff.length;
41661                       }
41662                     } else if (isOnly) {
41663                       for (k = 0; k < v.length; k++) {
41664                         // way doesn't match TO, but is one of the via ways along the path of an "only"
41665                         if (v[k].type === 'way' && v[k].id === way.id) {
41666                           isAlongOnlyPath = true;
41667                           break;
41668                         }
41669                       }
41670                     }
41671
41672                     if (matchesViaTo) {
41673                       if (isOnly) {
41674                         restrict = {
41675                           id: restriction.id,
41676                           direct: matchesFrom,
41677                           from: f.id,
41678                           only: true,
41679                           end: true
41680                         };
41681                       } else {
41682                         restrict = {
41683                           id: restriction.id,
41684                           direct: matchesFrom,
41685                           from: f.id,
41686                           no: true,
41687                           end: true
41688                         };
41689                       }
41690                     } else {
41691                       // indirect - caused by a different nearby restriction
41692                       if (isAlongOnlyPath) {
41693                         restrict = {
41694                           id: restriction.id,
41695                           direct: false,
41696                           from: f.id,
41697                           only: true,
41698                           end: false
41699                         };
41700                       } else if (isOnly) {
41701                         restrict = {
41702                           id: restriction.id,
41703                           direct: false,
41704                           from: f.id,
41705                           no: true,
41706                           end: true
41707                         };
41708                       }
41709                     } // stop looking if we find a "direct" restriction (matching FROM, VIA, TO)
41710
41711
41712                     if (restrict && restrict.direct) break;
41713                   }
41714
41715                   nextWays.push({
41716                     way: way,
41717                     restrict: restrict
41718                   });
41719                 }
41720
41721                 nextWays.forEach(function (nextWay) {
41722                   step(nextWay.way, currPath, currRestrictions, nextWay.restrict);
41723                 });
41724               } else {
41725                 // entity.type === 'way'
41726                 if (currPath.length >= 3) {
41727                   // this is a "complete" path..
41728                   var turnPath = currPath.slice(); // shallow copy
41729                   // an indirect restriction - only include the partial path (starting at FROM)
41730
41731                   if (matchedRestriction && matchedRestriction.direct === false) {
41732                     for (i = 0; i < turnPath.length; i++) {
41733                       if (turnPath[i] === matchedRestriction.from) {
41734                         turnPath = turnPath.slice(i);
41735                         break;
41736                       }
41737                     }
41738                   }
41739
41740                   var turn = pathToTurn(turnPath);
41741
41742                   if (turn) {
41743                     if (matchedRestriction) {
41744                       turn.restrictionID = matchedRestriction.id;
41745                       turn.no = matchedRestriction.no;
41746                       turn.only = matchedRestriction.only;
41747                       turn.direct = matchedRestriction.direct;
41748                     }
41749
41750                     turns.push(osmTurn(turn));
41751                   }
41752
41753                   if (currPath[0] === currPath[2]) return; // if we made a u-turn - stop here
41754                 }
41755
41756                 if (matchedRestriction && matchedRestriction.end) return; // don't advance any further
41757                 // which nodes can we step into?
41758
41759                 var n1 = vgraph.entity(entity.first());
41760                 var n2 = vgraph.entity(entity.last());
41761                 var dist = geoSphericalDistance(n1.loc, n2.loc);
41762                 var nextNodes = [];
41763
41764                 if (currPath.length > 1) {
41765                   if (dist > maxDistance) return; // the next node is too far
41766
41767                   if (!entity.__via) return; // this way is a leaf / can't be a via
41768                 }
41769
41770                 if (!entity.__oneWay && // bidirectional..
41771                 keyVertexIds.indexOf(n1.id) !== -1 && // key vertex..
41772                 currPath.indexOf(n1.id) === -1) {
41773                   // haven't seen it yet..
41774                   nextNodes.push(n1); // can advance to first node
41775                 }
41776
41777                 if (keyVertexIds.indexOf(n2.id) !== -1 && // key vertex..
41778                 currPath.indexOf(n2.id) === -1) {
41779                   // haven't seen it yet..
41780                   nextNodes.push(n2); // can advance to last node
41781                 }
41782
41783                 nextNodes.forEach(function (nextNode) {
41784                   // gather restrictions FROM this way
41785                   var fromRestrictions = vgraph.parentRelations(entity).filter(function (r) {
41786                     if (!r.isRestriction()) return false;
41787                     var f = r.memberByRole('from');
41788                     if (!f || f.id !== entity.id) return false;
41789                     var isOnly = /^only_/.test(r.tags.restriction);
41790                     if (!isOnly) return true; // `only_` restrictions only matter along the direction of the VIA - #4849
41791
41792                     var isOnlyVia = false;
41793                     var v = r.membersByRole('via');
41794
41795                     if (v.length === 1 && v[0].type === 'node') {
41796                       // via node
41797                       isOnlyVia = v[0].id === nextNode.id;
41798                     } else {
41799                       // via way(s)
41800                       for (var i = 0; i < v.length; i++) {
41801                         if (v[i].type !== 'way') continue;
41802                         var viaWay = vgraph.entity(v[i].id);
41803
41804                         if (viaWay.first() === nextNode.id || viaWay.last() === nextNode.id) {
41805                           isOnlyVia = true;
41806                           break;
41807                         }
41808                       }
41809                     }
41810
41811                     return isOnlyVia;
41812                   });
41813                   step(nextNode, currPath, currRestrictions.concat(fromRestrictions), false);
41814                 });
41815               }
41816             } // assumes path is alternating way-node-way of odd length
41817
41818
41819             function pathToTurn(path) {
41820               if (path.length < 3) return;
41821               var fromWayId, fromNodeId, fromVertexId;
41822               var toWayId, toNodeId, toVertexId;
41823               var viaWayIds, viaNodeId, isUturn;
41824               fromWayId = path[0];
41825               toWayId = path[path.length - 1];
41826
41827               if (path.length === 3 && fromWayId === toWayId) {
41828                 // u turn
41829                 var way = vgraph.entity(fromWayId);
41830                 if (way.__oneWay) return null;
41831                 isUturn = true;
41832                 viaNodeId = fromVertexId = toVertexId = path[1];
41833                 fromNodeId = toNodeId = adjacentNode(fromWayId, viaNodeId);
41834               } else {
41835                 isUturn = false;
41836                 fromVertexId = path[1];
41837                 fromNodeId = adjacentNode(fromWayId, fromVertexId);
41838                 toVertexId = path[path.length - 2];
41839                 toNodeId = adjacentNode(toWayId, toVertexId);
41840
41841                 if (path.length === 3) {
41842                   viaNodeId = path[1];
41843                 } else {
41844                   viaWayIds = path.filter(function (entityId) {
41845                     return entityId[0] === 'w';
41846                   });
41847                   viaWayIds = viaWayIds.slice(1, viaWayIds.length - 1); // remove first, last
41848                 }
41849               }
41850
41851               return {
41852                 key: path.join('_'),
41853                 path: path,
41854                 from: {
41855                   node: fromNodeId,
41856                   way: fromWayId,
41857                   vertex: fromVertexId
41858                 },
41859                 via: {
41860                   node: viaNodeId,
41861                   ways: viaWayIds
41862                 },
41863                 to: {
41864                   node: toNodeId,
41865                   way: toWayId,
41866                   vertex: toVertexId
41867                 },
41868                 u: isUturn
41869               };
41870
41871               function adjacentNode(wayId, affixId) {
41872                 var nodes = vgraph.entity(wayId).nodes;
41873                 return affixId === nodes[0] ? nodes[1] : nodes[nodes.length - 2];
41874               }
41875             }
41876           };
41877
41878           return intersection;
41879         }
41880         function osmInferRestriction(graph, turn, projection) {
41881           var fromWay = graph.entity(turn.from.way);
41882           var fromNode = graph.entity(turn.from.node);
41883           var fromVertex = graph.entity(turn.from.vertex);
41884           var toWay = graph.entity(turn.to.way);
41885           var toNode = graph.entity(turn.to.node);
41886           var toVertex = graph.entity(turn.to.vertex);
41887           var fromOneWay = fromWay.tags.oneway === 'yes';
41888           var toOneWay = toWay.tags.oneway === 'yes';
41889           var angle = (geoAngle(fromVertex, fromNode, projection) - geoAngle(toVertex, toNode, projection)) * 180 / Math.PI;
41890
41891           while (angle < 0) {
41892             angle += 360;
41893           }
41894
41895           if (fromNode === toNode) {
41896             return 'no_u_turn';
41897           }
41898
41899           if ((angle < 23 || angle > 336) && fromOneWay && toOneWay) {
41900             return 'no_u_turn'; // wider tolerance for u-turn if both ways are oneway
41901           }
41902
41903           if ((angle < 40 || angle > 319) && fromOneWay && toOneWay && turn.from.vertex !== turn.to.vertex) {
41904             return 'no_u_turn'; // even wider tolerance for u-turn if there is a via way (from !== to)
41905           }
41906
41907           if (angle < 158) {
41908             return 'no_right_turn';
41909           }
41910
41911           if (angle > 202) {
41912             return 'no_left_turn';
41913           }
41914
41915           return 'no_straight_on';
41916         }
41917
41918         function actionMergePolygon(ids, newRelationId) {
41919           function groupEntities(graph) {
41920             var entities = ids.map(function (id) {
41921               return graph.entity(id);
41922             });
41923             var geometryGroups = utilArrayGroupBy(entities, function (entity) {
41924               if (entity.type === 'way' && entity.isClosed()) {
41925                 return 'closedWay';
41926               } else if (entity.type === 'relation' && entity.isMultipolygon()) {
41927                 return 'multipolygon';
41928               } else {
41929                 return 'other';
41930               }
41931             });
41932             return Object.assign({
41933               closedWay: [],
41934               multipolygon: [],
41935               other: []
41936             }, geometryGroups);
41937           }
41938
41939           var action = function action(graph) {
41940             var entities = groupEntities(graph); // An array representing all the polygons that are part of the multipolygon.
41941             //
41942             // Each element is itself an array of objects with an id property, and has a
41943             // locs property which is an array of the locations forming the polygon.
41944
41945             var polygons = entities.multipolygon.reduce(function (polygons, m) {
41946               return polygons.concat(osmJoinWays(m.members, graph));
41947             }, []).concat(entities.closedWay.map(function (d) {
41948               var member = [{
41949                 id: d.id
41950               }];
41951               member.nodes = graph.childNodes(d);
41952               return member;
41953             })); // contained is an array of arrays of boolean values,
41954             // where contained[j][k] is true iff the jth way is
41955             // contained by the kth way.
41956
41957             var contained = polygons.map(function (w, i) {
41958               return polygons.map(function (d, n) {
41959                 if (i === n) return null;
41960                 return geoPolygonContainsPolygon(d.nodes.map(function (n) {
41961                   return n.loc;
41962                 }), w.nodes.map(function (n) {
41963                   return n.loc;
41964                 }));
41965               });
41966             }); // Sort all polygons as either outer or inner ways
41967
41968             var members = [];
41969             var outer = true;
41970
41971             while (polygons.length) {
41972               extractUncontained(polygons);
41973               polygons = polygons.filter(isContained);
41974               contained = contained.filter(isContained).map(filterContained);
41975             }
41976
41977             function isContained(d, i) {
41978               return contained[i].some(function (val) {
41979                 return val;
41980               });
41981             }
41982
41983             function filterContained(d) {
41984               return d.filter(isContained);
41985             }
41986
41987             function extractUncontained(polygons) {
41988               polygons.forEach(function (d, i) {
41989                 if (!isContained(d, i)) {
41990                   d.forEach(function (member) {
41991                     members.push({
41992                       type: 'way',
41993                       id: member.id,
41994                       role: outer ? 'outer' : 'inner'
41995                     });
41996                   });
41997                 }
41998               });
41999               outer = !outer;
42000             } // Move all tags to one relation.
42001             // Keep the oldest multipolygon alive if it exists.
42002
42003
42004             var relation;
42005
42006             if (entities.multipolygon.length > 0) {
42007               var oldestID = utilOldestID(entities.multipolygon.map(function (entity) {
42008                 return entity.id;
42009               }));
42010               relation = entities.multipolygon.find(function (entity) {
42011                 return entity.id === oldestID;
42012               });
42013             } else {
42014               relation = osmRelation({
42015                 id: newRelationId,
42016                 tags: {
42017                   type: 'multipolygon'
42018                 }
42019               });
42020             }
42021
42022             entities.multipolygon.forEach(function (m) {
42023               if (m.id !== relation.id) {
42024                 relation = relation.mergeTags(m.tags);
42025                 graph = graph.remove(m);
42026               }
42027             });
42028             entities.closedWay.forEach(function (way) {
42029               function isThisOuter(m) {
42030                 return m.id === way.id && m.role !== 'inner';
42031               }
42032
42033               if (members.some(isThisOuter)) {
42034                 relation = relation.mergeTags(way.tags);
42035                 graph = graph.replace(way.update({
42036                   tags: {}
42037                 }));
42038               }
42039             });
42040             return graph.replace(relation.update({
42041               members: members,
42042               tags: utilObjectOmit(relation.tags, ['area'])
42043             }));
42044           };
42045
42046           action.disabled = function (graph) {
42047             var entities = groupEntities(graph);
42048
42049             if (entities.other.length > 0 || entities.closedWay.length + entities.multipolygon.length < 2) {
42050               return 'not_eligible';
42051             }
42052
42053             if (!entities.multipolygon.every(function (r) {
42054               return r.isComplete(graph);
42055             })) {
42056               return 'incomplete_relation';
42057             }
42058
42059             if (!entities.multipolygon.length) {
42060               var sharedMultipolygons = [];
42061               entities.closedWay.forEach(function (way, i) {
42062                 if (i === 0) {
42063                   sharedMultipolygons = graph.parentMultipolygons(way);
42064                 } else {
42065                   sharedMultipolygons = utilArrayIntersection(sharedMultipolygons, graph.parentMultipolygons(way));
42066                 }
42067               });
42068               sharedMultipolygons = sharedMultipolygons.filter(function (relation) {
42069                 return relation.members.length === entities.closedWay.length;
42070               });
42071
42072               if (sharedMultipolygons.length) {
42073                 // don't create a new multipolygon if it'd be redundant
42074                 return 'not_eligible';
42075               }
42076             } else if (entities.closedWay.some(function (way) {
42077               return utilArrayIntersection(graph.parentMultipolygons(way), entities.multipolygon).length;
42078             })) {
42079               // don't add a way to a multipolygon again if it's already a member
42080               return 'not_eligible';
42081             }
42082           };
42083
42084           return action;
42085         }
42086
42087         var DESCRIPTORS$1 = descriptors;
42088         var objectDefinePropertyModule = objectDefineProperty;
42089         var regExpFlags = regexpFlags$1;
42090         var fails$4 = fails$S;
42091
42092         var RegExpPrototype = RegExp.prototype;
42093
42094         var FORCED$2 = DESCRIPTORS$1 && fails$4(function () {
42095           // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
42096           return Object.getOwnPropertyDescriptor(RegExpPrototype, 'flags').get.call({ dotAll: true, sticky: true }) !== 'sy';
42097         });
42098
42099         // `RegExp.prototype.flags` getter
42100         // https://tc39.es/ecma262/#sec-get-regexp.prototype.flags
42101         if (FORCED$2) objectDefinePropertyModule.f(RegExpPrototype, 'flags', {
42102           configurable: true,
42103           get: regExpFlags
42104         });
42105
42106         var fastDeepEqual = function equal(a, b) {
42107           if (a === b) return true;
42108
42109           if (a && b && _typeof(a) == 'object' && _typeof(b) == 'object') {
42110             if (a.constructor !== b.constructor) return false;
42111             var length, i, keys;
42112
42113             if (Array.isArray(a)) {
42114               length = a.length;
42115               if (length != b.length) return false;
42116
42117               for (i = length; i-- !== 0;) {
42118                 if (!equal(a[i], b[i])) return false;
42119               }
42120
42121               return true;
42122             }
42123
42124             if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
42125             if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
42126             if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
42127             keys = Object.keys(a);
42128             length = keys.length;
42129             if (length !== Object.keys(b).length) return false;
42130
42131             for (i = length; i-- !== 0;) {
42132               if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
42133             }
42134
42135             for (i = length; i-- !== 0;) {
42136               var key = keys[i];
42137               if (!equal(a[key], b[key])) return false;
42138             }
42139
42140             return true;
42141           } // true if both NaN, false otherwise
42142
42143
42144           return a !== a && b !== b;
42145         };
42146
42147         // J. W. Hunt and M. D. McIlroy, An algorithm for differential buffer
42148         // comparison, Bell Telephone Laboratories CSTR #41 (1976)
42149         // http://www.cs.dartmouth.edu/~doug/
42150         // https://en.wikipedia.org/wiki/Longest_common_subsequence_problem
42151         //
42152         // Expects two arrays, finds longest common sequence
42153
42154         function LCS(buffer1, buffer2) {
42155           var equivalenceClasses = {};
42156
42157           for (var j = 0; j < buffer2.length; j++) {
42158             var item = buffer2[j];
42159
42160             if (equivalenceClasses[item]) {
42161               equivalenceClasses[item].push(j);
42162             } else {
42163               equivalenceClasses[item] = [j];
42164             }
42165           }
42166
42167           var NULLRESULT = {
42168             buffer1index: -1,
42169             buffer2index: -1,
42170             chain: null
42171           };
42172           var candidates = [NULLRESULT];
42173
42174           for (var i = 0; i < buffer1.length; i++) {
42175             var _item = buffer1[i];
42176             var buffer2indices = equivalenceClasses[_item] || [];
42177             var r = 0;
42178             var c = candidates[0];
42179
42180             for (var jx = 0; jx < buffer2indices.length; jx++) {
42181               var _j = buffer2indices[jx];
42182               var s = void 0;
42183
42184               for (s = r; s < candidates.length; s++) {
42185                 if (candidates[s].buffer2index < _j && (s === candidates.length - 1 || candidates[s + 1].buffer2index > _j)) {
42186                   break;
42187                 }
42188               }
42189
42190               if (s < candidates.length) {
42191                 var newCandidate = {
42192                   buffer1index: i,
42193                   buffer2index: _j,
42194                   chain: candidates[s]
42195                 };
42196
42197                 if (r === candidates.length) {
42198                   candidates.push(c);
42199                 } else {
42200                   candidates[r] = c;
42201                 }
42202
42203                 r = s + 1;
42204                 c = newCandidate;
42205
42206                 if (r === candidates.length) {
42207                   break; // no point in examining further (j)s
42208                 }
42209               }
42210             }
42211
42212             candidates[r] = c;
42213           } // At this point, we know the LCS: it's in the reverse of the
42214           // linked-list through .chain of candidates[candidates.length - 1].
42215
42216
42217           return candidates[candidates.length - 1];
42218         } // We apply the LCS to build a 'comm'-style picture of the
42219         // offsets and lengths of mismatched chunks in the input
42220         // buffers. This is used by diff3MergeRegions.
42221
42222
42223         function diffIndices(buffer1, buffer2) {
42224           var lcs = LCS(buffer1, buffer2);
42225           var result = [];
42226           var tail1 = buffer1.length;
42227           var tail2 = buffer2.length;
42228
42229           for (var candidate = lcs; candidate !== null; candidate = candidate.chain) {
42230             var mismatchLength1 = tail1 - candidate.buffer1index - 1;
42231             var mismatchLength2 = tail2 - candidate.buffer2index - 1;
42232             tail1 = candidate.buffer1index;
42233             tail2 = candidate.buffer2index;
42234
42235             if (mismatchLength1 || mismatchLength2) {
42236               result.push({
42237                 buffer1: [tail1 + 1, mismatchLength1],
42238                 buffer1Content: buffer1.slice(tail1 + 1, tail1 + 1 + mismatchLength1),
42239                 buffer2: [tail2 + 1, mismatchLength2],
42240                 buffer2Content: buffer2.slice(tail2 + 1, tail2 + 1 + mismatchLength2)
42241               });
42242             }
42243           }
42244
42245           result.reverse();
42246           return result;
42247         } // We apply the LCS to build a JSON representation of a
42248         // independently derived from O, returns a fairly complicated
42249         // internal representation of merge decisions it's taken. The
42250         // interested reader may wish to consult
42251         //
42252         // Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce.
42253         // 'A Formal Investigation of ' In Arvind and Prasad,
42254         // editors, Foundations of Software Technology and Theoretical
42255         // Computer Science (FSTTCS), December 2007.
42256         //
42257         // (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf)
42258         //
42259
42260
42261         function diff3MergeRegions(a, o, b) {
42262           // "hunks" are array subsets where `a` or `b` are different from `o`
42263           // https://www.gnu.org/software/diffutils/manual/html_node/diff3-Hunks.html
42264           var hunks = [];
42265
42266           function addHunk(h, ab) {
42267             hunks.push({
42268               ab: ab,
42269               oStart: h.buffer1[0],
42270               oLength: h.buffer1[1],
42271               // length of o to remove
42272               abStart: h.buffer2[0],
42273               abLength: h.buffer2[1] // length of a/b to insert
42274               // abContent: (ab === 'a' ? a : b).slice(h.buffer2[0], h.buffer2[0] + h.buffer2[1])
42275
42276             });
42277           }
42278
42279           diffIndices(o, a).forEach(function (item) {
42280             return addHunk(item, 'a');
42281           });
42282           diffIndices(o, b).forEach(function (item) {
42283             return addHunk(item, 'b');
42284           });
42285           hunks.sort(function (x, y) {
42286             return x.oStart - y.oStart;
42287           });
42288           var results = [];
42289           var currOffset = 0;
42290
42291           function advanceTo(endOffset) {
42292             if (endOffset > currOffset) {
42293               results.push({
42294                 stable: true,
42295                 buffer: 'o',
42296                 bufferStart: currOffset,
42297                 bufferLength: endOffset - currOffset,
42298                 bufferContent: o.slice(currOffset, endOffset)
42299               });
42300               currOffset = endOffset;
42301             }
42302           }
42303
42304           while (hunks.length) {
42305             var hunk = hunks.shift();
42306             var regionStart = hunk.oStart;
42307             var regionEnd = hunk.oStart + hunk.oLength;
42308             var regionHunks = [hunk];
42309             advanceTo(regionStart); // Try to pull next overlapping hunk into this region
42310
42311             while (hunks.length) {
42312               var nextHunk = hunks[0];
42313               var nextHunkStart = nextHunk.oStart;
42314               if (nextHunkStart > regionEnd) break; // no overlap
42315
42316               regionEnd = Math.max(regionEnd, nextHunkStart + nextHunk.oLength);
42317               regionHunks.push(hunks.shift());
42318             }
42319
42320             if (regionHunks.length === 1) {
42321               // Only one hunk touches this region, meaning that there is no conflict here.
42322               // Either `a` or `b` is inserting into a region of `o` unchanged by the other.
42323               if (hunk.abLength > 0) {
42324                 var buffer = hunk.ab === 'a' ? a : b;
42325                 results.push({
42326                   stable: true,
42327                   buffer: hunk.ab,
42328                   bufferStart: hunk.abStart,
42329                   bufferLength: hunk.abLength,
42330                   bufferContent: buffer.slice(hunk.abStart, hunk.abStart + hunk.abLength)
42331                 });
42332               }
42333             } else {
42334               // A true a/b conflict. Determine the bounds involved from `a`, `o`, and `b`.
42335               // Effectively merge all the `a` hunks into one giant hunk, then do the
42336               // same for the `b` hunks; then, correct for skew in the regions of `o`
42337               // that each side changed, and report appropriate spans for the three sides.
42338               var bounds = {
42339                 a: [a.length, -1, o.length, -1],
42340                 b: [b.length, -1, o.length, -1]
42341               };
42342
42343               while (regionHunks.length) {
42344                 hunk = regionHunks.shift();
42345                 var oStart = hunk.oStart;
42346                 var oEnd = oStart + hunk.oLength;
42347                 var abStart = hunk.abStart;
42348                 var abEnd = abStart + hunk.abLength;
42349                 var _b = bounds[hunk.ab];
42350                 _b[0] = Math.min(abStart, _b[0]);
42351                 _b[1] = Math.max(abEnd, _b[1]);
42352                 _b[2] = Math.min(oStart, _b[2]);
42353                 _b[3] = Math.max(oEnd, _b[3]);
42354               }
42355
42356               var aStart = bounds.a[0] + (regionStart - bounds.a[2]);
42357               var aEnd = bounds.a[1] + (regionEnd - bounds.a[3]);
42358               var bStart = bounds.b[0] + (regionStart - bounds.b[2]);
42359               var bEnd = bounds.b[1] + (regionEnd - bounds.b[3]);
42360               var result = {
42361                 stable: false,
42362                 aStart: aStart,
42363                 aLength: aEnd - aStart,
42364                 aContent: a.slice(aStart, aEnd),
42365                 oStart: regionStart,
42366                 oLength: regionEnd - regionStart,
42367                 oContent: o.slice(regionStart, regionEnd),
42368                 bStart: bStart,
42369                 bLength: bEnd - bStart,
42370                 bContent: b.slice(bStart, bEnd)
42371               };
42372               results.push(result);
42373             }
42374
42375             currOffset = regionEnd;
42376           }
42377
42378           advanceTo(o.length);
42379           return results;
42380         } // Applies the output of diff3MergeRegions to actually
42381         // construct the merged buffer; the returned result alternates
42382         // between 'ok' and 'conflict' blocks.
42383         // A "false conflict" is where `a` and `b` both change the same from `o`
42384
42385
42386         function diff3Merge(a, o, b, options) {
42387           var defaults = {
42388             excludeFalseConflicts: true,
42389             stringSeparator: /\s+/
42390           };
42391           options = Object.assign(defaults, options);
42392           var aString = typeof a === 'string';
42393           var oString = typeof o === 'string';
42394           var bString = typeof b === 'string';
42395           if (aString) a = a.split(options.stringSeparator);
42396           if (oString) o = o.split(options.stringSeparator);
42397           if (bString) b = b.split(options.stringSeparator);
42398           var results = [];
42399           var regions = diff3MergeRegions(a, o, b);
42400           var okBuffer = [];
42401
42402           function flushOk() {
42403             if (okBuffer.length) {
42404               results.push({
42405                 ok: okBuffer
42406               });
42407             }
42408
42409             okBuffer = [];
42410           }
42411
42412           function isFalseConflict(a, b) {
42413             if (a.length !== b.length) return false;
42414
42415             for (var i = 0; i < a.length; i++) {
42416               if (a[i] !== b[i]) return false;
42417             }
42418
42419             return true;
42420           }
42421
42422           regions.forEach(function (region) {
42423             if (region.stable) {
42424               var _okBuffer;
42425
42426               (_okBuffer = okBuffer).push.apply(_okBuffer, _toConsumableArray(region.bufferContent));
42427             } else {
42428               if (options.excludeFalseConflicts && isFalseConflict(region.aContent, region.bContent)) {
42429                 var _okBuffer2;
42430
42431                 (_okBuffer2 = okBuffer).push.apply(_okBuffer2, _toConsumableArray(region.aContent));
42432               } else {
42433                 flushOk();
42434                 results.push({
42435                   conflict: {
42436                     a: region.aContent,
42437                     aIndex: region.aStart,
42438                     o: region.oContent,
42439                     oIndex: region.oStart,
42440                     b: region.bContent,
42441                     bIndex: region.bStart
42442                   }
42443                 });
42444               }
42445             }
42446           });
42447           flushOk();
42448           return results;
42449         }
42450
42451         var lodash = {exports: {}};
42452
42453         (function (module, exports) {
42454           (function () {
42455             /** Used as a safe reference for `undefined` in pre-ES5 environments. */
42456             var undefined$1;
42457             /** Used as the semantic version number. */
42458
42459             var VERSION = '4.17.21';
42460             /** Used as the size to enable large array optimizations. */
42461
42462             var LARGE_ARRAY_SIZE = 200;
42463             /** Error message constants. */
42464
42465             var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',
42466                 FUNC_ERROR_TEXT = 'Expected a function',
42467                 INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`';
42468             /** Used to stand-in for `undefined` hash values. */
42469
42470             var HASH_UNDEFINED = '__lodash_hash_undefined__';
42471             /** Used as the maximum memoize cache size. */
42472
42473             var MAX_MEMOIZE_SIZE = 500;
42474             /** Used as the internal argument placeholder. */
42475
42476             var PLACEHOLDER = '__lodash_placeholder__';
42477             /** Used to compose bitmasks for cloning. */
42478
42479             var CLONE_DEEP_FLAG = 1,
42480                 CLONE_FLAT_FLAG = 2,
42481                 CLONE_SYMBOLS_FLAG = 4;
42482             /** Used to compose bitmasks for value comparisons. */
42483
42484             var COMPARE_PARTIAL_FLAG = 1,
42485                 COMPARE_UNORDERED_FLAG = 2;
42486             /** Used to compose bitmasks for function metadata. */
42487
42488             var WRAP_BIND_FLAG = 1,
42489                 WRAP_BIND_KEY_FLAG = 2,
42490                 WRAP_CURRY_BOUND_FLAG = 4,
42491                 WRAP_CURRY_FLAG = 8,
42492                 WRAP_CURRY_RIGHT_FLAG = 16,
42493                 WRAP_PARTIAL_FLAG = 32,
42494                 WRAP_PARTIAL_RIGHT_FLAG = 64,
42495                 WRAP_ARY_FLAG = 128,
42496                 WRAP_REARG_FLAG = 256,
42497                 WRAP_FLIP_FLAG = 512;
42498             /** Used as default options for `_.truncate`. */
42499
42500             var DEFAULT_TRUNC_LENGTH = 30,
42501                 DEFAULT_TRUNC_OMISSION = '...';
42502             /** Used to detect hot functions by number of calls within a span of milliseconds. */
42503
42504             var HOT_COUNT = 800,
42505                 HOT_SPAN = 16;
42506             /** Used to indicate the type of lazy iteratees. */
42507
42508             var LAZY_FILTER_FLAG = 1,
42509                 LAZY_MAP_FLAG = 2,
42510                 LAZY_WHILE_FLAG = 3;
42511             /** Used as references for various `Number` constants. */
42512
42513             var INFINITY = 1 / 0,
42514                 MAX_SAFE_INTEGER = 9007199254740991,
42515                 MAX_INTEGER = 1.7976931348623157e+308,
42516                 NAN = 0 / 0;
42517             /** Used as references for the maximum length and index of an array. */
42518
42519             var MAX_ARRAY_LENGTH = 4294967295,
42520                 MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
42521                 HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
42522             /** Used to associate wrap methods with their bit flags. */
42523
42524             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]];
42525             /** `Object#toString` result references. */
42526
42527             var argsTag = '[object Arguments]',
42528                 arrayTag = '[object Array]',
42529                 asyncTag = '[object AsyncFunction]',
42530                 boolTag = '[object Boolean]',
42531                 dateTag = '[object Date]',
42532                 domExcTag = '[object DOMException]',
42533                 errorTag = '[object Error]',
42534                 funcTag = '[object Function]',
42535                 genTag = '[object GeneratorFunction]',
42536                 mapTag = '[object Map]',
42537                 numberTag = '[object Number]',
42538                 nullTag = '[object Null]',
42539                 objectTag = '[object Object]',
42540                 promiseTag = '[object Promise]',
42541                 proxyTag = '[object Proxy]',
42542                 regexpTag = '[object RegExp]',
42543                 setTag = '[object Set]',
42544                 stringTag = '[object String]',
42545                 symbolTag = '[object Symbol]',
42546                 undefinedTag = '[object Undefined]',
42547                 weakMapTag = '[object WeakMap]',
42548                 weakSetTag = '[object WeakSet]';
42549             var arrayBufferTag = '[object ArrayBuffer]',
42550                 dataViewTag = '[object DataView]',
42551                 float32Tag = '[object Float32Array]',
42552                 float64Tag = '[object Float64Array]',
42553                 int8Tag = '[object Int8Array]',
42554                 int16Tag = '[object Int16Array]',
42555                 int32Tag = '[object Int32Array]',
42556                 uint8Tag = '[object Uint8Array]',
42557                 uint8ClampedTag = '[object Uint8ClampedArray]',
42558                 uint16Tag = '[object Uint16Array]',
42559                 uint32Tag = '[object Uint32Array]';
42560             /** Used to match empty string literals in compiled template source. */
42561
42562             var reEmptyStringLeading = /\b__p \+= '';/g,
42563                 reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
42564                 reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
42565             /** Used to match HTML entities and HTML characters. */
42566
42567             var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g,
42568                 reUnescapedHtml = /[&<>"']/g,
42569                 reHasEscapedHtml = RegExp(reEscapedHtml.source),
42570                 reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
42571             /** Used to match template delimiters. */
42572
42573             var reEscape = /<%-([\s\S]+?)%>/g,
42574                 reEvaluate = /<%([\s\S]+?)%>/g,
42575                 reInterpolate = /<%=([\s\S]+?)%>/g;
42576             /** Used to match property names within property paths. */
42577
42578             var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
42579                 reIsPlainProp = /^\w*$/,
42580                 rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
42581             /**
42582              * Used to match `RegExp`
42583              * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
42584              */
42585
42586             var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
42587                 reHasRegExpChar = RegExp(reRegExpChar.source);
42588             /** Used to match leading whitespace. */
42589
42590             var reTrimStart = /^\s+/;
42591             /** Used to match a single whitespace character. */
42592
42593             var reWhitespace = /\s/;
42594             /** Used to match wrap detail comments. */
42595
42596             var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,
42597                 reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/,
42598                 reSplitDetails = /,? & /;
42599             /** Used to match words composed of alphanumeric characters. */
42600
42601             var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
42602             /**
42603              * Used to validate the `validate` option in `_.template` variable.
42604              *
42605              * Forbids characters which could potentially change the meaning of the function argument definition:
42606              * - "()," (modification of function parameters)
42607              * - "=" (default value)
42608              * - "[]{}" (destructuring of function parameters)
42609              * - "/" (beginning of a comment)
42610              * - whitespace
42611              */
42612
42613             var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/;
42614             /** Used to match backslashes in property paths. */
42615
42616             var reEscapeChar = /\\(\\)?/g;
42617             /**
42618              * Used to match
42619              * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components).
42620              */
42621
42622             var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
42623             /** Used to match `RegExp` flags from their coerced string values. */
42624
42625             var reFlags = /\w*$/;
42626             /** Used to detect bad signed hexadecimal string values. */
42627
42628             var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
42629             /** Used to detect binary string values. */
42630
42631             var reIsBinary = /^0b[01]+$/i;
42632             /** Used to detect host constructors (Safari). */
42633
42634             var reIsHostCtor = /^\[object .+?Constructor\]$/;
42635             /** Used to detect octal string values. */
42636
42637             var reIsOctal = /^0o[0-7]+$/i;
42638             /** Used to detect unsigned integer values. */
42639
42640             var reIsUint = /^(?:0|[1-9]\d*)$/;
42641             /** Used to match Latin Unicode letters (excluding mathematical operators). */
42642
42643             var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
42644             /** Used to ensure capturing order of template delimiters. */
42645
42646             var reNoMatch = /($^)/;
42647             /** Used to match unescaped characters in compiled string literals. */
42648
42649             var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
42650             /** Used to compose unicode character classes. */
42651
42652             var rsAstralRange = "\\ud800-\\udfff",
42653                 rsComboMarksRange = "\\u0300-\\u036f",
42654                 reComboHalfMarksRange = "\\ufe20-\\ufe2f",
42655                 rsComboSymbolsRange = "\\u20d0-\\u20ff",
42656                 rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
42657                 rsDingbatRange = "\\u2700-\\u27bf",
42658                 rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff',
42659                 rsMathOpRange = '\\xac\\xb1\\xd7\\xf7',
42660                 rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf',
42661                 rsPunctuationRange = "\\u2000-\\u206f",
42662                 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",
42663                 rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde',
42664                 rsVarRange = "\\ufe0e\\ufe0f",
42665                 rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;
42666             /** Used to compose unicode capture groups. */
42667
42668             var rsApos = "['\u2019]",
42669                 rsAstral = '[' + rsAstralRange + ']',
42670                 rsBreak = '[' + rsBreakRange + ']',
42671                 rsCombo = '[' + rsComboRange + ']',
42672                 rsDigits = '\\d+',
42673                 rsDingbat = '[' + rsDingbatRange + ']',
42674                 rsLower = '[' + rsLowerRange + ']',
42675                 rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',
42676                 rsFitz = "\\ud83c[\\udffb-\\udfff]",
42677                 rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
42678                 rsNonAstral = '[^' + rsAstralRange + ']',
42679                 rsRegional = "(?:\\ud83c[\\udde6-\\uddff]){2}",
42680                 rsSurrPair = "[\\ud800-\\udbff][\\udc00-\\udfff]",
42681                 rsUpper = '[' + rsUpperRange + ']',
42682                 rsZWJ = "\\u200d";
42683             /** Used to compose unicode regexes. */
42684
42685             var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')',
42686                 rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')',
42687                 rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',
42688                 rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',
42689                 reOptMod = rsModifier + '?',
42690                 rsOptVar = '[' + rsVarRange + ']?',
42691                 rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
42692                 rsOrdLower = '\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])',
42693                 rsOrdUpper = '\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])',
42694                 rsSeq = rsOptVar + reOptMod + rsOptJoin,
42695                 rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq,
42696                 rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
42697             /** Used to match apostrophes. */
42698
42699             var reApos = RegExp(rsApos, 'g');
42700             /**
42701              * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and
42702              * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).
42703              */
42704
42705             var reComboMark = RegExp(rsCombo, 'g');
42706             /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
42707
42708             var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
42709             /** Used to match complex or compound words. */
42710
42711             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');
42712             /** 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/). */
42713
42714             var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');
42715             /** Used to detect strings that need a more robust regexp to match words. */
42716
42717             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 ]/;
42718             /** Used to assign default `context` object properties. */
42719
42720             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'];
42721             /** Used to make template sourceURLs easier to identify. */
42722
42723             var templateCounter = -1;
42724             /** Used to identify `toStringTag` values of typed arrays. */
42725
42726             var typedArrayTags = {};
42727             typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true;
42728             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;
42729             /** Used to identify `toStringTag` values supported by `_.clone`. */
42730
42731             var cloneableTags = {};
42732             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;
42733             cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[weakMapTag] = false;
42734             /** Used to map Latin Unicode letters to basic Latin letters. */
42735
42736             var deburredLetters = {
42737               // Latin-1 Supplement block.
42738               '\xc0': 'A',
42739               '\xc1': 'A',
42740               '\xc2': 'A',
42741               '\xc3': 'A',
42742               '\xc4': 'A',
42743               '\xc5': 'A',
42744               '\xe0': 'a',
42745               '\xe1': 'a',
42746               '\xe2': 'a',
42747               '\xe3': 'a',
42748               '\xe4': 'a',
42749               '\xe5': 'a',
42750               '\xc7': 'C',
42751               '\xe7': 'c',
42752               '\xd0': 'D',
42753               '\xf0': 'd',
42754               '\xc8': 'E',
42755               '\xc9': 'E',
42756               '\xca': 'E',
42757               '\xcb': 'E',
42758               '\xe8': 'e',
42759               '\xe9': 'e',
42760               '\xea': 'e',
42761               '\xeb': 'e',
42762               '\xcc': 'I',
42763               '\xcd': 'I',
42764               '\xce': 'I',
42765               '\xcf': 'I',
42766               '\xec': 'i',
42767               '\xed': 'i',
42768               '\xee': 'i',
42769               '\xef': 'i',
42770               '\xd1': 'N',
42771               '\xf1': 'n',
42772               '\xd2': 'O',
42773               '\xd3': 'O',
42774               '\xd4': 'O',
42775               '\xd5': 'O',
42776               '\xd6': 'O',
42777               '\xd8': 'O',
42778               '\xf2': 'o',
42779               '\xf3': 'o',
42780               '\xf4': 'o',
42781               '\xf5': 'o',
42782               '\xf6': 'o',
42783               '\xf8': 'o',
42784               '\xd9': 'U',
42785               '\xda': 'U',
42786               '\xdb': 'U',
42787               '\xdc': 'U',
42788               '\xf9': 'u',
42789               '\xfa': 'u',
42790               '\xfb': 'u',
42791               '\xfc': 'u',
42792               '\xdd': 'Y',
42793               '\xfd': 'y',
42794               '\xff': 'y',
42795               '\xc6': 'Ae',
42796               '\xe6': 'ae',
42797               '\xde': 'Th',
42798               '\xfe': 'th',
42799               '\xdf': 'ss',
42800               // Latin Extended-A block.
42801               "\u0100": 'A',
42802               "\u0102": 'A',
42803               "\u0104": 'A',
42804               "\u0101": 'a',
42805               "\u0103": 'a',
42806               "\u0105": 'a',
42807               "\u0106": 'C',
42808               "\u0108": 'C',
42809               "\u010A": 'C',
42810               "\u010C": 'C',
42811               "\u0107": 'c',
42812               "\u0109": 'c',
42813               "\u010B": 'c',
42814               "\u010D": 'c',
42815               "\u010E": 'D',
42816               "\u0110": 'D',
42817               "\u010F": 'd',
42818               "\u0111": 'd',
42819               "\u0112": 'E',
42820               "\u0114": 'E',
42821               "\u0116": 'E',
42822               "\u0118": 'E',
42823               "\u011A": 'E',
42824               "\u0113": 'e',
42825               "\u0115": 'e',
42826               "\u0117": 'e',
42827               "\u0119": 'e',
42828               "\u011B": 'e',
42829               "\u011C": 'G',
42830               "\u011E": 'G',
42831               "\u0120": 'G',
42832               "\u0122": 'G',
42833               "\u011D": 'g',
42834               "\u011F": 'g',
42835               "\u0121": 'g',
42836               "\u0123": 'g',
42837               "\u0124": 'H',
42838               "\u0126": 'H',
42839               "\u0125": 'h',
42840               "\u0127": 'h',
42841               "\u0128": 'I',
42842               "\u012A": 'I',
42843               "\u012C": 'I',
42844               "\u012E": 'I',
42845               "\u0130": 'I',
42846               "\u0129": 'i',
42847               "\u012B": 'i',
42848               "\u012D": 'i',
42849               "\u012F": 'i',
42850               "\u0131": 'i',
42851               "\u0134": 'J',
42852               "\u0135": 'j',
42853               "\u0136": 'K',
42854               "\u0137": 'k',
42855               "\u0138": 'k',
42856               "\u0139": 'L',
42857               "\u013B": 'L',
42858               "\u013D": 'L',
42859               "\u013F": 'L',
42860               "\u0141": 'L',
42861               "\u013A": 'l',
42862               "\u013C": 'l',
42863               "\u013E": 'l',
42864               "\u0140": 'l',
42865               "\u0142": 'l',
42866               "\u0143": 'N',
42867               "\u0145": 'N',
42868               "\u0147": 'N',
42869               "\u014A": 'N',
42870               "\u0144": 'n',
42871               "\u0146": 'n',
42872               "\u0148": 'n',
42873               "\u014B": 'n',
42874               "\u014C": 'O',
42875               "\u014E": 'O',
42876               "\u0150": 'O',
42877               "\u014D": 'o',
42878               "\u014F": 'o',
42879               "\u0151": 'o',
42880               "\u0154": 'R',
42881               "\u0156": 'R',
42882               "\u0158": 'R',
42883               "\u0155": 'r',
42884               "\u0157": 'r',
42885               "\u0159": 'r',
42886               "\u015A": 'S',
42887               "\u015C": 'S',
42888               "\u015E": 'S',
42889               "\u0160": 'S',
42890               "\u015B": 's',
42891               "\u015D": 's',
42892               "\u015F": 's',
42893               "\u0161": 's',
42894               "\u0162": 'T',
42895               "\u0164": 'T',
42896               "\u0166": 'T',
42897               "\u0163": 't',
42898               "\u0165": 't',
42899               "\u0167": 't',
42900               "\u0168": 'U',
42901               "\u016A": 'U',
42902               "\u016C": 'U',
42903               "\u016E": 'U',
42904               "\u0170": 'U',
42905               "\u0172": 'U',
42906               "\u0169": 'u',
42907               "\u016B": 'u',
42908               "\u016D": 'u',
42909               "\u016F": 'u',
42910               "\u0171": 'u',
42911               "\u0173": 'u',
42912               "\u0174": 'W',
42913               "\u0175": 'w',
42914               "\u0176": 'Y',
42915               "\u0177": 'y',
42916               "\u0178": 'Y',
42917               "\u0179": 'Z',
42918               "\u017B": 'Z',
42919               "\u017D": 'Z',
42920               "\u017A": 'z',
42921               "\u017C": 'z',
42922               "\u017E": 'z',
42923               "\u0132": 'IJ',
42924               "\u0133": 'ij',
42925               "\u0152": 'Oe',
42926               "\u0153": 'oe',
42927               "\u0149": "'n",
42928               "\u017F": 's'
42929             };
42930             /** Used to map characters to HTML entities. */
42931
42932             var htmlEscapes = {
42933               '&': '&amp;',
42934               '<': '&lt;',
42935               '>': '&gt;',
42936               '"': '&quot;',
42937               "'": '&#39;'
42938             };
42939             /** Used to map HTML entities to characters. */
42940
42941             var htmlUnescapes = {
42942               '&amp;': '&',
42943               '&lt;': '<',
42944               '&gt;': '>',
42945               '&quot;': '"',
42946               '&#39;': "'"
42947             };
42948             /** Used to escape characters for inclusion in compiled string literals. */
42949
42950             var stringEscapes = {
42951               '\\': '\\',
42952               "'": "'",
42953               '\n': 'n',
42954               '\r': 'r',
42955               "\u2028": 'u2028',
42956               "\u2029": 'u2029'
42957             };
42958             /** Built-in method references without a dependency on `root`. */
42959
42960             var freeParseFloat = parseFloat,
42961                 freeParseInt = parseInt;
42962             /** Detect free variable `global` from Node.js. */
42963
42964             var freeGlobal = _typeof(commonjsGlobal) == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
42965             /** Detect free variable `self`. */
42966
42967             var freeSelf = (typeof self === "undefined" ? "undefined" : _typeof(self)) == 'object' && self && self.Object === Object && self;
42968             /** Used as a reference to the global object. */
42969
42970             var root = freeGlobal || freeSelf || Function('return this')();
42971             /** Detect free variable `exports`. */
42972
42973             var freeExports = exports && !exports.nodeType && exports;
42974             /** Detect free variable `module`. */
42975
42976             var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module;
42977             /** Detect the popular CommonJS extension `module.exports`. */
42978
42979             var moduleExports = freeModule && freeModule.exports === freeExports;
42980             /** Detect free variable `process` from Node.js. */
42981
42982             var freeProcess = moduleExports && freeGlobal.process;
42983             /** Used to access faster Node.js helpers. */
42984
42985             var nodeUtil = function () {
42986               try {
42987                 // Use `util.types` for Node.js 10+.
42988                 var types = freeModule && freeModule.require && freeModule.require('util').types;
42989
42990                 if (types) {
42991                   return types;
42992                 } // Legacy `process.binding('util')` for Node.js < 10.
42993
42994
42995                 return freeProcess && freeProcess.binding && freeProcess.binding('util');
42996               } catch (e) {}
42997             }();
42998             /* Node.js helper references. */
42999
43000
43001             var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer,
43002                 nodeIsDate = nodeUtil && nodeUtil.isDate,
43003                 nodeIsMap = nodeUtil && nodeUtil.isMap,
43004                 nodeIsRegExp = nodeUtil && nodeUtil.isRegExp,
43005                 nodeIsSet = nodeUtil && nodeUtil.isSet,
43006                 nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
43007             /*--------------------------------------------------------------------------*/
43008
43009             /**
43010              * A faster alternative to `Function#apply`, this function invokes `func`
43011              * with the `this` binding of `thisArg` and the arguments of `args`.
43012              *
43013              * @private
43014              * @param {Function} func The function to invoke.
43015              * @param {*} thisArg The `this` binding of `func`.
43016              * @param {Array} args The arguments to invoke `func` with.
43017              * @returns {*} Returns the result of `func`.
43018              */
43019
43020             function apply(func, thisArg, args) {
43021               switch (args.length) {
43022                 case 0:
43023                   return func.call(thisArg);
43024
43025                 case 1:
43026                   return func.call(thisArg, args[0]);
43027
43028                 case 2:
43029                   return func.call(thisArg, args[0], args[1]);
43030
43031                 case 3:
43032                   return func.call(thisArg, args[0], args[1], args[2]);
43033               }
43034
43035               return func.apply(thisArg, args);
43036             }
43037             /**
43038              * A specialized version of `baseAggregator` for arrays.
43039              *
43040              * @private
43041              * @param {Array} [array] The array to iterate over.
43042              * @param {Function} setter The function to set `accumulator` values.
43043              * @param {Function} iteratee The iteratee to transform keys.
43044              * @param {Object} accumulator The initial aggregated object.
43045              * @returns {Function} Returns `accumulator`.
43046              */
43047
43048
43049             function arrayAggregator(array, setter, iteratee, accumulator) {
43050               var index = -1,
43051                   length = array == null ? 0 : array.length;
43052
43053               while (++index < length) {
43054                 var value = array[index];
43055                 setter(accumulator, value, iteratee(value), array);
43056               }
43057
43058               return accumulator;
43059             }
43060             /**
43061              * A specialized version of `_.forEach` for arrays without support for
43062              * iteratee shorthands.
43063              *
43064              * @private
43065              * @param {Array} [array] The array to iterate over.
43066              * @param {Function} iteratee The function invoked per iteration.
43067              * @returns {Array} Returns `array`.
43068              */
43069
43070
43071             function arrayEach(array, iteratee) {
43072               var index = -1,
43073                   length = array == null ? 0 : array.length;
43074
43075               while (++index < length) {
43076                 if (iteratee(array[index], index, array) === false) {
43077                   break;
43078                 }
43079               }
43080
43081               return array;
43082             }
43083             /**
43084              * A specialized version of `_.forEachRight` for arrays without support for
43085              * iteratee shorthands.
43086              *
43087              * @private
43088              * @param {Array} [array] The array to iterate over.
43089              * @param {Function} iteratee The function invoked per iteration.
43090              * @returns {Array} Returns `array`.
43091              */
43092
43093
43094             function arrayEachRight(array, iteratee) {
43095               var length = array == null ? 0 : array.length;
43096
43097               while (length--) {
43098                 if (iteratee(array[length], length, array) === false) {
43099                   break;
43100                 }
43101               }
43102
43103               return array;
43104             }
43105             /**
43106              * A specialized version of `_.every` for arrays without support for
43107              * iteratee shorthands.
43108              *
43109              * @private
43110              * @param {Array} [array] The array to iterate over.
43111              * @param {Function} predicate The function invoked per iteration.
43112              * @returns {boolean} Returns `true` if all elements pass the predicate check,
43113              *  else `false`.
43114              */
43115
43116
43117             function arrayEvery(array, predicate) {
43118               var index = -1,
43119                   length = array == null ? 0 : array.length;
43120
43121               while (++index < length) {
43122                 if (!predicate(array[index], index, array)) {
43123                   return false;
43124                 }
43125               }
43126
43127               return true;
43128             }
43129             /**
43130              * A specialized version of `_.filter` for arrays without support for
43131              * iteratee shorthands.
43132              *
43133              * @private
43134              * @param {Array} [array] The array to iterate over.
43135              * @param {Function} predicate The function invoked per iteration.
43136              * @returns {Array} Returns the new filtered array.
43137              */
43138
43139
43140             function arrayFilter(array, predicate) {
43141               var index = -1,
43142                   length = array == null ? 0 : array.length,
43143                   resIndex = 0,
43144                   result = [];
43145
43146               while (++index < length) {
43147                 var value = array[index];
43148
43149                 if (predicate(value, index, array)) {
43150                   result[resIndex++] = value;
43151                 }
43152               }
43153
43154               return result;
43155             }
43156             /**
43157              * A specialized version of `_.includes` for arrays without support for
43158              * specifying an index to search from.
43159              *
43160              * @private
43161              * @param {Array} [array] The array to inspect.
43162              * @param {*} target The value to search for.
43163              * @returns {boolean} Returns `true` if `target` is found, else `false`.
43164              */
43165
43166
43167             function arrayIncludes(array, value) {
43168               var length = array == null ? 0 : array.length;
43169               return !!length && baseIndexOf(array, value, 0) > -1;
43170             }
43171             /**
43172              * This function is like `arrayIncludes` except that it accepts a comparator.
43173              *
43174              * @private
43175              * @param {Array} [array] The array to inspect.
43176              * @param {*} target The value to search for.
43177              * @param {Function} comparator The comparator invoked per element.
43178              * @returns {boolean} Returns `true` if `target` is found, else `false`.
43179              */
43180
43181
43182             function arrayIncludesWith(array, value, comparator) {
43183               var index = -1,
43184                   length = array == null ? 0 : array.length;
43185
43186               while (++index < length) {
43187                 if (comparator(value, array[index])) {
43188                   return true;
43189                 }
43190               }
43191
43192               return false;
43193             }
43194             /**
43195              * A specialized version of `_.map` for arrays without support for iteratee
43196              * shorthands.
43197              *
43198              * @private
43199              * @param {Array} [array] The array to iterate over.
43200              * @param {Function} iteratee The function invoked per iteration.
43201              * @returns {Array} Returns the new mapped array.
43202              */
43203
43204
43205             function arrayMap(array, iteratee) {
43206               var index = -1,
43207                   length = array == null ? 0 : array.length,
43208                   result = Array(length);
43209
43210               while (++index < length) {
43211                 result[index] = iteratee(array[index], index, array);
43212               }
43213
43214               return result;
43215             }
43216             /**
43217              * Appends the elements of `values` to `array`.
43218              *
43219              * @private
43220              * @param {Array} array The array to modify.
43221              * @param {Array} values The values to append.
43222              * @returns {Array} Returns `array`.
43223              */
43224
43225
43226             function arrayPush(array, values) {
43227               var index = -1,
43228                   length = values.length,
43229                   offset = array.length;
43230
43231               while (++index < length) {
43232                 array[offset + index] = values[index];
43233               }
43234
43235               return array;
43236             }
43237             /**
43238              * A specialized version of `_.reduce` for arrays without support for
43239              * iteratee shorthands.
43240              *
43241              * @private
43242              * @param {Array} [array] The array to iterate over.
43243              * @param {Function} iteratee The function invoked per iteration.
43244              * @param {*} [accumulator] The initial value.
43245              * @param {boolean} [initAccum] Specify using the first element of `array` as
43246              *  the initial value.
43247              * @returns {*} Returns the accumulated value.
43248              */
43249
43250
43251             function arrayReduce(array, iteratee, accumulator, initAccum) {
43252               var index = -1,
43253                   length = array == null ? 0 : array.length;
43254
43255               if (initAccum && length) {
43256                 accumulator = array[++index];
43257               }
43258
43259               while (++index < length) {
43260                 accumulator = iteratee(accumulator, array[index], index, array);
43261               }
43262
43263               return accumulator;
43264             }
43265             /**
43266              * A specialized version of `_.reduceRight` for arrays without support for
43267              * iteratee shorthands.
43268              *
43269              * @private
43270              * @param {Array} [array] The array to iterate over.
43271              * @param {Function} iteratee The function invoked per iteration.
43272              * @param {*} [accumulator] The initial value.
43273              * @param {boolean} [initAccum] Specify using the last element of `array` as
43274              *  the initial value.
43275              * @returns {*} Returns the accumulated value.
43276              */
43277
43278
43279             function arrayReduceRight(array, iteratee, accumulator, initAccum) {
43280               var length = array == null ? 0 : array.length;
43281
43282               if (initAccum && length) {
43283                 accumulator = array[--length];
43284               }
43285
43286               while (length--) {
43287                 accumulator = iteratee(accumulator, array[length], length, array);
43288               }
43289
43290               return accumulator;
43291             }
43292             /**
43293              * A specialized version of `_.some` for arrays without support for iteratee
43294              * shorthands.
43295              *
43296              * @private
43297              * @param {Array} [array] The array to iterate over.
43298              * @param {Function} predicate The function invoked per iteration.
43299              * @returns {boolean} Returns `true` if any element passes the predicate check,
43300              *  else `false`.
43301              */
43302
43303
43304             function arraySome(array, predicate) {
43305               var index = -1,
43306                   length = array == null ? 0 : array.length;
43307
43308               while (++index < length) {
43309                 if (predicate(array[index], index, array)) {
43310                   return true;
43311                 }
43312               }
43313
43314               return false;
43315             }
43316             /**
43317              * Gets the size of an ASCII `string`.
43318              *
43319              * @private
43320              * @param {string} string The string inspect.
43321              * @returns {number} Returns the string size.
43322              */
43323
43324
43325             var asciiSize = baseProperty('length');
43326             /**
43327              * Converts an ASCII `string` to an array.
43328              *
43329              * @private
43330              * @param {string} string The string to convert.
43331              * @returns {Array} Returns the converted array.
43332              */
43333
43334             function asciiToArray(string) {
43335               return string.split('');
43336             }
43337             /**
43338              * Splits an ASCII `string` into an array of its words.
43339              *
43340              * @private
43341              * @param {string} The string to inspect.
43342              * @returns {Array} Returns the words of `string`.
43343              */
43344
43345
43346             function asciiWords(string) {
43347               return string.match(reAsciiWord) || [];
43348             }
43349             /**
43350              * The base implementation of methods like `_.findKey` and `_.findLastKey`,
43351              * without support for iteratee shorthands, which iterates over `collection`
43352              * using `eachFunc`.
43353              *
43354              * @private
43355              * @param {Array|Object} collection The collection to inspect.
43356              * @param {Function} predicate The function invoked per iteration.
43357              * @param {Function} eachFunc The function to iterate over `collection`.
43358              * @returns {*} Returns the found element or its key, else `undefined`.
43359              */
43360
43361
43362             function baseFindKey(collection, predicate, eachFunc) {
43363               var result;
43364               eachFunc(collection, function (value, key, collection) {
43365                 if (predicate(value, key, collection)) {
43366                   result = key;
43367                   return false;
43368                 }
43369               });
43370               return result;
43371             }
43372             /**
43373              * The base implementation of `_.findIndex` and `_.findLastIndex` without
43374              * support for iteratee shorthands.
43375              *
43376              * @private
43377              * @param {Array} array The array to inspect.
43378              * @param {Function} predicate The function invoked per iteration.
43379              * @param {number} fromIndex The index to search from.
43380              * @param {boolean} [fromRight] Specify iterating from right to left.
43381              * @returns {number} Returns the index of the matched value, else `-1`.
43382              */
43383
43384
43385             function baseFindIndex(array, predicate, fromIndex, fromRight) {
43386               var length = array.length,
43387                   index = fromIndex + (fromRight ? 1 : -1);
43388
43389               while (fromRight ? index-- : ++index < length) {
43390                 if (predicate(array[index], index, array)) {
43391                   return index;
43392                 }
43393               }
43394
43395               return -1;
43396             }
43397             /**
43398              * The base implementation of `_.indexOf` without `fromIndex` bounds checks.
43399              *
43400              * @private
43401              * @param {Array} array The array to inspect.
43402              * @param {*} value The value to search for.
43403              * @param {number} fromIndex The index to search from.
43404              * @returns {number} Returns the index of the matched value, else `-1`.
43405              */
43406
43407
43408             function baseIndexOf(array, value, fromIndex) {
43409               return value === value ? strictIndexOf(array, value, fromIndex) : baseFindIndex(array, baseIsNaN, fromIndex);
43410             }
43411             /**
43412              * This function is like `baseIndexOf` except that it accepts a comparator.
43413              *
43414              * @private
43415              * @param {Array} array The array to inspect.
43416              * @param {*} value The value to search for.
43417              * @param {number} fromIndex The index to search from.
43418              * @param {Function} comparator The comparator invoked per element.
43419              * @returns {number} Returns the index of the matched value, else `-1`.
43420              */
43421
43422
43423             function baseIndexOfWith(array, value, fromIndex, comparator) {
43424               var index = fromIndex - 1,
43425                   length = array.length;
43426
43427               while (++index < length) {
43428                 if (comparator(array[index], value)) {
43429                   return index;
43430                 }
43431               }
43432
43433               return -1;
43434             }
43435             /**
43436              * The base implementation of `_.isNaN` without support for number objects.
43437              *
43438              * @private
43439              * @param {*} value The value to check.
43440              * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
43441              */
43442
43443
43444             function baseIsNaN(value) {
43445               return value !== value;
43446             }
43447             /**
43448              * The base implementation of `_.mean` and `_.meanBy` without support for
43449              * iteratee shorthands.
43450              *
43451              * @private
43452              * @param {Array} array The array to iterate over.
43453              * @param {Function} iteratee The function invoked per iteration.
43454              * @returns {number} Returns the mean.
43455              */
43456
43457
43458             function baseMean(array, iteratee) {
43459               var length = array == null ? 0 : array.length;
43460               return length ? baseSum(array, iteratee) / length : NAN;
43461             }
43462             /**
43463              * The base implementation of `_.property` without support for deep paths.
43464              *
43465              * @private
43466              * @param {string} key The key of the property to get.
43467              * @returns {Function} Returns the new accessor function.
43468              */
43469
43470
43471             function baseProperty(key) {
43472               return function (object) {
43473                 return object == null ? undefined$1 : object[key];
43474               };
43475             }
43476             /**
43477              * The base implementation of `_.propertyOf` without support for deep paths.
43478              *
43479              * @private
43480              * @param {Object} object The object to query.
43481              * @returns {Function} Returns the new accessor function.
43482              */
43483
43484
43485             function basePropertyOf(object) {
43486               return function (key) {
43487                 return object == null ? undefined$1 : object[key];
43488               };
43489             }
43490             /**
43491              * The base implementation of `_.reduce` and `_.reduceRight`, without support
43492              * for iteratee shorthands, which iterates over `collection` using `eachFunc`.
43493              *
43494              * @private
43495              * @param {Array|Object} collection The collection to iterate over.
43496              * @param {Function} iteratee The function invoked per iteration.
43497              * @param {*} accumulator The initial value.
43498              * @param {boolean} initAccum Specify using the first or last element of
43499              *  `collection` as the initial value.
43500              * @param {Function} eachFunc The function to iterate over `collection`.
43501              * @returns {*} Returns the accumulated value.
43502              */
43503
43504
43505             function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
43506               eachFunc(collection, function (value, index, collection) {
43507                 accumulator = initAccum ? (initAccum = false, value) : iteratee(accumulator, value, index, collection);
43508               });
43509               return accumulator;
43510             }
43511             /**
43512              * The base implementation of `_.sortBy` which uses `comparer` to define the
43513              * sort order of `array` and replaces criteria objects with their corresponding
43514              * values.
43515              *
43516              * @private
43517              * @param {Array} array The array to sort.
43518              * @param {Function} comparer The function to define sort order.
43519              * @returns {Array} Returns `array`.
43520              */
43521
43522
43523             function baseSortBy(array, comparer) {
43524               var length = array.length;
43525               array.sort(comparer);
43526
43527               while (length--) {
43528                 array[length] = array[length].value;
43529               }
43530
43531               return array;
43532             }
43533             /**
43534              * The base implementation of `_.sum` and `_.sumBy` without support for
43535              * iteratee shorthands.
43536              *
43537              * @private
43538              * @param {Array} array The array to iterate over.
43539              * @param {Function} iteratee The function invoked per iteration.
43540              * @returns {number} Returns the sum.
43541              */
43542
43543
43544             function baseSum(array, iteratee) {
43545               var result,
43546                   index = -1,
43547                   length = array.length;
43548
43549               while (++index < length) {
43550                 var current = iteratee(array[index]);
43551
43552                 if (current !== undefined$1) {
43553                   result = result === undefined$1 ? current : result + current;
43554                 }
43555               }
43556
43557               return result;
43558             }
43559             /**
43560              * The base implementation of `_.times` without support for iteratee shorthands
43561              * or max array length checks.
43562              *
43563              * @private
43564              * @param {number} n The number of times to invoke `iteratee`.
43565              * @param {Function} iteratee The function invoked per iteration.
43566              * @returns {Array} Returns the array of results.
43567              */
43568
43569
43570             function baseTimes(n, iteratee) {
43571               var index = -1,
43572                   result = Array(n);
43573
43574               while (++index < n) {
43575                 result[index] = iteratee(index);
43576               }
43577
43578               return result;
43579             }
43580             /**
43581              * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array
43582              * of key-value pairs for `object` corresponding to the property names of `props`.
43583              *
43584              * @private
43585              * @param {Object} object The object to query.
43586              * @param {Array} props The property names to get values for.
43587              * @returns {Object} Returns the key-value pairs.
43588              */
43589
43590
43591             function baseToPairs(object, props) {
43592               return arrayMap(props, function (key) {
43593                 return [key, object[key]];
43594               });
43595             }
43596             /**
43597              * The base implementation of `_.trim`.
43598              *
43599              * @private
43600              * @param {string} string The string to trim.
43601              * @returns {string} Returns the trimmed string.
43602              */
43603
43604
43605             function baseTrim(string) {
43606               return string ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') : string;
43607             }
43608             /**
43609              * The base implementation of `_.unary` without support for storing metadata.
43610              *
43611              * @private
43612              * @param {Function} func The function to cap arguments for.
43613              * @returns {Function} Returns the new capped function.
43614              */
43615
43616
43617             function baseUnary(func) {
43618               return function (value) {
43619                 return func(value);
43620               };
43621             }
43622             /**
43623              * The base implementation of `_.values` and `_.valuesIn` which creates an
43624              * array of `object` property values corresponding to the property names
43625              * of `props`.
43626              *
43627              * @private
43628              * @param {Object} object The object to query.
43629              * @param {Array} props The property names to get values for.
43630              * @returns {Object} Returns the array of property values.
43631              */
43632
43633
43634             function baseValues(object, props) {
43635               return arrayMap(props, function (key) {
43636                 return object[key];
43637               });
43638             }
43639             /**
43640              * Checks if a `cache` value for `key` exists.
43641              *
43642              * @private
43643              * @param {Object} cache The cache to query.
43644              * @param {string} key The key of the entry to check.
43645              * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
43646              */
43647
43648
43649             function cacheHas(cache, key) {
43650               return cache.has(key);
43651             }
43652             /**
43653              * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol
43654              * that is not found in the character symbols.
43655              *
43656              * @private
43657              * @param {Array} strSymbols The string symbols to inspect.
43658              * @param {Array} chrSymbols The character symbols to find.
43659              * @returns {number} Returns the index of the first unmatched string symbol.
43660              */
43661
43662
43663             function charsStartIndex(strSymbols, chrSymbols) {
43664               var index = -1,
43665                   length = strSymbols.length;
43666
43667               while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
43668
43669               return index;
43670             }
43671             /**
43672              * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol
43673              * that is not found in the character symbols.
43674              *
43675              * @private
43676              * @param {Array} strSymbols The string symbols to inspect.
43677              * @param {Array} chrSymbols The character symbols to find.
43678              * @returns {number} Returns the index of the last unmatched string symbol.
43679              */
43680
43681
43682             function charsEndIndex(strSymbols, chrSymbols) {
43683               var index = strSymbols.length;
43684
43685               while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
43686
43687               return index;
43688             }
43689             /**
43690              * Gets the number of `placeholder` occurrences in `array`.
43691              *
43692              * @private
43693              * @param {Array} array The array to inspect.
43694              * @param {*} placeholder The placeholder to search for.
43695              * @returns {number} Returns the placeholder count.
43696              */
43697
43698
43699             function countHolders(array, placeholder) {
43700               var length = array.length,
43701                   result = 0;
43702
43703               while (length--) {
43704                 if (array[length] === placeholder) {
43705                   ++result;
43706                 }
43707               }
43708
43709               return result;
43710             }
43711             /**
43712              * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A
43713              * letters to basic Latin letters.
43714              *
43715              * @private
43716              * @param {string} letter The matched letter to deburr.
43717              * @returns {string} Returns the deburred letter.
43718              */
43719
43720
43721             var deburrLetter = basePropertyOf(deburredLetters);
43722             /**
43723              * Used by `_.escape` to convert characters to HTML entities.
43724              *
43725              * @private
43726              * @param {string} chr The matched character to escape.
43727              * @returns {string} Returns the escaped character.
43728              */
43729
43730             var escapeHtmlChar = basePropertyOf(htmlEscapes);
43731             /**
43732              * Used by `_.template` to escape characters for inclusion in compiled string literals.
43733              *
43734              * @private
43735              * @param {string} chr The matched character to escape.
43736              * @returns {string} Returns the escaped character.
43737              */
43738
43739             function escapeStringChar(chr) {
43740               return '\\' + stringEscapes[chr];
43741             }
43742             /**
43743              * Gets the value at `key` of `object`.
43744              *
43745              * @private
43746              * @param {Object} [object] The object to query.
43747              * @param {string} key The key of the property to get.
43748              * @returns {*} Returns the property value.
43749              */
43750
43751
43752             function getValue(object, key) {
43753               return object == null ? undefined$1 : object[key];
43754             }
43755             /**
43756              * Checks if `string` contains Unicode symbols.
43757              *
43758              * @private
43759              * @param {string} string The string to inspect.
43760              * @returns {boolean} Returns `true` if a symbol is found, else `false`.
43761              */
43762
43763
43764             function hasUnicode(string) {
43765               return reHasUnicode.test(string);
43766             }
43767             /**
43768              * Checks if `string` contains a word composed of Unicode symbols.
43769              *
43770              * @private
43771              * @param {string} string The string to inspect.
43772              * @returns {boolean} Returns `true` if a word is found, else `false`.
43773              */
43774
43775
43776             function hasUnicodeWord(string) {
43777               return reHasUnicodeWord.test(string);
43778             }
43779             /**
43780              * Converts `iterator` to an array.
43781              *
43782              * @private
43783              * @param {Object} iterator The iterator to convert.
43784              * @returns {Array} Returns the converted array.
43785              */
43786
43787
43788             function iteratorToArray(iterator) {
43789               var data,
43790                   result = [];
43791
43792               while (!(data = iterator.next()).done) {
43793                 result.push(data.value);
43794               }
43795
43796               return result;
43797             }
43798             /**
43799              * Converts `map` to its key-value pairs.
43800              *
43801              * @private
43802              * @param {Object} map The map to convert.
43803              * @returns {Array} Returns the key-value pairs.
43804              */
43805
43806
43807             function mapToArray(map) {
43808               var index = -1,
43809                   result = Array(map.size);
43810               map.forEach(function (value, key) {
43811                 result[++index] = [key, value];
43812               });
43813               return result;
43814             }
43815             /**
43816              * Creates a unary function that invokes `func` with its argument transformed.
43817              *
43818              * @private
43819              * @param {Function} func The function to wrap.
43820              * @param {Function} transform The argument transform.
43821              * @returns {Function} Returns the new function.
43822              */
43823
43824
43825             function overArg(func, transform) {
43826               return function (arg) {
43827                 return func(transform(arg));
43828               };
43829             }
43830             /**
43831              * Replaces all `placeholder` elements in `array` with an internal placeholder
43832              * and returns an array of their indexes.
43833              *
43834              * @private
43835              * @param {Array} array The array to modify.
43836              * @param {*} placeholder The placeholder to replace.
43837              * @returns {Array} Returns the new array of placeholder indexes.
43838              */
43839
43840
43841             function replaceHolders(array, placeholder) {
43842               var index = -1,
43843                   length = array.length,
43844                   resIndex = 0,
43845                   result = [];
43846
43847               while (++index < length) {
43848                 var value = array[index];
43849
43850                 if (value === placeholder || value === PLACEHOLDER) {
43851                   array[index] = PLACEHOLDER;
43852                   result[resIndex++] = index;
43853                 }
43854               }
43855
43856               return result;
43857             }
43858             /**
43859              * Converts `set` to an array of its values.
43860              *
43861              * @private
43862              * @param {Object} set The set to convert.
43863              * @returns {Array} Returns the values.
43864              */
43865
43866
43867             function setToArray(set) {
43868               var index = -1,
43869                   result = Array(set.size);
43870               set.forEach(function (value) {
43871                 result[++index] = value;
43872               });
43873               return result;
43874             }
43875             /**
43876              * Converts `set` to its value-value pairs.
43877              *
43878              * @private
43879              * @param {Object} set The set to convert.
43880              * @returns {Array} Returns the value-value pairs.
43881              */
43882
43883
43884             function setToPairs(set) {
43885               var index = -1,
43886                   result = Array(set.size);
43887               set.forEach(function (value) {
43888                 result[++index] = [value, value];
43889               });
43890               return result;
43891             }
43892             /**
43893              * A specialized version of `_.indexOf` which performs strict equality
43894              * comparisons of values, i.e. `===`.
43895              *
43896              * @private
43897              * @param {Array} array The array to inspect.
43898              * @param {*} value The value to search for.
43899              * @param {number} fromIndex The index to search from.
43900              * @returns {number} Returns the index of the matched value, else `-1`.
43901              */
43902
43903
43904             function strictIndexOf(array, value, fromIndex) {
43905               var index = fromIndex - 1,
43906                   length = array.length;
43907
43908               while (++index < length) {
43909                 if (array[index] === value) {
43910                   return index;
43911                 }
43912               }
43913
43914               return -1;
43915             }
43916             /**
43917              * A specialized version of `_.lastIndexOf` which performs strict equality
43918              * comparisons of values, i.e. `===`.
43919              *
43920              * @private
43921              * @param {Array} array The array to inspect.
43922              * @param {*} value The value to search for.
43923              * @param {number} fromIndex The index to search from.
43924              * @returns {number} Returns the index of the matched value, else `-1`.
43925              */
43926
43927
43928             function strictLastIndexOf(array, value, fromIndex) {
43929               var index = fromIndex + 1;
43930
43931               while (index--) {
43932                 if (array[index] === value) {
43933                   return index;
43934                 }
43935               }
43936
43937               return index;
43938             }
43939             /**
43940              * Gets the number of symbols in `string`.
43941              *
43942              * @private
43943              * @param {string} string The string to inspect.
43944              * @returns {number} Returns the string size.
43945              */
43946
43947
43948             function stringSize(string) {
43949               return hasUnicode(string) ? unicodeSize(string) : asciiSize(string);
43950             }
43951             /**
43952              * Converts `string` to an array.
43953              *
43954              * @private
43955              * @param {string} string The string to convert.
43956              * @returns {Array} Returns the converted array.
43957              */
43958
43959
43960             function stringToArray(string) {
43961               return hasUnicode(string) ? unicodeToArray(string) : asciiToArray(string);
43962             }
43963             /**
43964              * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace
43965              * character of `string`.
43966              *
43967              * @private
43968              * @param {string} string The string to inspect.
43969              * @returns {number} Returns the index of the last non-whitespace character.
43970              */
43971
43972
43973             function trimmedEndIndex(string) {
43974               var index = string.length;
43975
43976               while (index-- && reWhitespace.test(string.charAt(index))) {}
43977
43978               return index;
43979             }
43980             /**
43981              * Used by `_.unescape` to convert HTML entities to characters.
43982              *
43983              * @private
43984              * @param {string} chr The matched character to unescape.
43985              * @returns {string} Returns the unescaped character.
43986              */
43987
43988
43989             var unescapeHtmlChar = basePropertyOf(htmlUnescapes);
43990             /**
43991              * Gets the size of a Unicode `string`.
43992              *
43993              * @private
43994              * @param {string} string The string inspect.
43995              * @returns {number} Returns the string size.
43996              */
43997
43998             function unicodeSize(string) {
43999               var result = reUnicode.lastIndex = 0;
44000
44001               while (reUnicode.test(string)) {
44002                 ++result;
44003               }
44004
44005               return result;
44006             }
44007             /**
44008              * Converts a Unicode `string` to an array.
44009              *
44010              * @private
44011              * @param {string} string The string to convert.
44012              * @returns {Array} Returns the converted array.
44013              */
44014
44015
44016             function unicodeToArray(string) {
44017               return string.match(reUnicode) || [];
44018             }
44019             /**
44020              * Splits a Unicode `string` into an array of its words.
44021              *
44022              * @private
44023              * @param {string} The string to inspect.
44024              * @returns {Array} Returns the words of `string`.
44025              */
44026
44027
44028             function unicodeWords(string) {
44029               return string.match(reUnicodeWord) || [];
44030             }
44031             /*--------------------------------------------------------------------------*/
44032
44033             /**
44034              * Create a new pristine `lodash` function using the `context` object.
44035              *
44036              * @static
44037              * @memberOf _
44038              * @since 1.1.0
44039              * @category Util
44040              * @param {Object} [context=root] The context object.
44041              * @returns {Function} Returns a new `lodash` function.
44042              * @example
44043              *
44044              * _.mixin({ 'foo': _.constant('foo') });
44045              *
44046              * var lodash = _.runInContext();
44047              * lodash.mixin({ 'bar': lodash.constant('bar') });
44048              *
44049              * _.isFunction(_.foo);
44050              * // => true
44051              * _.isFunction(_.bar);
44052              * // => false
44053              *
44054              * lodash.isFunction(lodash.foo);
44055              * // => false
44056              * lodash.isFunction(lodash.bar);
44057              * // => true
44058              *
44059              * // Create a suped-up `defer` in Node.js.
44060              * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
44061              */
44062
44063
44064             var runInContext = function runInContext(context) {
44065               context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps));
44066               /** Built-in constructor references. */
44067
44068               var Array = context.Array,
44069                   Date = context.Date,
44070                   Error = context.Error,
44071                   Function = context.Function,
44072                   Math = context.Math,
44073                   Object = context.Object,
44074                   RegExp = context.RegExp,
44075                   String = context.String,
44076                   TypeError = context.TypeError;
44077               /** Used for built-in method references. */
44078
44079               var arrayProto = Array.prototype,
44080                   funcProto = Function.prototype,
44081                   objectProto = Object.prototype;
44082               /** Used to detect overreaching core-js shims. */
44083
44084               var coreJsData = context['__core-js_shared__'];
44085               /** Used to resolve the decompiled source of functions. */
44086
44087               var funcToString = funcProto.toString;
44088               /** Used to check objects for own properties. */
44089
44090               var hasOwnProperty = objectProto.hasOwnProperty;
44091               /** Used to generate unique IDs. */
44092
44093               var idCounter = 0;
44094               /** Used to detect methods masquerading as native. */
44095
44096               var maskSrcKey = function () {
44097                 var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
44098                 return uid ? 'Symbol(src)_1.' + uid : '';
44099               }();
44100               /**
44101                * Used to resolve the
44102                * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
44103                * of values.
44104                */
44105
44106
44107               var nativeObjectToString = objectProto.toString;
44108               /** Used to infer the `Object` constructor. */
44109
44110               var objectCtorString = funcToString.call(Object);
44111               /** Used to restore the original `_` reference in `_.noConflict`. */
44112
44113               var oldDash = root._;
44114               /** Used to detect if a method is native. */
44115
44116               var reIsNative = RegExp('^' + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&').replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$');
44117               /** Built-in value references. */
44118
44119               var Buffer = moduleExports ? context.Buffer : undefined$1,
44120                   _Symbol = context.Symbol,
44121                   Uint8Array = context.Uint8Array,
44122                   allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined$1,
44123                   getPrototype = overArg(Object.getPrototypeOf, Object),
44124                   objectCreate = Object.create,
44125                   propertyIsEnumerable = objectProto.propertyIsEnumerable,
44126                   splice = arrayProto.splice,
44127                   spreadableSymbol = _Symbol ? _Symbol.isConcatSpreadable : undefined$1,
44128                   symIterator = _Symbol ? _Symbol.iterator : undefined$1,
44129                   symToStringTag = _Symbol ? _Symbol.toStringTag : undefined$1;
44130
44131               var defineProperty = function () {
44132                 try {
44133                   var func = getNative(Object, 'defineProperty');
44134                   func({}, '', {});
44135                   return func;
44136                 } catch (e) {}
44137               }();
44138               /** Mocked built-ins. */
44139
44140
44141               var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout,
44142                   ctxNow = Date && Date.now !== root.Date.now && Date.now,
44143                   ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout;
44144               /* Built-in method references for those with the same name as other `lodash` methods. */
44145
44146               var nativeCeil = Math.ceil,
44147                   nativeFloor = Math.floor,
44148                   nativeGetSymbols = Object.getOwnPropertySymbols,
44149                   nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined$1,
44150                   nativeIsFinite = context.isFinite,
44151                   nativeJoin = arrayProto.join,
44152                   nativeKeys = overArg(Object.keys, Object),
44153                   nativeMax = Math.max,
44154                   nativeMin = Math.min,
44155                   nativeNow = Date.now,
44156                   nativeParseInt = context.parseInt,
44157                   nativeRandom = Math.random,
44158                   nativeReverse = arrayProto.reverse;
44159               /* Built-in method references that are verified to be native. */
44160
44161               var DataView = getNative(context, 'DataView'),
44162                   Map = getNative(context, 'Map'),
44163                   Promise = getNative(context, 'Promise'),
44164                   Set = getNative(context, 'Set'),
44165                   WeakMap = getNative(context, 'WeakMap'),
44166                   nativeCreate = getNative(Object, 'create');
44167               /** Used to store function metadata. */
44168
44169               var metaMap = WeakMap && new WeakMap();
44170               /** Used to lookup unminified function names. */
44171
44172               var realNames = {};
44173               /** Used to detect maps, sets, and weakmaps. */
44174
44175               var dataViewCtorString = toSource(DataView),
44176                   mapCtorString = toSource(Map),
44177                   promiseCtorString = toSource(Promise),
44178                   setCtorString = toSource(Set),
44179                   weakMapCtorString = toSource(WeakMap);
44180               /** Used to convert symbols to primitives and strings. */
44181
44182               var symbolProto = _Symbol ? _Symbol.prototype : undefined$1,
44183                   symbolValueOf = symbolProto ? symbolProto.valueOf : undefined$1,
44184                   symbolToString = symbolProto ? symbolProto.toString : undefined$1;
44185               /*------------------------------------------------------------------------*/
44186
44187               /**
44188                * Creates a `lodash` object which wraps `value` to enable implicit method
44189                * chain sequences. Methods that operate on and return arrays, collections,
44190                * and functions can be chained together. Methods that retrieve a single value
44191                * or may return a primitive value will automatically end the chain sequence
44192                * and return the unwrapped value. Otherwise, the value must be unwrapped
44193                * with `_#value`.
44194                *
44195                * Explicit chain sequences, which must be unwrapped with `_#value`, may be
44196                * enabled using `_.chain`.
44197                *
44198                * The execution of chained methods is lazy, that is, it's deferred until
44199                * `_#value` is implicitly or explicitly called.
44200                *
44201                * Lazy evaluation allows several methods to support shortcut fusion.
44202                * Shortcut fusion is an optimization to merge iteratee calls; this avoids
44203                * the creation of intermediate arrays and can greatly reduce the number of
44204                * iteratee executions. Sections of a chain sequence qualify for shortcut
44205                * fusion if the section is applied to an array and iteratees accept only
44206                * one argument. The heuristic for whether a section qualifies for shortcut
44207                * fusion is subject to change.
44208                *
44209                * Chaining is supported in custom builds as long as the `_#value` method is
44210                * directly or indirectly included in the build.
44211                *
44212                * In addition to lodash methods, wrappers have `Array` and `String` methods.
44213                *
44214                * The wrapper `Array` methods are:
44215                * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift`
44216                *
44217                * The wrapper `String` methods are:
44218                * `replace` and `split`
44219                *
44220                * The wrapper methods that support shortcut fusion are:
44221                * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,
44222                * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,
44223                * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`
44224                *
44225                * The chainable wrapper methods are:
44226                * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,
44227                * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,
44228                * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,
44229                * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`,
44230                * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`,
44231                * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`,
44232                * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`,
44233                * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`,
44234                * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`,
44235                * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`,
44236                * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,
44237                * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`,
44238                * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`,
44239                * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`,
44240                * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`,
44241                * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`,
44242                * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`,
44243                * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`,
44244                * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`,
44245                * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`,
44246                * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`,
44247                * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`,
44248                * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`,
44249                * `zipObject`, `zipObjectDeep`, and `zipWith`
44250                *
44251                * The wrapper methods that are **not** chainable by default are:
44252                * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,
44253                * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`,
44254                * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`,
44255                * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`,
44256                * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`,
44257                * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`,
44258                * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`,
44259                * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`,
44260                * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`,
44261                * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`,
44262                * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`,
44263                * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`,
44264                * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`,
44265                * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`,
44266                * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`,
44267                * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`,
44268                * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`,
44269                * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`,
44270                * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`,
44271                * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`,
44272                * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`,
44273                * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`,
44274                * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`,
44275                * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`,
44276                * `upperFirst`, `value`, and `words`
44277                *
44278                * @name _
44279                * @constructor
44280                * @category Seq
44281                * @param {*} value The value to wrap in a `lodash` instance.
44282                * @returns {Object} Returns the new `lodash` wrapper instance.
44283                * @example
44284                *
44285                * function square(n) {
44286                *   return n * n;
44287                * }
44288                *
44289                * var wrapped = _([1, 2, 3]);
44290                *
44291                * // Returns an unwrapped value.
44292                * wrapped.reduce(_.add);
44293                * // => 6
44294                *
44295                * // Returns a wrapped value.
44296                * var squares = wrapped.map(square);
44297                *
44298                * _.isArray(squares);
44299                * // => false
44300                *
44301                * _.isArray(squares.value());
44302                * // => true
44303                */
44304
44305               function lodash(value) {
44306                 if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
44307                   if (value instanceof LodashWrapper) {
44308                     return value;
44309                   }
44310
44311                   if (hasOwnProperty.call(value, '__wrapped__')) {
44312                     return wrapperClone(value);
44313                   }
44314                 }
44315
44316                 return new LodashWrapper(value);
44317               }
44318               /**
44319                * The base implementation of `_.create` without support for assigning
44320                * properties to the created object.
44321                *
44322                * @private
44323                * @param {Object} proto The object to inherit from.
44324                * @returns {Object} Returns the new object.
44325                */
44326
44327
44328               var baseCreate = function () {
44329                 function object() {}
44330
44331                 return function (proto) {
44332                   if (!isObject(proto)) {
44333                     return {};
44334                   }
44335
44336                   if (objectCreate) {
44337                     return objectCreate(proto);
44338                   }
44339
44340                   object.prototype = proto;
44341                   var result = new object();
44342                   object.prototype = undefined$1;
44343                   return result;
44344                 };
44345               }();
44346               /**
44347                * The function whose prototype chain sequence wrappers inherit from.
44348                *
44349                * @private
44350                */
44351
44352
44353               function baseLodash() {// No operation performed.
44354               }
44355               /**
44356                * The base constructor for creating `lodash` wrapper objects.
44357                *
44358                * @private
44359                * @param {*} value The value to wrap.
44360                * @param {boolean} [chainAll] Enable explicit method chain sequences.
44361                */
44362
44363
44364               function LodashWrapper(value, chainAll) {
44365                 this.__wrapped__ = value;
44366                 this.__actions__ = [];
44367                 this.__chain__ = !!chainAll;
44368                 this.__index__ = 0;
44369                 this.__values__ = undefined$1;
44370               }
44371               /**
44372                * By default, the template delimiters used by lodash are like those in
44373                * embedded Ruby (ERB) as well as ES2015 template strings. Change the
44374                * following template settings to use alternative delimiters.
44375                *
44376                * @static
44377                * @memberOf _
44378                * @type {Object}
44379                */
44380
44381
44382               lodash.templateSettings = {
44383                 /**
44384                  * Used to detect `data` property values to be HTML-escaped.
44385                  *
44386                  * @memberOf _.templateSettings
44387                  * @type {RegExp}
44388                  */
44389                 'escape': reEscape,
44390
44391                 /**
44392                  * Used to detect code to be evaluated.
44393                  *
44394                  * @memberOf _.templateSettings
44395                  * @type {RegExp}
44396                  */
44397                 'evaluate': reEvaluate,
44398
44399                 /**
44400                  * Used to detect `data` property values to inject.
44401                  *
44402                  * @memberOf _.templateSettings
44403                  * @type {RegExp}
44404                  */
44405                 'interpolate': reInterpolate,
44406
44407                 /**
44408                  * Used to reference the data object in the template text.
44409                  *
44410                  * @memberOf _.templateSettings
44411                  * @type {string}
44412                  */
44413                 'variable': '',
44414
44415                 /**
44416                  * Used to import variables into the compiled template.
44417                  *
44418                  * @memberOf _.templateSettings
44419                  * @type {Object}
44420                  */
44421                 'imports': {
44422                   /**
44423                    * A reference to the `lodash` function.
44424                    *
44425                    * @memberOf _.templateSettings.imports
44426                    * @type {Function}
44427                    */
44428                   '_': lodash
44429                 }
44430               }; // Ensure wrappers are instances of `baseLodash`.
44431
44432               lodash.prototype = baseLodash.prototype;
44433               lodash.prototype.constructor = lodash;
44434               LodashWrapper.prototype = baseCreate(baseLodash.prototype);
44435               LodashWrapper.prototype.constructor = LodashWrapper;
44436               /*------------------------------------------------------------------------*/
44437
44438               /**
44439                * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
44440                *
44441                * @private
44442                * @constructor
44443                * @param {*} value The value to wrap.
44444                */
44445
44446               function LazyWrapper(value) {
44447                 this.__wrapped__ = value;
44448                 this.__actions__ = [];
44449                 this.__dir__ = 1;
44450                 this.__filtered__ = false;
44451                 this.__iteratees__ = [];
44452                 this.__takeCount__ = MAX_ARRAY_LENGTH;
44453                 this.__views__ = [];
44454               }
44455               /**
44456                * Creates a clone of the lazy wrapper object.
44457                *
44458                * @private
44459                * @name clone
44460                * @memberOf LazyWrapper
44461                * @returns {Object} Returns the cloned `LazyWrapper` object.
44462                */
44463
44464
44465               function lazyClone() {
44466                 var result = new LazyWrapper(this.__wrapped__);
44467                 result.__actions__ = copyArray(this.__actions__);
44468                 result.__dir__ = this.__dir__;
44469                 result.__filtered__ = this.__filtered__;
44470                 result.__iteratees__ = copyArray(this.__iteratees__);
44471                 result.__takeCount__ = this.__takeCount__;
44472                 result.__views__ = copyArray(this.__views__);
44473                 return result;
44474               }
44475               /**
44476                * Reverses the direction of lazy iteration.
44477                *
44478                * @private
44479                * @name reverse
44480                * @memberOf LazyWrapper
44481                * @returns {Object} Returns the new reversed `LazyWrapper` object.
44482                */
44483
44484
44485               function lazyReverse() {
44486                 if (this.__filtered__) {
44487                   var result = new LazyWrapper(this);
44488                   result.__dir__ = -1;
44489                   result.__filtered__ = true;
44490                 } else {
44491                   result = this.clone();
44492                   result.__dir__ *= -1;
44493                 }
44494
44495                 return result;
44496               }
44497               /**
44498                * Extracts the unwrapped value from its lazy wrapper.
44499                *
44500                * @private
44501                * @name value
44502                * @memberOf LazyWrapper
44503                * @returns {*} Returns the unwrapped value.
44504                */
44505
44506
44507               function lazyValue() {
44508                 var array = this.__wrapped__.value(),
44509                     dir = this.__dir__,
44510                     isArr = isArray(array),
44511                     isRight = dir < 0,
44512                     arrLength = isArr ? array.length : 0,
44513                     view = getView(0, arrLength, this.__views__),
44514                     start = view.start,
44515                     end = view.end,
44516                     length = end - start,
44517                     index = isRight ? end : start - 1,
44518                     iteratees = this.__iteratees__,
44519                     iterLength = iteratees.length,
44520                     resIndex = 0,
44521                     takeCount = nativeMin(length, this.__takeCount__);
44522
44523                 if (!isArr || !isRight && arrLength == length && takeCount == length) {
44524                   return baseWrapperValue(array, this.__actions__);
44525                 }
44526
44527                 var result = [];
44528
44529                 outer: while (length-- && resIndex < takeCount) {
44530                   index += dir;
44531                   var iterIndex = -1,
44532                       value = array[index];
44533
44534                   while (++iterIndex < iterLength) {
44535                     var data = iteratees[iterIndex],
44536                         iteratee = data.iteratee,
44537                         type = data.type,
44538                         computed = iteratee(value);
44539
44540                     if (type == LAZY_MAP_FLAG) {
44541                       value = computed;
44542                     } else if (!computed) {
44543                       if (type == LAZY_FILTER_FLAG) {
44544                         continue outer;
44545                       } else {
44546                         break outer;
44547                       }
44548                     }
44549                   }
44550
44551                   result[resIndex++] = value;
44552                 }
44553
44554                 return result;
44555               } // Ensure `LazyWrapper` is an instance of `baseLodash`.
44556
44557
44558               LazyWrapper.prototype = baseCreate(baseLodash.prototype);
44559               LazyWrapper.prototype.constructor = LazyWrapper;
44560               /*------------------------------------------------------------------------*/
44561
44562               /**
44563                * Creates a hash object.
44564                *
44565                * @private
44566                * @constructor
44567                * @param {Array} [entries] The key-value pairs to cache.
44568                */
44569
44570               function Hash(entries) {
44571                 var index = -1,
44572                     length = entries == null ? 0 : entries.length;
44573                 this.clear();
44574
44575                 while (++index < length) {
44576                   var entry = entries[index];
44577                   this.set(entry[0], entry[1]);
44578                 }
44579               }
44580               /**
44581                * Removes all key-value entries from the hash.
44582                *
44583                * @private
44584                * @name clear
44585                * @memberOf Hash
44586                */
44587
44588
44589               function hashClear() {
44590                 this.__data__ = nativeCreate ? nativeCreate(null) : {};
44591                 this.size = 0;
44592               }
44593               /**
44594                * Removes `key` and its value from the hash.
44595                *
44596                * @private
44597                * @name delete
44598                * @memberOf Hash
44599                * @param {Object} hash The hash to modify.
44600                * @param {string} key The key of the value to remove.
44601                * @returns {boolean} Returns `true` if the entry was removed, else `false`.
44602                */
44603
44604
44605               function hashDelete(key) {
44606                 var result = this.has(key) && delete this.__data__[key];
44607                 this.size -= result ? 1 : 0;
44608                 return result;
44609               }
44610               /**
44611                * Gets the hash value for `key`.
44612                *
44613                * @private
44614                * @name get
44615                * @memberOf Hash
44616                * @param {string} key The key of the value to get.
44617                * @returns {*} Returns the entry value.
44618                */
44619
44620
44621               function hashGet(key) {
44622                 var data = this.__data__;
44623
44624                 if (nativeCreate) {
44625                   var result = data[key];
44626                   return result === HASH_UNDEFINED ? undefined$1 : result;
44627                 }
44628
44629                 return hasOwnProperty.call(data, key) ? data[key] : undefined$1;
44630               }
44631               /**
44632                * Checks if a hash value for `key` exists.
44633                *
44634                * @private
44635                * @name has
44636                * @memberOf Hash
44637                * @param {string} key The key of the entry to check.
44638                * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
44639                */
44640
44641
44642               function hashHas(key) {
44643                 var data = this.__data__;
44644                 return nativeCreate ? data[key] !== undefined$1 : hasOwnProperty.call(data, key);
44645               }
44646               /**
44647                * Sets the hash `key` to `value`.
44648                *
44649                * @private
44650                * @name set
44651                * @memberOf Hash
44652                * @param {string} key The key of the value to set.
44653                * @param {*} value The value to set.
44654                * @returns {Object} Returns the hash instance.
44655                */
44656
44657
44658               function hashSet(key, value) {
44659                 var data = this.__data__;
44660                 this.size += this.has(key) ? 0 : 1;
44661                 data[key] = nativeCreate && value === undefined$1 ? HASH_UNDEFINED : value;
44662                 return this;
44663               } // Add methods to `Hash`.
44664
44665
44666               Hash.prototype.clear = hashClear;
44667               Hash.prototype['delete'] = hashDelete;
44668               Hash.prototype.get = hashGet;
44669               Hash.prototype.has = hashHas;
44670               Hash.prototype.set = hashSet;
44671               /*------------------------------------------------------------------------*/
44672
44673               /**
44674                * Creates an list cache object.
44675                *
44676                * @private
44677                * @constructor
44678                * @param {Array} [entries] The key-value pairs to cache.
44679                */
44680
44681               function ListCache(entries) {
44682                 var index = -1,
44683                     length = entries == null ? 0 : entries.length;
44684                 this.clear();
44685
44686                 while (++index < length) {
44687                   var entry = entries[index];
44688                   this.set(entry[0], entry[1]);
44689                 }
44690               }
44691               /**
44692                * Removes all key-value entries from the list cache.
44693                *
44694                * @private
44695                * @name clear
44696                * @memberOf ListCache
44697                */
44698
44699
44700               function listCacheClear() {
44701                 this.__data__ = [];
44702                 this.size = 0;
44703               }
44704               /**
44705                * Removes `key` and its value from the list cache.
44706                *
44707                * @private
44708                * @name delete
44709                * @memberOf ListCache
44710                * @param {string} key The key of the value to remove.
44711                * @returns {boolean} Returns `true` if the entry was removed, else `false`.
44712                */
44713
44714
44715               function listCacheDelete(key) {
44716                 var data = this.__data__,
44717                     index = assocIndexOf(data, key);
44718
44719                 if (index < 0) {
44720                   return false;
44721                 }
44722
44723                 var lastIndex = data.length - 1;
44724
44725                 if (index == lastIndex) {
44726                   data.pop();
44727                 } else {
44728                   splice.call(data, index, 1);
44729                 }
44730
44731                 --this.size;
44732                 return true;
44733               }
44734               /**
44735                * Gets the list cache value for `key`.
44736                *
44737                * @private
44738                * @name get
44739                * @memberOf ListCache
44740                * @param {string} key The key of the value to get.
44741                * @returns {*} Returns the entry value.
44742                */
44743
44744
44745               function listCacheGet(key) {
44746                 var data = this.__data__,
44747                     index = assocIndexOf(data, key);
44748                 return index < 0 ? undefined$1 : data[index][1];
44749               }
44750               /**
44751                * Checks if a list cache value for `key` exists.
44752                *
44753                * @private
44754                * @name has
44755                * @memberOf ListCache
44756                * @param {string} key The key of the entry to check.
44757                * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
44758                */
44759
44760
44761               function listCacheHas(key) {
44762                 return assocIndexOf(this.__data__, key) > -1;
44763               }
44764               /**
44765                * Sets the list cache `key` to `value`.
44766                *
44767                * @private
44768                * @name set
44769                * @memberOf ListCache
44770                * @param {string} key The key of the value to set.
44771                * @param {*} value The value to set.
44772                * @returns {Object} Returns the list cache instance.
44773                */
44774
44775
44776               function listCacheSet(key, value) {
44777                 var data = this.__data__,
44778                     index = assocIndexOf(data, key);
44779
44780                 if (index < 0) {
44781                   ++this.size;
44782                   data.push([key, value]);
44783                 } else {
44784                   data[index][1] = value;
44785                 }
44786
44787                 return this;
44788               } // Add methods to `ListCache`.
44789
44790
44791               ListCache.prototype.clear = listCacheClear;
44792               ListCache.prototype['delete'] = listCacheDelete;
44793               ListCache.prototype.get = listCacheGet;
44794               ListCache.prototype.has = listCacheHas;
44795               ListCache.prototype.set = listCacheSet;
44796               /*------------------------------------------------------------------------*/
44797
44798               /**
44799                * Creates a map cache object to store key-value pairs.
44800                *
44801                * @private
44802                * @constructor
44803                * @param {Array} [entries] The key-value pairs to cache.
44804                */
44805
44806               function MapCache(entries) {
44807                 var index = -1,
44808                     length = entries == null ? 0 : entries.length;
44809                 this.clear();
44810
44811                 while (++index < length) {
44812                   var entry = entries[index];
44813                   this.set(entry[0], entry[1]);
44814                 }
44815               }
44816               /**
44817                * Removes all key-value entries from the map.
44818                *
44819                * @private
44820                * @name clear
44821                * @memberOf MapCache
44822                */
44823
44824
44825               function mapCacheClear() {
44826                 this.size = 0;
44827                 this.__data__ = {
44828                   'hash': new Hash(),
44829                   'map': new (Map || ListCache)(),
44830                   'string': new Hash()
44831                 };
44832               }
44833               /**
44834                * Removes `key` and its value from the map.
44835                *
44836                * @private
44837                * @name delete
44838                * @memberOf MapCache
44839                * @param {string} key The key of the value to remove.
44840                * @returns {boolean} Returns `true` if the entry was removed, else `false`.
44841                */
44842
44843
44844               function mapCacheDelete(key) {
44845                 var result = getMapData(this, key)['delete'](key);
44846                 this.size -= result ? 1 : 0;
44847                 return result;
44848               }
44849               /**
44850                * Gets the map value for `key`.
44851                *
44852                * @private
44853                * @name get
44854                * @memberOf MapCache
44855                * @param {string} key The key of the value to get.
44856                * @returns {*} Returns the entry value.
44857                */
44858
44859
44860               function mapCacheGet(key) {
44861                 return getMapData(this, key).get(key);
44862               }
44863               /**
44864                * Checks if a map value for `key` exists.
44865                *
44866                * @private
44867                * @name has
44868                * @memberOf MapCache
44869                * @param {string} key The key of the entry to check.
44870                * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
44871                */
44872
44873
44874               function mapCacheHas(key) {
44875                 return getMapData(this, key).has(key);
44876               }
44877               /**
44878                * Sets the map `key` to `value`.
44879                *
44880                * @private
44881                * @name set
44882                * @memberOf MapCache
44883                * @param {string} key The key of the value to set.
44884                * @param {*} value The value to set.
44885                * @returns {Object} Returns the map cache instance.
44886                */
44887
44888
44889               function mapCacheSet(key, value) {
44890                 var data = getMapData(this, key),
44891                     size = data.size;
44892                 data.set(key, value);
44893                 this.size += data.size == size ? 0 : 1;
44894                 return this;
44895               } // Add methods to `MapCache`.
44896
44897
44898               MapCache.prototype.clear = mapCacheClear;
44899               MapCache.prototype['delete'] = mapCacheDelete;
44900               MapCache.prototype.get = mapCacheGet;
44901               MapCache.prototype.has = mapCacheHas;
44902               MapCache.prototype.set = mapCacheSet;
44903               /*------------------------------------------------------------------------*/
44904
44905               /**
44906                *
44907                * Creates an array cache object to store unique values.
44908                *
44909                * @private
44910                * @constructor
44911                * @param {Array} [values] The values to cache.
44912                */
44913
44914               function SetCache(values) {
44915                 var index = -1,
44916                     length = values == null ? 0 : values.length;
44917                 this.__data__ = new MapCache();
44918
44919                 while (++index < length) {
44920                   this.add(values[index]);
44921                 }
44922               }
44923               /**
44924                * Adds `value` to the array cache.
44925                *
44926                * @private
44927                * @name add
44928                * @memberOf SetCache
44929                * @alias push
44930                * @param {*} value The value to cache.
44931                * @returns {Object} Returns the cache instance.
44932                */
44933
44934
44935               function setCacheAdd(value) {
44936                 this.__data__.set(value, HASH_UNDEFINED);
44937
44938                 return this;
44939               }
44940               /**
44941                * Checks if `value` is in the array cache.
44942                *
44943                * @private
44944                * @name has
44945                * @memberOf SetCache
44946                * @param {*} value The value to search for.
44947                * @returns {number} Returns `true` if `value` is found, else `false`.
44948                */
44949
44950
44951               function setCacheHas(value) {
44952                 return this.__data__.has(value);
44953               } // Add methods to `SetCache`.
44954
44955
44956               SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
44957               SetCache.prototype.has = setCacheHas;
44958               /*------------------------------------------------------------------------*/
44959
44960               /**
44961                * Creates a stack cache object to store key-value pairs.
44962                *
44963                * @private
44964                * @constructor
44965                * @param {Array} [entries] The key-value pairs to cache.
44966                */
44967
44968               function Stack(entries) {
44969                 var data = this.__data__ = new ListCache(entries);
44970                 this.size = data.size;
44971               }
44972               /**
44973                * Removes all key-value entries from the stack.
44974                *
44975                * @private
44976                * @name clear
44977                * @memberOf Stack
44978                */
44979
44980
44981               function stackClear() {
44982                 this.__data__ = new ListCache();
44983                 this.size = 0;
44984               }
44985               /**
44986                * Removes `key` and its value from the stack.
44987                *
44988                * @private
44989                * @name delete
44990                * @memberOf Stack
44991                * @param {string} key The key of the value to remove.
44992                * @returns {boolean} Returns `true` if the entry was removed, else `false`.
44993                */
44994
44995
44996               function stackDelete(key) {
44997                 var data = this.__data__,
44998                     result = data['delete'](key);
44999                 this.size = data.size;
45000                 return result;
45001               }
45002               /**
45003                * Gets the stack value for `key`.
45004                *
45005                * @private
45006                * @name get
45007                * @memberOf Stack
45008                * @param {string} key The key of the value to get.
45009                * @returns {*} Returns the entry value.
45010                */
45011
45012
45013               function stackGet(key) {
45014                 return this.__data__.get(key);
45015               }
45016               /**
45017                * Checks if a stack value for `key` exists.
45018                *
45019                * @private
45020                * @name has
45021                * @memberOf Stack
45022                * @param {string} key The key of the entry to check.
45023                * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
45024                */
45025
45026
45027               function stackHas(key) {
45028                 return this.__data__.has(key);
45029               }
45030               /**
45031                * Sets the stack `key` to `value`.
45032                *
45033                * @private
45034                * @name set
45035                * @memberOf Stack
45036                * @param {string} key The key of the value to set.
45037                * @param {*} value The value to set.
45038                * @returns {Object} Returns the stack cache instance.
45039                */
45040
45041
45042               function stackSet(key, value) {
45043                 var data = this.__data__;
45044
45045                 if (data instanceof ListCache) {
45046                   var pairs = data.__data__;
45047
45048                   if (!Map || pairs.length < LARGE_ARRAY_SIZE - 1) {
45049                     pairs.push([key, value]);
45050                     this.size = ++data.size;
45051                     return this;
45052                   }
45053
45054                   data = this.__data__ = new MapCache(pairs);
45055                 }
45056
45057                 data.set(key, value);
45058                 this.size = data.size;
45059                 return this;
45060               } // Add methods to `Stack`.
45061
45062
45063               Stack.prototype.clear = stackClear;
45064               Stack.prototype['delete'] = stackDelete;
45065               Stack.prototype.get = stackGet;
45066               Stack.prototype.has = stackHas;
45067               Stack.prototype.set = stackSet;
45068               /*------------------------------------------------------------------------*/
45069
45070               /**
45071                * Creates an array of the enumerable property names of the array-like `value`.
45072                *
45073                * @private
45074                * @param {*} value The value to query.
45075                * @param {boolean} inherited Specify returning inherited property names.
45076                * @returns {Array} Returns the array of property names.
45077                */
45078
45079               function arrayLikeKeys(value, inherited) {
45080                 var isArr = isArray(value),
45081                     isArg = !isArr && isArguments(value),
45082                     isBuff = !isArr && !isArg && isBuffer(value),
45083                     isType = !isArr && !isArg && !isBuff && isTypedArray(value),
45084                     skipIndexes = isArr || isArg || isBuff || isType,
45085                     result = skipIndexes ? baseTimes(value.length, String) : [],
45086                     length = result.length;
45087
45088                 for (var key in value) {
45089                   if ((inherited || hasOwnProperty.call(value, key)) && !(skipIndexes && ( // Safari 9 has enumerable `arguments.length` in strict mode.
45090                   key == 'length' || // Node.js 0.10 has enumerable non-index properties on buffers.
45091                   isBuff && (key == 'offset' || key == 'parent') || // PhantomJS 2 has enumerable non-index properties on typed arrays.
45092                   isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset') || // Skip index properties.
45093                   isIndex(key, length)))) {
45094                     result.push(key);
45095                   }
45096                 }
45097
45098                 return result;
45099               }
45100               /**
45101                * A specialized version of `_.sample` for arrays.
45102                *
45103                * @private
45104                * @param {Array} array The array to sample.
45105                * @returns {*} Returns the random element.
45106                */
45107
45108
45109               function arraySample(array) {
45110                 var length = array.length;
45111                 return length ? array[baseRandom(0, length - 1)] : undefined$1;
45112               }
45113               /**
45114                * A specialized version of `_.sampleSize` for arrays.
45115                *
45116                * @private
45117                * @param {Array} array The array to sample.
45118                * @param {number} n The number of elements to sample.
45119                * @returns {Array} Returns the random elements.
45120                */
45121
45122
45123               function arraySampleSize(array, n) {
45124                 return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length));
45125               }
45126               /**
45127                * A specialized version of `_.shuffle` for arrays.
45128                *
45129                * @private
45130                * @param {Array} array The array to shuffle.
45131                * @returns {Array} Returns the new shuffled array.
45132                */
45133
45134
45135               function arrayShuffle(array) {
45136                 return shuffleSelf(copyArray(array));
45137               }
45138               /**
45139                * This function is like `assignValue` except that it doesn't assign
45140                * `undefined` values.
45141                *
45142                * @private
45143                * @param {Object} object The object to modify.
45144                * @param {string} key The key of the property to assign.
45145                * @param {*} value The value to assign.
45146                */
45147
45148
45149               function assignMergeValue(object, key, value) {
45150                 if (value !== undefined$1 && !eq(object[key], value) || value === undefined$1 && !(key in object)) {
45151                   baseAssignValue(object, key, value);
45152                 }
45153               }
45154               /**
45155                * Assigns `value` to `key` of `object` if the existing value is not equivalent
45156                * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
45157                * for equality comparisons.
45158                *
45159                * @private
45160                * @param {Object} object The object to modify.
45161                * @param {string} key The key of the property to assign.
45162                * @param {*} value The value to assign.
45163                */
45164
45165
45166               function assignValue(object, key, value) {
45167                 var objValue = object[key];
45168
45169                 if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || value === undefined$1 && !(key in object)) {
45170                   baseAssignValue(object, key, value);
45171                 }
45172               }
45173               /**
45174                * Gets the index at which the `key` is found in `array` of key-value pairs.
45175                *
45176                * @private
45177                * @param {Array} array The array to inspect.
45178                * @param {*} key The key to search for.
45179                * @returns {number} Returns the index of the matched value, else `-1`.
45180                */
45181
45182
45183               function assocIndexOf(array, key) {
45184                 var length = array.length;
45185
45186                 while (length--) {
45187                   if (eq(array[length][0], key)) {
45188                     return length;
45189                   }
45190                 }
45191
45192                 return -1;
45193               }
45194               /**
45195                * Aggregates elements of `collection` on `accumulator` with keys transformed
45196                * by `iteratee` and values set by `setter`.
45197                *
45198                * @private
45199                * @param {Array|Object} collection The collection to iterate over.
45200                * @param {Function} setter The function to set `accumulator` values.
45201                * @param {Function} iteratee The iteratee to transform keys.
45202                * @param {Object} accumulator The initial aggregated object.
45203                * @returns {Function} Returns `accumulator`.
45204                */
45205
45206
45207               function baseAggregator(collection, setter, iteratee, accumulator) {
45208                 baseEach(collection, function (value, key, collection) {
45209                   setter(accumulator, value, iteratee(value), collection);
45210                 });
45211                 return accumulator;
45212               }
45213               /**
45214                * The base implementation of `_.assign` without support for multiple sources
45215                * or `customizer` functions.
45216                *
45217                * @private
45218                * @param {Object} object The destination object.
45219                * @param {Object} source The source object.
45220                * @returns {Object} Returns `object`.
45221                */
45222
45223
45224               function baseAssign(object, source) {
45225                 return object && copyObject(source, keys(source), object);
45226               }
45227               /**
45228                * The base implementation of `_.assignIn` without support for multiple sources
45229                * or `customizer` functions.
45230                *
45231                * @private
45232                * @param {Object} object The destination object.
45233                * @param {Object} source The source object.
45234                * @returns {Object} Returns `object`.
45235                */
45236
45237
45238               function baseAssignIn(object, source) {
45239                 return object && copyObject(source, keysIn(source), object);
45240               }
45241               /**
45242                * The base implementation of `assignValue` and `assignMergeValue` without
45243                * value checks.
45244                *
45245                * @private
45246                * @param {Object} object The object to modify.
45247                * @param {string} key The key of the property to assign.
45248                * @param {*} value The value to assign.
45249                */
45250
45251
45252               function baseAssignValue(object, key, value) {
45253                 if (key == '__proto__' && defineProperty) {
45254                   defineProperty(object, key, {
45255                     'configurable': true,
45256                     'enumerable': true,
45257                     'value': value,
45258                     'writable': true
45259                   });
45260                 } else {
45261                   object[key] = value;
45262                 }
45263               }
45264               /**
45265                * The base implementation of `_.at` without support for individual paths.
45266                *
45267                * @private
45268                * @param {Object} object The object to iterate over.
45269                * @param {string[]} paths The property paths to pick.
45270                * @returns {Array} Returns the picked elements.
45271                */
45272
45273
45274               function baseAt(object, paths) {
45275                 var index = -1,
45276                     length = paths.length,
45277                     result = Array(length),
45278                     skip = object == null;
45279
45280                 while (++index < length) {
45281                   result[index] = skip ? undefined$1 : get(object, paths[index]);
45282                 }
45283
45284                 return result;
45285               }
45286               /**
45287                * The base implementation of `_.clamp` which doesn't coerce arguments.
45288                *
45289                * @private
45290                * @param {number} number The number to clamp.
45291                * @param {number} [lower] The lower bound.
45292                * @param {number} upper The upper bound.
45293                * @returns {number} Returns the clamped number.
45294                */
45295
45296
45297               function baseClamp(number, lower, upper) {
45298                 if (number === number) {
45299                   if (upper !== undefined$1) {
45300                     number = number <= upper ? number : upper;
45301                   }
45302
45303                   if (lower !== undefined$1) {
45304                     number = number >= lower ? number : lower;
45305                   }
45306                 }
45307
45308                 return number;
45309               }
45310               /**
45311                * The base implementation of `_.clone` and `_.cloneDeep` which tracks
45312                * traversed objects.
45313                *
45314                * @private
45315                * @param {*} value The value to clone.
45316                * @param {boolean} bitmask The bitmask flags.
45317                *  1 - Deep clone
45318                *  2 - Flatten inherited properties
45319                *  4 - Clone symbols
45320                * @param {Function} [customizer] The function to customize cloning.
45321                * @param {string} [key] The key of `value`.
45322                * @param {Object} [object] The parent object of `value`.
45323                * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
45324                * @returns {*} Returns the cloned value.
45325                */
45326
45327
45328               function baseClone(value, bitmask, customizer, key, object, stack) {
45329                 var result,
45330                     isDeep = bitmask & CLONE_DEEP_FLAG,
45331                     isFlat = bitmask & CLONE_FLAT_FLAG,
45332                     isFull = bitmask & CLONE_SYMBOLS_FLAG;
45333
45334                 if (customizer) {
45335                   result = object ? customizer(value, key, object, stack) : customizer(value);
45336                 }
45337
45338                 if (result !== undefined$1) {
45339                   return result;
45340                 }
45341
45342                 if (!isObject(value)) {
45343                   return value;
45344                 }
45345
45346                 var isArr = isArray(value);
45347
45348                 if (isArr) {
45349                   result = initCloneArray(value);
45350
45351                   if (!isDeep) {
45352                     return copyArray(value, result);
45353                   }
45354                 } else {
45355                   var tag = getTag(value),
45356                       isFunc = tag == funcTag || tag == genTag;
45357
45358                   if (isBuffer(value)) {
45359                     return cloneBuffer(value, isDeep);
45360                   }
45361
45362                   if (tag == objectTag || tag == argsTag || isFunc && !object) {
45363                     result = isFlat || isFunc ? {} : initCloneObject(value);
45364
45365                     if (!isDeep) {
45366                       return isFlat ? copySymbolsIn(value, baseAssignIn(result, value)) : copySymbols(value, baseAssign(result, value));
45367                     }
45368                   } else {
45369                     if (!cloneableTags[tag]) {
45370                       return object ? value : {};
45371                     }
45372
45373                     result = initCloneByTag(value, tag, isDeep);
45374                   }
45375                 } // Check for circular references and return its corresponding clone.
45376
45377
45378                 stack || (stack = new Stack());
45379                 var stacked = stack.get(value);
45380
45381                 if (stacked) {
45382                   return stacked;
45383                 }
45384
45385                 stack.set(value, result);
45386
45387                 if (isSet(value)) {
45388                   value.forEach(function (subValue) {
45389                     result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));
45390                   });
45391                 } else if (isMap(value)) {
45392                   value.forEach(function (subValue, key) {
45393                     result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack));
45394                   });
45395                 }
45396
45397                 var keysFunc = isFull ? isFlat ? getAllKeysIn : getAllKeys : isFlat ? keysIn : keys;
45398                 var props = isArr ? undefined$1 : keysFunc(value);
45399                 arrayEach(props || value, function (subValue, key) {
45400                   if (props) {
45401                     key = subValue;
45402                     subValue = value[key];
45403                   } // Recursively populate clone (susceptible to call stack limits).
45404
45405
45406                   assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));
45407                 });
45408                 return result;
45409               }
45410               /**
45411                * The base implementation of `_.conforms` which doesn't clone `source`.
45412                *
45413                * @private
45414                * @param {Object} source The object of property predicates to conform to.
45415                * @returns {Function} Returns the new spec function.
45416                */
45417
45418
45419               function baseConforms(source) {
45420                 var props = keys(source);
45421                 return function (object) {
45422                   return baseConformsTo(object, source, props);
45423                 };
45424               }
45425               /**
45426                * The base implementation of `_.conformsTo` which accepts `props` to check.
45427                *
45428                * @private
45429                * @param {Object} object The object to inspect.
45430                * @param {Object} source The object of property predicates to conform to.
45431                * @returns {boolean} Returns `true` if `object` conforms, else `false`.
45432                */
45433
45434
45435               function baseConformsTo(object, source, props) {
45436                 var length = props.length;
45437
45438                 if (object == null) {
45439                   return !length;
45440                 }
45441
45442                 object = Object(object);
45443
45444                 while (length--) {
45445                   var key = props[length],
45446                       predicate = source[key],
45447                       value = object[key];
45448
45449                   if (value === undefined$1 && !(key in object) || !predicate(value)) {
45450                     return false;
45451                   }
45452                 }
45453
45454                 return true;
45455               }
45456               /**
45457                * The base implementation of `_.delay` and `_.defer` which accepts `args`
45458                * to provide to `func`.
45459                *
45460                * @private
45461                * @param {Function} func The function to delay.
45462                * @param {number} wait The number of milliseconds to delay invocation.
45463                * @param {Array} args The arguments to provide to `func`.
45464                * @returns {number|Object} Returns the timer id or timeout object.
45465                */
45466
45467
45468               function baseDelay(func, wait, args) {
45469                 if (typeof func != 'function') {
45470                   throw new TypeError(FUNC_ERROR_TEXT);
45471                 }
45472
45473                 return setTimeout(function () {
45474                   func.apply(undefined$1, args);
45475                 }, wait);
45476               }
45477               /**
45478                * The base implementation of methods like `_.difference` without support
45479                * for excluding multiple arrays or iteratee shorthands.
45480                *
45481                * @private
45482                * @param {Array} array The array to inspect.
45483                * @param {Array} values The values to exclude.
45484                * @param {Function} [iteratee] The iteratee invoked per element.
45485                * @param {Function} [comparator] The comparator invoked per element.
45486                * @returns {Array} Returns the new array of filtered values.
45487                */
45488
45489
45490               function baseDifference(array, values, iteratee, comparator) {
45491                 var index = -1,
45492                     includes = arrayIncludes,
45493                     isCommon = true,
45494                     length = array.length,
45495                     result = [],
45496                     valuesLength = values.length;
45497
45498                 if (!length) {
45499                   return result;
45500                 }
45501
45502                 if (iteratee) {
45503                   values = arrayMap(values, baseUnary(iteratee));
45504                 }
45505
45506                 if (comparator) {
45507                   includes = arrayIncludesWith;
45508                   isCommon = false;
45509                 } else if (values.length >= LARGE_ARRAY_SIZE) {
45510                   includes = cacheHas;
45511                   isCommon = false;
45512                   values = new SetCache(values);
45513                 }
45514
45515                 outer: while (++index < length) {
45516                   var value = array[index],
45517                       computed = iteratee == null ? value : iteratee(value);
45518                   value = comparator || value !== 0 ? value : 0;
45519
45520                   if (isCommon && computed === computed) {
45521                     var valuesIndex = valuesLength;
45522
45523                     while (valuesIndex--) {
45524                       if (values[valuesIndex] === computed) {
45525                         continue outer;
45526                       }
45527                     }
45528
45529                     result.push(value);
45530                   } else if (!includes(values, computed, comparator)) {
45531                     result.push(value);
45532                   }
45533                 }
45534
45535                 return result;
45536               }
45537               /**
45538                * The base implementation of `_.forEach` without support for iteratee shorthands.
45539                *
45540                * @private
45541                * @param {Array|Object} collection The collection to iterate over.
45542                * @param {Function} iteratee The function invoked per iteration.
45543                * @returns {Array|Object} Returns `collection`.
45544                */
45545
45546
45547               var baseEach = createBaseEach(baseForOwn);
45548               /**
45549                * The base implementation of `_.forEachRight` without support for iteratee shorthands.
45550                *
45551                * @private
45552                * @param {Array|Object} collection The collection to iterate over.
45553                * @param {Function} iteratee The function invoked per iteration.
45554                * @returns {Array|Object} Returns `collection`.
45555                */
45556
45557               var baseEachRight = createBaseEach(baseForOwnRight, true);
45558               /**
45559                * The base implementation of `_.every` without support for iteratee shorthands.
45560                *
45561                * @private
45562                * @param {Array|Object} collection The collection to iterate over.
45563                * @param {Function} predicate The function invoked per iteration.
45564                * @returns {boolean} Returns `true` if all elements pass the predicate check,
45565                *  else `false`
45566                */
45567
45568               function baseEvery(collection, predicate) {
45569                 var result = true;
45570                 baseEach(collection, function (value, index, collection) {
45571                   result = !!predicate(value, index, collection);
45572                   return result;
45573                 });
45574                 return result;
45575               }
45576               /**
45577                * The base implementation of methods like `_.max` and `_.min` which accepts a
45578                * `comparator` to determine the extremum value.
45579                *
45580                * @private
45581                * @param {Array} array The array to iterate over.
45582                * @param {Function} iteratee The iteratee invoked per iteration.
45583                * @param {Function} comparator The comparator used to compare values.
45584                * @returns {*} Returns the extremum value.
45585                */
45586
45587
45588               function baseExtremum(array, iteratee, comparator) {
45589                 var index = -1,
45590                     length = array.length;
45591
45592                 while (++index < length) {
45593                   var value = array[index],
45594                       current = iteratee(value);
45595
45596                   if (current != null && (computed === undefined$1 ? current === current && !isSymbol(current) : comparator(current, computed))) {
45597                     var computed = current,
45598                         result = value;
45599                   }
45600                 }
45601
45602                 return result;
45603               }
45604               /**
45605                * The base implementation of `_.fill` without an iteratee call guard.
45606                *
45607                * @private
45608                * @param {Array} array The array to fill.
45609                * @param {*} value The value to fill `array` with.
45610                * @param {number} [start=0] The start position.
45611                * @param {number} [end=array.length] The end position.
45612                * @returns {Array} Returns `array`.
45613                */
45614
45615
45616               function baseFill(array, value, start, end) {
45617                 var length = array.length;
45618                 start = toInteger(start);
45619
45620                 if (start < 0) {
45621                   start = -start > length ? 0 : length + start;
45622                 }
45623
45624                 end = end === undefined$1 || end > length ? length : toInteger(end);
45625
45626                 if (end < 0) {
45627                   end += length;
45628                 }
45629
45630                 end = start > end ? 0 : toLength(end);
45631
45632                 while (start < end) {
45633                   array[start++] = value;
45634                 }
45635
45636                 return array;
45637               }
45638               /**
45639                * The base implementation of `_.filter` without support for iteratee shorthands.
45640                *
45641                * @private
45642                * @param {Array|Object} collection The collection to iterate over.
45643                * @param {Function} predicate The function invoked per iteration.
45644                * @returns {Array} Returns the new filtered array.
45645                */
45646
45647
45648               function baseFilter(collection, predicate) {
45649                 var result = [];
45650                 baseEach(collection, function (value, index, collection) {
45651                   if (predicate(value, index, collection)) {
45652                     result.push(value);
45653                   }
45654                 });
45655                 return result;
45656               }
45657               /**
45658                * The base implementation of `_.flatten` with support for restricting flattening.
45659                *
45660                * @private
45661                * @param {Array} array The array to flatten.
45662                * @param {number} depth The maximum recursion depth.
45663                * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
45664                * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
45665                * @param {Array} [result=[]] The initial result value.
45666                * @returns {Array} Returns the new flattened array.
45667                */
45668
45669
45670               function baseFlatten(array, depth, predicate, isStrict, result) {
45671                 var index = -1,
45672                     length = array.length;
45673                 predicate || (predicate = isFlattenable);
45674                 result || (result = []);
45675
45676                 while (++index < length) {
45677                   var value = array[index];
45678
45679                   if (depth > 0 && predicate(value)) {
45680                     if (depth > 1) {
45681                       // Recursively flatten arrays (susceptible to call stack limits).
45682                       baseFlatten(value, depth - 1, predicate, isStrict, result);
45683                     } else {
45684                       arrayPush(result, value);
45685                     }
45686                   } else if (!isStrict) {
45687                     result[result.length] = value;
45688                   }
45689                 }
45690
45691                 return result;
45692               }
45693               /**
45694                * The base implementation of `baseForOwn` which iterates over `object`
45695                * properties returned by `keysFunc` and invokes `iteratee` for each property.
45696                * Iteratee functions may exit iteration early by explicitly returning `false`.
45697                *
45698                * @private
45699                * @param {Object} object The object to iterate over.
45700                * @param {Function} iteratee The function invoked per iteration.
45701                * @param {Function} keysFunc The function to get the keys of `object`.
45702                * @returns {Object} Returns `object`.
45703                */
45704
45705
45706               var baseFor = createBaseFor();
45707               /**
45708                * This function is like `baseFor` except that it iterates over properties
45709                * in the opposite order.
45710                *
45711                * @private
45712                * @param {Object} object The object to iterate over.
45713                * @param {Function} iteratee The function invoked per iteration.
45714                * @param {Function} keysFunc The function to get the keys of `object`.
45715                * @returns {Object} Returns `object`.
45716                */
45717
45718               var baseForRight = createBaseFor(true);
45719               /**
45720                * The base implementation of `_.forOwn` without support for iteratee shorthands.
45721                *
45722                * @private
45723                * @param {Object} object The object to iterate over.
45724                * @param {Function} iteratee The function invoked per iteration.
45725                * @returns {Object} Returns `object`.
45726                */
45727
45728               function baseForOwn(object, iteratee) {
45729                 return object && baseFor(object, iteratee, keys);
45730               }
45731               /**
45732                * The base implementation of `_.forOwnRight` without support for iteratee shorthands.
45733                *
45734                * @private
45735                * @param {Object} object The object to iterate over.
45736                * @param {Function} iteratee The function invoked per iteration.
45737                * @returns {Object} Returns `object`.
45738                */
45739
45740
45741               function baseForOwnRight(object, iteratee) {
45742                 return object && baseForRight(object, iteratee, keys);
45743               }
45744               /**
45745                * The base implementation of `_.functions` which creates an array of
45746                * `object` function property names filtered from `props`.
45747                *
45748                * @private
45749                * @param {Object} object The object to inspect.
45750                * @param {Array} props The property names to filter.
45751                * @returns {Array} Returns the function names.
45752                */
45753
45754
45755               function baseFunctions(object, props) {
45756                 return arrayFilter(props, function (key) {
45757                   return isFunction(object[key]);
45758                 });
45759               }
45760               /**
45761                * The base implementation of `_.get` without support for default values.
45762                *
45763                * @private
45764                * @param {Object} object The object to query.
45765                * @param {Array|string} path The path of the property to get.
45766                * @returns {*} Returns the resolved value.
45767                */
45768
45769
45770               function baseGet(object, path) {
45771                 path = castPath(path, object);
45772                 var index = 0,
45773                     length = path.length;
45774
45775                 while (object != null && index < length) {
45776                   object = object[toKey(path[index++])];
45777                 }
45778
45779                 return index && index == length ? object : undefined$1;
45780               }
45781               /**
45782                * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
45783                * `keysFunc` and `symbolsFunc` to get the enumerable property names and
45784                * symbols of `object`.
45785                *
45786                * @private
45787                * @param {Object} object The object to query.
45788                * @param {Function} keysFunc The function to get the keys of `object`.
45789                * @param {Function} symbolsFunc The function to get the symbols of `object`.
45790                * @returns {Array} Returns the array of property names and symbols.
45791                */
45792
45793
45794               function baseGetAllKeys(object, keysFunc, symbolsFunc) {
45795                 var result = keysFunc(object);
45796                 return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
45797               }
45798               /**
45799                * The base implementation of `getTag` without fallbacks for buggy environments.
45800                *
45801                * @private
45802                * @param {*} value The value to query.
45803                * @returns {string} Returns the `toStringTag`.
45804                */
45805
45806
45807               function baseGetTag(value) {
45808                 if (value == null) {
45809                   return value === undefined$1 ? undefinedTag : nullTag;
45810                 }
45811
45812                 return symToStringTag && symToStringTag in Object(value) ? getRawTag(value) : objectToString(value);
45813               }
45814               /**
45815                * The base implementation of `_.gt` which doesn't coerce arguments.
45816                *
45817                * @private
45818                * @param {*} value The value to compare.
45819                * @param {*} other The other value to compare.
45820                * @returns {boolean} Returns `true` if `value` is greater than `other`,
45821                *  else `false`.
45822                */
45823
45824
45825               function baseGt(value, other) {
45826                 return value > other;
45827               }
45828               /**
45829                * The base implementation of `_.has` without support for deep paths.
45830                *
45831                * @private
45832                * @param {Object} [object] The object to query.
45833                * @param {Array|string} key The key to check.
45834                * @returns {boolean} Returns `true` if `key` exists, else `false`.
45835                */
45836
45837
45838               function baseHas(object, key) {
45839                 return object != null && hasOwnProperty.call(object, key);
45840               }
45841               /**
45842                * The base implementation of `_.hasIn` without support for deep paths.
45843                *
45844                * @private
45845                * @param {Object} [object] The object to query.
45846                * @param {Array|string} key The key to check.
45847                * @returns {boolean} Returns `true` if `key` exists, else `false`.
45848                */
45849
45850
45851               function baseHasIn(object, key) {
45852                 return object != null && key in Object(object);
45853               }
45854               /**
45855                * The base implementation of `_.inRange` which doesn't coerce arguments.
45856                *
45857                * @private
45858                * @param {number} number The number to check.
45859                * @param {number} start The start of the range.
45860                * @param {number} end The end of the range.
45861                * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
45862                */
45863
45864
45865               function baseInRange(number, start, end) {
45866                 return number >= nativeMin(start, end) && number < nativeMax(start, end);
45867               }
45868               /**
45869                * The base implementation of methods like `_.intersection`, without support
45870                * for iteratee shorthands, that accepts an array of arrays to inspect.
45871                *
45872                * @private
45873                * @param {Array} arrays The arrays to inspect.
45874                * @param {Function} [iteratee] The iteratee invoked per element.
45875                * @param {Function} [comparator] The comparator invoked per element.
45876                * @returns {Array} Returns the new array of shared values.
45877                */
45878
45879
45880               function baseIntersection(arrays, iteratee, comparator) {
45881                 var includes = comparator ? arrayIncludesWith : arrayIncludes,
45882                     length = arrays[0].length,
45883                     othLength = arrays.length,
45884                     othIndex = othLength,
45885                     caches = Array(othLength),
45886                     maxLength = Infinity,
45887                     result = [];
45888
45889                 while (othIndex--) {
45890                   var array = arrays[othIndex];
45891
45892                   if (othIndex && iteratee) {
45893                     array = arrayMap(array, baseUnary(iteratee));
45894                   }
45895
45896                   maxLength = nativeMin(array.length, maxLength);
45897                   caches[othIndex] = !comparator && (iteratee || length >= 120 && array.length >= 120) ? new SetCache(othIndex && array) : undefined$1;
45898                 }
45899
45900                 array = arrays[0];
45901                 var index = -1,
45902                     seen = caches[0];
45903
45904                 outer: while (++index < length && result.length < maxLength) {
45905                   var value = array[index],
45906                       computed = iteratee ? iteratee(value) : value;
45907                   value = comparator || value !== 0 ? value : 0;
45908
45909                   if (!(seen ? cacheHas(seen, computed) : includes(result, computed, comparator))) {
45910                     othIndex = othLength;
45911
45912                     while (--othIndex) {
45913                       var cache = caches[othIndex];
45914
45915                       if (!(cache ? cacheHas(cache, computed) : includes(arrays[othIndex], computed, comparator))) {
45916                         continue outer;
45917                       }
45918                     }
45919
45920                     if (seen) {
45921                       seen.push(computed);
45922                     }
45923
45924                     result.push(value);
45925                   }
45926                 }
45927
45928                 return result;
45929               }
45930               /**
45931                * The base implementation of `_.invert` and `_.invertBy` which inverts
45932                * `object` with values transformed by `iteratee` and set by `setter`.
45933                *
45934                * @private
45935                * @param {Object} object The object to iterate over.
45936                * @param {Function} setter The function to set `accumulator` values.
45937                * @param {Function} iteratee The iteratee to transform values.
45938                * @param {Object} accumulator The initial inverted object.
45939                * @returns {Function} Returns `accumulator`.
45940                */
45941
45942
45943               function baseInverter(object, setter, iteratee, accumulator) {
45944                 baseForOwn(object, function (value, key, object) {
45945                   setter(accumulator, iteratee(value), key, object);
45946                 });
45947                 return accumulator;
45948               }
45949               /**
45950                * The base implementation of `_.invoke` without support for individual
45951                * method arguments.
45952                *
45953                * @private
45954                * @param {Object} object The object to query.
45955                * @param {Array|string} path The path of the method to invoke.
45956                * @param {Array} args The arguments to invoke the method with.
45957                * @returns {*} Returns the result of the invoked method.
45958                */
45959
45960
45961               function baseInvoke(object, path, args) {
45962                 path = castPath(path, object);
45963                 object = parent(object, path);
45964                 var func = object == null ? object : object[toKey(last(path))];
45965                 return func == null ? undefined$1 : apply(func, object, args);
45966               }
45967               /**
45968                * The base implementation of `_.isArguments`.
45969                *
45970                * @private
45971                * @param {*} value The value to check.
45972                * @returns {boolean} Returns `true` if `value` is an `arguments` object,
45973                */
45974
45975
45976               function baseIsArguments(value) {
45977                 return isObjectLike(value) && baseGetTag(value) == argsTag;
45978               }
45979               /**
45980                * The base implementation of `_.isArrayBuffer` without Node.js optimizations.
45981                *
45982                * @private
45983                * @param {*} value The value to check.
45984                * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
45985                */
45986
45987
45988               function baseIsArrayBuffer(value) {
45989                 return isObjectLike(value) && baseGetTag(value) == arrayBufferTag;
45990               }
45991               /**
45992                * The base implementation of `_.isDate` without Node.js optimizations.
45993                *
45994                * @private
45995                * @param {*} value The value to check.
45996                * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
45997                */
45998
45999
46000               function baseIsDate(value) {
46001                 return isObjectLike(value) && baseGetTag(value) == dateTag;
46002               }
46003               /**
46004                * The base implementation of `_.isEqual` which supports partial comparisons
46005                * and tracks traversed objects.
46006                *
46007                * @private
46008                * @param {*} value The value to compare.
46009                * @param {*} other The other value to compare.
46010                * @param {boolean} bitmask The bitmask flags.
46011                *  1 - Unordered comparison
46012                *  2 - Partial comparison
46013                * @param {Function} [customizer] The function to customize comparisons.
46014                * @param {Object} [stack] Tracks traversed `value` and `other` objects.
46015                * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
46016                */
46017
46018
46019               function baseIsEqual(value, other, bitmask, customizer, stack) {
46020                 if (value === other) {
46021                   return true;
46022                 }
46023
46024                 if (value == null || other == null || !isObjectLike(value) && !isObjectLike(other)) {
46025                   return value !== value && other !== other;
46026                 }
46027
46028                 return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
46029               }
46030               /**
46031                * A specialized version of `baseIsEqual` for arrays and objects which performs
46032                * deep comparisons and tracks traversed objects enabling objects with circular
46033                * references to be compared.
46034                *
46035                * @private
46036                * @param {Object} object The object to compare.
46037                * @param {Object} other The other object to compare.
46038                * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
46039                * @param {Function} customizer The function to customize comparisons.
46040                * @param {Function} equalFunc The function to determine equivalents of values.
46041                * @param {Object} [stack] Tracks traversed `object` and `other` objects.
46042                * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
46043                */
46044
46045
46046               function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
46047                 var objIsArr = isArray(object),
46048                     othIsArr = isArray(other),
46049                     objTag = objIsArr ? arrayTag : getTag(object),
46050                     othTag = othIsArr ? arrayTag : getTag(other);
46051                 objTag = objTag == argsTag ? objectTag : objTag;
46052                 othTag = othTag == argsTag ? objectTag : othTag;
46053                 var objIsObj = objTag == objectTag,
46054                     othIsObj = othTag == objectTag,
46055                     isSameTag = objTag == othTag;
46056
46057                 if (isSameTag && isBuffer(object)) {
46058                   if (!isBuffer(other)) {
46059                     return false;
46060                   }
46061
46062                   objIsArr = true;
46063                   objIsObj = false;
46064                 }
46065
46066                 if (isSameTag && !objIsObj) {
46067                   stack || (stack = new Stack());
46068                   return objIsArr || isTypedArray(object) ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
46069                 }
46070
46071                 if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
46072                   var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
46073                       othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
46074
46075                   if (objIsWrapped || othIsWrapped) {
46076                     var objUnwrapped = objIsWrapped ? object.value() : object,
46077                         othUnwrapped = othIsWrapped ? other.value() : other;
46078                     stack || (stack = new Stack());
46079                     return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
46080                   }
46081                 }
46082
46083                 if (!isSameTag) {
46084                   return false;
46085                 }
46086
46087                 stack || (stack = new Stack());
46088                 return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
46089               }
46090               /**
46091                * The base implementation of `_.isMap` without Node.js optimizations.
46092                *
46093                * @private
46094                * @param {*} value The value to check.
46095                * @returns {boolean} Returns `true` if `value` is a map, else `false`.
46096                */
46097
46098
46099               function baseIsMap(value) {
46100                 return isObjectLike(value) && getTag(value) == mapTag;
46101               }
46102               /**
46103                * The base implementation of `_.isMatch` without support for iteratee shorthands.
46104                *
46105                * @private
46106                * @param {Object} object The object to inspect.
46107                * @param {Object} source The object of property values to match.
46108                * @param {Array} matchData The property names, values, and compare flags to match.
46109                * @param {Function} [customizer] The function to customize comparisons.
46110                * @returns {boolean} Returns `true` if `object` is a match, else `false`.
46111                */
46112
46113
46114               function baseIsMatch(object, source, matchData, customizer) {
46115                 var index = matchData.length,
46116                     length = index,
46117                     noCustomizer = !customizer;
46118
46119                 if (object == null) {
46120                   return !length;
46121                 }
46122
46123                 object = Object(object);
46124
46125                 while (index--) {
46126                   var data = matchData[index];
46127
46128                   if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) {
46129                     return false;
46130                   }
46131                 }
46132
46133                 while (++index < length) {
46134                   data = matchData[index];
46135                   var key = data[0],
46136                       objValue = object[key],
46137                       srcValue = data[1];
46138
46139                   if (noCustomizer && data[2]) {
46140                     if (objValue === undefined$1 && !(key in object)) {
46141                       return false;
46142                     }
46143                   } else {
46144                     var stack = new Stack();
46145
46146                     if (customizer) {
46147                       var result = customizer(objValue, srcValue, key, object, source, stack);
46148                     }
46149
46150                     if (!(result === undefined$1 ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack) : result)) {
46151                       return false;
46152                     }
46153                   }
46154                 }
46155
46156                 return true;
46157               }
46158               /**
46159                * The base implementation of `_.isNative` without bad shim checks.
46160                *
46161                * @private
46162                * @param {*} value The value to check.
46163                * @returns {boolean} Returns `true` if `value` is a native function,
46164                *  else `false`.
46165                */
46166
46167
46168               function baseIsNative(value) {
46169                 if (!isObject(value) || isMasked(value)) {
46170                   return false;
46171                 }
46172
46173                 var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
46174                 return pattern.test(toSource(value));
46175               }
46176               /**
46177                * The base implementation of `_.isRegExp` without Node.js optimizations.
46178                *
46179                * @private
46180                * @param {*} value The value to check.
46181                * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
46182                */
46183
46184
46185               function baseIsRegExp(value) {
46186                 return isObjectLike(value) && baseGetTag(value) == regexpTag;
46187               }
46188               /**
46189                * The base implementation of `_.isSet` without Node.js optimizations.
46190                *
46191                * @private
46192                * @param {*} value The value to check.
46193                * @returns {boolean} Returns `true` if `value` is a set, else `false`.
46194                */
46195
46196
46197               function baseIsSet(value) {
46198                 return isObjectLike(value) && getTag(value) == setTag;
46199               }
46200               /**
46201                * The base implementation of `_.isTypedArray` without Node.js optimizations.
46202                *
46203                * @private
46204                * @param {*} value The value to check.
46205                * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
46206                */
46207
46208
46209               function baseIsTypedArray(value) {
46210                 return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
46211               }
46212               /**
46213                * The base implementation of `_.iteratee`.
46214                *
46215                * @private
46216                * @param {*} [value=_.identity] The value to convert to an iteratee.
46217                * @returns {Function} Returns the iteratee.
46218                */
46219
46220
46221               function baseIteratee(value) {
46222                 // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
46223                 // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
46224                 if (typeof value == 'function') {
46225                   return value;
46226                 }
46227
46228                 if (value == null) {
46229                   return identity;
46230                 }
46231
46232                 if (_typeof(value) == 'object') {
46233                   return isArray(value) ? baseMatchesProperty(value[0], value[1]) : baseMatches(value);
46234                 }
46235
46236                 return property(value);
46237               }
46238               /**
46239                * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
46240                *
46241                * @private
46242                * @param {Object} object The object to query.
46243                * @returns {Array} Returns the array of property names.
46244                */
46245
46246
46247               function baseKeys(object) {
46248                 if (!isPrototype(object)) {
46249                   return nativeKeys(object);
46250                 }
46251
46252                 var result = [];
46253
46254                 for (var key in Object(object)) {
46255                   if (hasOwnProperty.call(object, key) && key != 'constructor') {
46256                     result.push(key);
46257                   }
46258                 }
46259
46260                 return result;
46261               }
46262               /**
46263                * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
46264                *
46265                * @private
46266                * @param {Object} object The object to query.
46267                * @returns {Array} Returns the array of property names.
46268                */
46269
46270
46271               function baseKeysIn(object) {
46272                 if (!isObject(object)) {
46273                   return nativeKeysIn(object);
46274                 }
46275
46276                 var isProto = isPrototype(object),
46277                     result = [];
46278
46279                 for (var key in object) {
46280                   if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
46281                     result.push(key);
46282                   }
46283                 }
46284
46285                 return result;
46286               }
46287               /**
46288                * The base implementation of `_.lt` which doesn't coerce arguments.
46289                *
46290                * @private
46291                * @param {*} value The value to compare.
46292                * @param {*} other The other value to compare.
46293                * @returns {boolean} Returns `true` if `value` is less than `other`,
46294                *  else `false`.
46295                */
46296
46297
46298               function baseLt(value, other) {
46299                 return value < other;
46300               }
46301               /**
46302                * The base implementation of `_.map` without support for iteratee shorthands.
46303                *
46304                * @private
46305                * @param {Array|Object} collection The collection to iterate over.
46306                * @param {Function} iteratee The function invoked per iteration.
46307                * @returns {Array} Returns the new mapped array.
46308                */
46309
46310
46311               function baseMap(collection, iteratee) {
46312                 var index = -1,
46313                     result = isArrayLike(collection) ? Array(collection.length) : [];
46314                 baseEach(collection, function (value, key, collection) {
46315                   result[++index] = iteratee(value, key, collection);
46316                 });
46317                 return result;
46318               }
46319               /**
46320                * The base implementation of `_.matches` which doesn't clone `source`.
46321                *
46322                * @private
46323                * @param {Object} source The object of property values to match.
46324                * @returns {Function} Returns the new spec function.
46325                */
46326
46327
46328               function baseMatches(source) {
46329                 var matchData = getMatchData(source);
46330
46331                 if (matchData.length == 1 && matchData[0][2]) {
46332                   return matchesStrictComparable(matchData[0][0], matchData[0][1]);
46333                 }
46334
46335                 return function (object) {
46336                   return object === source || baseIsMatch(object, source, matchData);
46337                 };
46338               }
46339               /**
46340                * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
46341                *
46342                * @private
46343                * @param {string} path The path of the property to get.
46344                * @param {*} srcValue The value to match.
46345                * @returns {Function} Returns the new spec function.
46346                */
46347
46348
46349               function baseMatchesProperty(path, srcValue) {
46350                 if (isKey(path) && isStrictComparable(srcValue)) {
46351                   return matchesStrictComparable(toKey(path), srcValue);
46352                 }
46353
46354                 return function (object) {
46355                   var objValue = get(object, path);
46356                   return objValue === undefined$1 && objValue === srcValue ? hasIn(object, path) : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
46357                 };
46358               }
46359               /**
46360                * The base implementation of `_.merge` without support for multiple sources.
46361                *
46362                * @private
46363                * @param {Object} object The destination object.
46364                * @param {Object} source The source object.
46365                * @param {number} srcIndex The index of `source`.
46366                * @param {Function} [customizer] The function to customize merged values.
46367                * @param {Object} [stack] Tracks traversed source values and their merged
46368                *  counterparts.
46369                */
46370
46371
46372               function baseMerge(object, source, srcIndex, customizer, stack) {
46373                 if (object === source) {
46374                   return;
46375                 }
46376
46377                 baseFor(source, function (srcValue, key) {
46378                   stack || (stack = new Stack());
46379
46380                   if (isObject(srcValue)) {
46381                     baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
46382                   } else {
46383                     var newValue = customizer ? customizer(safeGet(object, key), srcValue, key + '', object, source, stack) : undefined$1;
46384
46385                     if (newValue === undefined$1) {
46386                       newValue = srcValue;
46387                     }
46388
46389                     assignMergeValue(object, key, newValue);
46390                   }
46391                 }, keysIn);
46392               }
46393               /**
46394                * A specialized version of `baseMerge` for arrays and objects which performs
46395                * deep merges and tracks traversed objects enabling objects with circular
46396                * references to be merged.
46397                *
46398                * @private
46399                * @param {Object} object The destination object.
46400                * @param {Object} source The source object.
46401                * @param {string} key The key of the value to merge.
46402                * @param {number} srcIndex The index of `source`.
46403                * @param {Function} mergeFunc The function to merge values.
46404                * @param {Function} [customizer] The function to customize assigned values.
46405                * @param {Object} [stack] Tracks traversed source values and their merged
46406                *  counterparts.
46407                */
46408
46409
46410               function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
46411                 var objValue = safeGet(object, key),
46412                     srcValue = safeGet(source, key),
46413                     stacked = stack.get(srcValue);
46414
46415                 if (stacked) {
46416                   assignMergeValue(object, key, stacked);
46417                   return;
46418                 }
46419
46420                 var newValue = customizer ? customizer(objValue, srcValue, key + '', object, source, stack) : undefined$1;
46421                 var isCommon = newValue === undefined$1;
46422
46423                 if (isCommon) {
46424                   var isArr = isArray(srcValue),
46425                       isBuff = !isArr && isBuffer(srcValue),
46426                       isTyped = !isArr && !isBuff && isTypedArray(srcValue);
46427                   newValue = srcValue;
46428
46429                   if (isArr || isBuff || isTyped) {
46430                     if (isArray(objValue)) {
46431                       newValue = objValue;
46432                     } else if (isArrayLikeObject(objValue)) {
46433                       newValue = copyArray(objValue);
46434                     } else if (isBuff) {
46435                       isCommon = false;
46436                       newValue = cloneBuffer(srcValue, true);
46437                     } else if (isTyped) {
46438                       isCommon = false;
46439                       newValue = cloneTypedArray(srcValue, true);
46440                     } else {
46441                       newValue = [];
46442                     }
46443                   } else if (isPlainObject(srcValue) || isArguments(srcValue)) {
46444                     newValue = objValue;
46445
46446                     if (isArguments(objValue)) {
46447                       newValue = toPlainObject(objValue);
46448                     } else if (!isObject(objValue) || isFunction(objValue)) {
46449                       newValue = initCloneObject(srcValue);
46450                     }
46451                   } else {
46452                     isCommon = false;
46453                   }
46454                 }
46455
46456                 if (isCommon) {
46457                   // Recursively merge objects and arrays (susceptible to call stack limits).
46458                   stack.set(srcValue, newValue);
46459                   mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
46460                   stack['delete'](srcValue);
46461                 }
46462
46463                 assignMergeValue(object, key, newValue);
46464               }
46465               /**
46466                * The base implementation of `_.nth` which doesn't coerce arguments.
46467                *
46468                * @private
46469                * @param {Array} array The array to query.
46470                * @param {number} n The index of the element to return.
46471                * @returns {*} Returns the nth element of `array`.
46472                */
46473
46474
46475               function baseNth(array, n) {
46476                 var length = array.length;
46477
46478                 if (!length) {
46479                   return;
46480                 }
46481
46482                 n += n < 0 ? length : 0;
46483                 return isIndex(n, length) ? array[n] : undefined$1;
46484               }
46485               /**
46486                * The base implementation of `_.orderBy` without param guards.
46487                *
46488                * @private
46489                * @param {Array|Object} collection The collection to iterate over.
46490                * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
46491                * @param {string[]} orders The sort orders of `iteratees`.
46492                * @returns {Array} Returns the new sorted array.
46493                */
46494
46495
46496               function baseOrderBy(collection, iteratees, orders) {
46497                 if (iteratees.length) {
46498                   iteratees = arrayMap(iteratees, function (iteratee) {
46499                     if (isArray(iteratee)) {
46500                       return function (value) {
46501                         return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee);
46502                       };
46503                     }
46504
46505                     return iteratee;
46506                   });
46507                 } else {
46508                   iteratees = [identity];
46509                 }
46510
46511                 var index = -1;
46512                 iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
46513                 var result = baseMap(collection, function (value, key, collection) {
46514                   var criteria = arrayMap(iteratees, function (iteratee) {
46515                     return iteratee(value);
46516                   });
46517                   return {
46518                     'criteria': criteria,
46519                     'index': ++index,
46520                     'value': value
46521                   };
46522                 });
46523                 return baseSortBy(result, function (object, other) {
46524                   return compareMultiple(object, other, orders);
46525                 });
46526               }
46527               /**
46528                * The base implementation of `_.pick` without support for individual
46529                * property identifiers.
46530                *
46531                * @private
46532                * @param {Object} object The source object.
46533                * @param {string[]} paths The property paths to pick.
46534                * @returns {Object} Returns the new object.
46535                */
46536
46537
46538               function basePick(object, paths) {
46539                 return basePickBy(object, paths, function (value, path) {
46540                   return hasIn(object, path);
46541                 });
46542               }
46543               /**
46544                * The base implementation of  `_.pickBy` without support for iteratee shorthands.
46545                *
46546                * @private
46547                * @param {Object} object The source object.
46548                * @param {string[]} paths The property paths to pick.
46549                * @param {Function} predicate The function invoked per property.
46550                * @returns {Object} Returns the new object.
46551                */
46552
46553
46554               function basePickBy(object, paths, predicate) {
46555                 var index = -1,
46556                     length = paths.length,
46557                     result = {};
46558
46559                 while (++index < length) {
46560                   var path = paths[index],
46561                       value = baseGet(object, path);
46562
46563                   if (predicate(value, path)) {
46564                     baseSet(result, castPath(path, object), value);
46565                   }
46566                 }
46567
46568                 return result;
46569               }
46570               /**
46571                * A specialized version of `baseProperty` which supports deep paths.
46572                *
46573                * @private
46574                * @param {Array|string} path The path of the property to get.
46575                * @returns {Function} Returns the new accessor function.
46576                */
46577
46578
46579               function basePropertyDeep(path) {
46580                 return function (object) {
46581                   return baseGet(object, path);
46582                 };
46583               }
46584               /**
46585                * The base implementation of `_.pullAllBy` without support for iteratee
46586                * shorthands.
46587                *
46588                * @private
46589                * @param {Array} array The array to modify.
46590                * @param {Array} values The values to remove.
46591                * @param {Function} [iteratee] The iteratee invoked per element.
46592                * @param {Function} [comparator] The comparator invoked per element.
46593                * @returns {Array} Returns `array`.
46594                */
46595
46596
46597               function basePullAll(array, values, iteratee, comparator) {
46598                 var indexOf = comparator ? baseIndexOfWith : baseIndexOf,
46599                     index = -1,
46600                     length = values.length,
46601                     seen = array;
46602
46603                 if (array === values) {
46604                   values = copyArray(values);
46605                 }
46606
46607                 if (iteratee) {
46608                   seen = arrayMap(array, baseUnary(iteratee));
46609                 }
46610
46611                 while (++index < length) {
46612                   var fromIndex = 0,
46613                       value = values[index],
46614                       computed = iteratee ? iteratee(value) : value;
46615
46616                   while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {
46617                     if (seen !== array) {
46618                       splice.call(seen, fromIndex, 1);
46619                     }
46620
46621                     splice.call(array, fromIndex, 1);
46622                   }
46623                 }
46624
46625                 return array;
46626               }
46627               /**
46628                * The base implementation of `_.pullAt` without support for individual
46629                * indexes or capturing the removed elements.
46630                *
46631                * @private
46632                * @param {Array} array The array to modify.
46633                * @param {number[]} indexes The indexes of elements to remove.
46634                * @returns {Array} Returns `array`.
46635                */
46636
46637
46638               function basePullAt(array, indexes) {
46639                 var length = array ? indexes.length : 0,
46640                     lastIndex = length - 1;
46641
46642                 while (length--) {
46643                   var index = indexes[length];
46644
46645                   if (length == lastIndex || index !== previous) {
46646                     var previous = index;
46647
46648                     if (isIndex(index)) {
46649                       splice.call(array, index, 1);
46650                     } else {
46651                       baseUnset(array, index);
46652                     }
46653                   }
46654                 }
46655
46656                 return array;
46657               }
46658               /**
46659                * The base implementation of `_.random` without support for returning
46660                * floating-point numbers.
46661                *
46662                * @private
46663                * @param {number} lower The lower bound.
46664                * @param {number} upper The upper bound.
46665                * @returns {number} Returns the random number.
46666                */
46667
46668
46669               function baseRandom(lower, upper) {
46670                 return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
46671               }
46672               /**
46673                * The base implementation of `_.range` and `_.rangeRight` which doesn't
46674                * coerce arguments.
46675                *
46676                * @private
46677                * @param {number} start The start of the range.
46678                * @param {number} end The end of the range.
46679                * @param {number} step The value to increment or decrement by.
46680                * @param {boolean} [fromRight] Specify iterating from right to left.
46681                * @returns {Array} Returns the range of numbers.
46682                */
46683
46684
46685               function baseRange(start, end, step, fromRight) {
46686                 var index = -1,
46687                     length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
46688                     result = Array(length);
46689
46690                 while (length--) {
46691                   result[fromRight ? length : ++index] = start;
46692                   start += step;
46693                 }
46694
46695                 return result;
46696               }
46697               /**
46698                * The base implementation of `_.repeat` which doesn't coerce arguments.
46699                *
46700                * @private
46701                * @param {string} string The string to repeat.
46702                * @param {number} n The number of times to repeat the string.
46703                * @returns {string} Returns the repeated string.
46704                */
46705
46706
46707               function baseRepeat(string, n) {
46708                 var result = '';
46709
46710                 if (!string || n < 1 || n > MAX_SAFE_INTEGER) {
46711                   return result;
46712                 } // Leverage the exponentiation by squaring algorithm for a faster repeat.
46713                 // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.
46714
46715
46716                 do {
46717                   if (n % 2) {
46718                     result += string;
46719                   }
46720
46721                   n = nativeFloor(n / 2);
46722
46723                   if (n) {
46724                     string += string;
46725                   }
46726                 } while (n);
46727
46728                 return result;
46729               }
46730               /**
46731                * The base implementation of `_.rest` which doesn't validate or coerce arguments.
46732                *
46733                * @private
46734                * @param {Function} func The function to apply a rest parameter to.
46735                * @param {number} [start=func.length-1] The start position of the rest parameter.
46736                * @returns {Function} Returns the new function.
46737                */
46738
46739
46740               function baseRest(func, start) {
46741                 return setToString(overRest(func, start, identity), func + '');
46742               }
46743               /**
46744                * The base implementation of `_.sample`.
46745                *
46746                * @private
46747                * @param {Array|Object} collection The collection to sample.
46748                * @returns {*} Returns the random element.
46749                */
46750
46751
46752               function baseSample(collection) {
46753                 return arraySample(values(collection));
46754               }
46755               /**
46756                * The base implementation of `_.sampleSize` without param guards.
46757                *
46758                * @private
46759                * @param {Array|Object} collection The collection to sample.
46760                * @param {number} n The number of elements to sample.
46761                * @returns {Array} Returns the random elements.
46762                */
46763
46764
46765               function baseSampleSize(collection, n) {
46766                 var array = values(collection);
46767                 return shuffleSelf(array, baseClamp(n, 0, array.length));
46768               }
46769               /**
46770                * The base implementation of `_.set`.
46771                *
46772                * @private
46773                * @param {Object} object The object to modify.
46774                * @param {Array|string} path The path of the property to set.
46775                * @param {*} value The value to set.
46776                * @param {Function} [customizer] The function to customize path creation.
46777                * @returns {Object} Returns `object`.
46778                */
46779
46780
46781               function baseSet(object, path, value, customizer) {
46782                 if (!isObject(object)) {
46783                   return object;
46784                 }
46785
46786                 path = castPath(path, object);
46787                 var index = -1,
46788                     length = path.length,
46789                     lastIndex = length - 1,
46790                     nested = object;
46791
46792                 while (nested != null && ++index < length) {
46793                   var key = toKey(path[index]),
46794                       newValue = value;
46795
46796                   if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
46797                     return object;
46798                   }
46799
46800                   if (index != lastIndex) {
46801                     var objValue = nested[key];
46802                     newValue = customizer ? customizer(objValue, key, nested) : undefined$1;
46803
46804                     if (newValue === undefined$1) {
46805                       newValue = isObject(objValue) ? objValue : isIndex(path[index + 1]) ? [] : {};
46806                     }
46807                   }
46808
46809                   assignValue(nested, key, newValue);
46810                   nested = nested[key];
46811                 }
46812
46813                 return object;
46814               }
46815               /**
46816                * The base implementation of `setData` without support for hot loop shorting.
46817                *
46818                * @private
46819                * @param {Function} func The function to associate metadata with.
46820                * @param {*} data The metadata.
46821                * @returns {Function} Returns `func`.
46822                */
46823
46824
46825               var baseSetData = !metaMap ? identity : function (func, data) {
46826                 metaMap.set(func, data);
46827                 return func;
46828               };
46829               /**
46830                * The base implementation of `setToString` without support for hot loop shorting.
46831                *
46832                * @private
46833                * @param {Function} func The function to modify.
46834                * @param {Function} string The `toString` result.
46835                * @returns {Function} Returns `func`.
46836                */
46837
46838               var baseSetToString = !defineProperty ? identity : function (func, string) {
46839                 return defineProperty(func, 'toString', {
46840                   'configurable': true,
46841                   'enumerable': false,
46842                   'value': constant(string),
46843                   'writable': true
46844                 });
46845               };
46846               /**
46847                * The base implementation of `_.shuffle`.
46848                *
46849                * @private
46850                * @param {Array|Object} collection The collection to shuffle.
46851                * @returns {Array} Returns the new shuffled array.
46852                */
46853
46854               function baseShuffle(collection) {
46855                 return shuffleSelf(values(collection));
46856               }
46857               /**
46858                * The base implementation of `_.slice` without an iteratee call guard.
46859                *
46860                * @private
46861                * @param {Array} array The array to slice.
46862                * @param {number} [start=0] The start position.
46863                * @param {number} [end=array.length] The end position.
46864                * @returns {Array} Returns the slice of `array`.
46865                */
46866
46867
46868               function baseSlice(array, start, end) {
46869                 var index = -1,
46870                     length = array.length;
46871
46872                 if (start < 0) {
46873                   start = -start > length ? 0 : length + start;
46874                 }
46875
46876                 end = end > length ? length : end;
46877
46878                 if (end < 0) {
46879                   end += length;
46880                 }
46881
46882                 length = start > end ? 0 : end - start >>> 0;
46883                 start >>>= 0;
46884                 var result = Array(length);
46885
46886                 while (++index < length) {
46887                   result[index] = array[index + start];
46888                 }
46889
46890                 return result;
46891               }
46892               /**
46893                * The base implementation of `_.some` without support for iteratee shorthands.
46894                *
46895                * @private
46896                * @param {Array|Object} collection The collection to iterate over.
46897                * @param {Function} predicate The function invoked per iteration.
46898                * @returns {boolean} Returns `true` if any element passes the predicate check,
46899                *  else `false`.
46900                */
46901
46902
46903               function baseSome(collection, predicate) {
46904                 var result;
46905                 baseEach(collection, function (value, index, collection) {
46906                   result = predicate(value, index, collection);
46907                   return !result;
46908                 });
46909                 return !!result;
46910               }
46911               /**
46912                * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which
46913                * performs a binary search of `array` to determine the index at which `value`
46914                * should be inserted into `array` in order to maintain its sort order.
46915                *
46916                * @private
46917                * @param {Array} array The sorted array to inspect.
46918                * @param {*} value The value to evaluate.
46919                * @param {boolean} [retHighest] Specify returning the highest qualified index.
46920                * @returns {number} Returns the index at which `value` should be inserted
46921                *  into `array`.
46922                */
46923
46924
46925               function baseSortedIndex(array, value, retHighest) {
46926                 var low = 0,
46927                     high = array == null ? low : array.length;
46928
46929                 if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
46930                   while (low < high) {
46931                     var mid = low + high >>> 1,
46932                         computed = array[mid];
46933
46934                     if (computed !== null && !isSymbol(computed) && (retHighest ? computed <= value : computed < value)) {
46935                       low = mid + 1;
46936                     } else {
46937                       high = mid;
46938                     }
46939                   }
46940
46941                   return high;
46942                 }
46943
46944                 return baseSortedIndexBy(array, value, identity, retHighest);
46945               }
46946               /**
46947                * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy`
46948                * which invokes `iteratee` for `value` and each element of `array` to compute
46949                * their sort ranking. The iteratee is invoked with one argument; (value).
46950                *
46951                * @private
46952                * @param {Array} array The sorted array to inspect.
46953                * @param {*} value The value to evaluate.
46954                * @param {Function} iteratee The iteratee invoked per element.
46955                * @param {boolean} [retHighest] Specify returning the highest qualified index.
46956                * @returns {number} Returns the index at which `value` should be inserted
46957                *  into `array`.
46958                */
46959
46960
46961               function baseSortedIndexBy(array, value, iteratee, retHighest) {
46962                 var low = 0,
46963                     high = array == null ? 0 : array.length;
46964
46965                 if (high === 0) {
46966                   return 0;
46967                 }
46968
46969                 value = iteratee(value);
46970                 var valIsNaN = value !== value,
46971                     valIsNull = value === null,
46972                     valIsSymbol = isSymbol(value),
46973                     valIsUndefined = value === undefined$1;
46974
46975                 while (low < high) {
46976                   var mid = nativeFloor((low + high) / 2),
46977                       computed = iteratee(array[mid]),
46978                       othIsDefined = computed !== undefined$1,
46979                       othIsNull = computed === null,
46980                       othIsReflexive = computed === computed,
46981                       othIsSymbol = isSymbol(computed);
46982
46983                   if (valIsNaN) {
46984                     var setLow = retHighest || othIsReflexive;
46985                   } else if (valIsUndefined) {
46986                     setLow = othIsReflexive && (retHighest || othIsDefined);
46987                   } else if (valIsNull) {
46988                     setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull);
46989                   } else if (valIsSymbol) {
46990                     setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol);
46991                   } else if (othIsNull || othIsSymbol) {
46992                     setLow = false;
46993                   } else {
46994                     setLow = retHighest ? computed <= value : computed < value;
46995                   }
46996
46997                   if (setLow) {
46998                     low = mid + 1;
46999                   } else {
47000                     high = mid;
47001                   }
47002                 }
47003
47004                 return nativeMin(high, MAX_ARRAY_INDEX);
47005               }
47006               /**
47007                * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without
47008                * support for iteratee shorthands.
47009                *
47010                * @private
47011                * @param {Array} array The array to inspect.
47012                * @param {Function} [iteratee] The iteratee invoked per element.
47013                * @returns {Array} Returns the new duplicate free array.
47014                */
47015
47016
47017               function baseSortedUniq(array, iteratee) {
47018                 var index = -1,
47019                     length = array.length,
47020                     resIndex = 0,
47021                     result = [];
47022
47023                 while (++index < length) {
47024                   var value = array[index],
47025                       computed = iteratee ? iteratee(value) : value;
47026
47027                   if (!index || !eq(computed, seen)) {
47028                     var seen = computed;
47029                     result[resIndex++] = value === 0 ? 0 : value;
47030                   }
47031                 }
47032
47033                 return result;
47034               }
47035               /**
47036                * The base implementation of `_.toNumber` which doesn't ensure correct
47037                * conversions of binary, hexadecimal, or octal string values.
47038                *
47039                * @private
47040                * @param {*} value The value to process.
47041                * @returns {number} Returns the number.
47042                */
47043
47044
47045               function baseToNumber(value) {
47046                 if (typeof value == 'number') {
47047                   return value;
47048                 }
47049
47050                 if (isSymbol(value)) {
47051                   return NAN;
47052                 }
47053
47054                 return +value;
47055               }
47056               /**
47057                * The base implementation of `_.toString` which doesn't convert nullish
47058                * values to empty strings.
47059                *
47060                * @private
47061                * @param {*} value The value to process.
47062                * @returns {string} Returns the string.
47063                */
47064
47065
47066               function baseToString(value) {
47067                 // Exit early for strings to avoid a performance hit in some environments.
47068                 if (typeof value == 'string') {
47069                   return value;
47070                 }
47071
47072                 if (isArray(value)) {
47073                   // Recursively convert values (susceptible to call stack limits).
47074                   return arrayMap(value, baseToString) + '';
47075                 }
47076
47077                 if (isSymbol(value)) {
47078                   return symbolToString ? symbolToString.call(value) : '';
47079                 }
47080
47081                 var result = value + '';
47082                 return result == '0' && 1 / value == -INFINITY ? '-0' : result;
47083               }
47084               /**
47085                * The base implementation of `_.uniqBy` without support for iteratee shorthands.
47086                *
47087                * @private
47088                * @param {Array} array The array to inspect.
47089                * @param {Function} [iteratee] The iteratee invoked per element.
47090                * @param {Function} [comparator] The comparator invoked per element.
47091                * @returns {Array} Returns the new duplicate free array.
47092                */
47093
47094
47095               function baseUniq(array, iteratee, comparator) {
47096                 var index = -1,
47097                     includes = arrayIncludes,
47098                     length = array.length,
47099                     isCommon = true,
47100                     result = [],
47101                     seen = result;
47102
47103                 if (comparator) {
47104                   isCommon = false;
47105                   includes = arrayIncludesWith;
47106                 } else if (length >= LARGE_ARRAY_SIZE) {
47107                   var set = iteratee ? null : createSet(array);
47108
47109                   if (set) {
47110                     return setToArray(set);
47111                   }
47112
47113                   isCommon = false;
47114                   includes = cacheHas;
47115                   seen = new SetCache();
47116                 } else {
47117                   seen = iteratee ? [] : result;
47118                 }
47119
47120                 outer: while (++index < length) {
47121                   var value = array[index],
47122                       computed = iteratee ? iteratee(value) : value;
47123                   value = comparator || value !== 0 ? value : 0;
47124
47125                   if (isCommon && computed === computed) {
47126                     var seenIndex = seen.length;
47127
47128                     while (seenIndex--) {
47129                       if (seen[seenIndex] === computed) {
47130                         continue outer;
47131                       }
47132                     }
47133
47134                     if (iteratee) {
47135                       seen.push(computed);
47136                     }
47137
47138                     result.push(value);
47139                   } else if (!includes(seen, computed, comparator)) {
47140                     if (seen !== result) {
47141                       seen.push(computed);
47142                     }
47143
47144                     result.push(value);
47145                   }
47146                 }
47147
47148                 return result;
47149               }
47150               /**
47151                * The base implementation of `_.unset`.
47152                *
47153                * @private
47154                * @param {Object} object The object to modify.
47155                * @param {Array|string} path The property path to unset.
47156                * @returns {boolean} Returns `true` if the property is deleted, else `false`.
47157                */
47158
47159
47160               function baseUnset(object, path) {
47161                 path = castPath(path, object);
47162                 object = parent(object, path);
47163                 return object == null || delete object[toKey(last(path))];
47164               }
47165               /**
47166                * The base implementation of `_.update`.
47167                *
47168                * @private
47169                * @param {Object} object The object to modify.
47170                * @param {Array|string} path The path of the property to update.
47171                * @param {Function} updater The function to produce the updated value.
47172                * @param {Function} [customizer] The function to customize path creation.
47173                * @returns {Object} Returns `object`.
47174                */
47175
47176
47177               function baseUpdate(object, path, updater, customizer) {
47178                 return baseSet(object, path, updater(baseGet(object, path)), customizer);
47179               }
47180               /**
47181                * The base implementation of methods like `_.dropWhile` and `_.takeWhile`
47182                * without support for iteratee shorthands.
47183                *
47184                * @private
47185                * @param {Array} array The array to query.
47186                * @param {Function} predicate The function invoked per iteration.
47187                * @param {boolean} [isDrop] Specify dropping elements instead of taking them.
47188                * @param {boolean} [fromRight] Specify iterating from right to left.
47189                * @returns {Array} Returns the slice of `array`.
47190                */
47191
47192
47193               function baseWhile(array, predicate, isDrop, fromRight) {
47194                 var length = array.length,
47195                     index = fromRight ? length : -1;
47196
47197                 while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {}
47198
47199                 return isDrop ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length) : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index);
47200               }
47201               /**
47202                * The base implementation of `wrapperValue` which returns the result of
47203                * performing a sequence of actions on the unwrapped `value`, where each
47204                * successive action is supplied the return value of the previous.
47205                *
47206                * @private
47207                * @param {*} value The unwrapped value.
47208                * @param {Array} actions Actions to perform to resolve the unwrapped value.
47209                * @returns {*} Returns the resolved value.
47210                */
47211
47212
47213               function baseWrapperValue(value, actions) {
47214                 var result = value;
47215
47216                 if (result instanceof LazyWrapper) {
47217                   result = result.value();
47218                 }
47219
47220                 return arrayReduce(actions, function (result, action) {
47221                   return action.func.apply(action.thisArg, arrayPush([result], action.args));
47222                 }, result);
47223               }
47224               /**
47225                * The base implementation of methods like `_.xor`, without support for
47226                * iteratee shorthands, that accepts an array of arrays to inspect.
47227                *
47228                * @private
47229                * @param {Array} arrays The arrays to inspect.
47230                * @param {Function} [iteratee] The iteratee invoked per element.
47231                * @param {Function} [comparator] The comparator invoked per element.
47232                * @returns {Array} Returns the new array of values.
47233                */
47234
47235
47236               function baseXor(arrays, iteratee, comparator) {
47237                 var length = arrays.length;
47238
47239                 if (length < 2) {
47240                   return length ? baseUniq(arrays[0]) : [];
47241                 }
47242
47243                 var index = -1,
47244                     result = Array(length);
47245
47246                 while (++index < length) {
47247                   var array = arrays[index],
47248                       othIndex = -1;
47249
47250                   while (++othIndex < length) {
47251                     if (othIndex != index) {
47252                       result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator);
47253                     }
47254                   }
47255                 }
47256
47257                 return baseUniq(baseFlatten(result, 1), iteratee, comparator);
47258               }
47259               /**
47260                * This base implementation of `_.zipObject` which assigns values using `assignFunc`.
47261                *
47262                * @private
47263                * @param {Array} props The property identifiers.
47264                * @param {Array} values The property values.
47265                * @param {Function} assignFunc The function to assign values.
47266                * @returns {Object} Returns the new object.
47267                */
47268
47269
47270               function baseZipObject(props, values, assignFunc) {
47271                 var index = -1,
47272                     length = props.length,
47273                     valsLength = values.length,
47274                     result = {};
47275
47276                 while (++index < length) {
47277                   var value = index < valsLength ? values[index] : undefined$1;
47278                   assignFunc(result, props[index], value);
47279                 }
47280
47281                 return result;
47282               }
47283               /**
47284                * Casts `value` to an empty array if it's not an array like object.
47285                *
47286                * @private
47287                * @param {*} value The value to inspect.
47288                * @returns {Array|Object} Returns the cast array-like object.
47289                */
47290
47291
47292               function castArrayLikeObject(value) {
47293                 return isArrayLikeObject(value) ? value : [];
47294               }
47295               /**
47296                * Casts `value` to `identity` if it's not a function.
47297                *
47298                * @private
47299                * @param {*} value The value to inspect.
47300                * @returns {Function} Returns cast function.
47301                */
47302
47303
47304               function castFunction(value) {
47305                 return typeof value == 'function' ? value : identity;
47306               }
47307               /**
47308                * Casts `value` to a path array if it's not one.
47309                *
47310                * @private
47311                * @param {*} value The value to inspect.
47312                * @param {Object} [object] The object to query keys on.
47313                * @returns {Array} Returns the cast property path array.
47314                */
47315
47316
47317               function castPath(value, object) {
47318                 if (isArray(value)) {
47319                   return value;
47320                 }
47321
47322                 return isKey(value, object) ? [value] : stringToPath(toString(value));
47323               }
47324               /**
47325                * A `baseRest` alias which can be replaced with `identity` by module
47326                * replacement plugins.
47327                *
47328                * @private
47329                * @type {Function}
47330                * @param {Function} func The function to apply a rest parameter to.
47331                * @returns {Function} Returns the new function.
47332                */
47333
47334
47335               var castRest = baseRest;
47336               /**
47337                * Casts `array` to a slice if it's needed.
47338                *
47339                * @private
47340                * @param {Array} array The array to inspect.
47341                * @param {number} start The start position.
47342                * @param {number} [end=array.length] The end position.
47343                * @returns {Array} Returns the cast slice.
47344                */
47345
47346               function castSlice(array, start, end) {
47347                 var length = array.length;
47348                 end = end === undefined$1 ? length : end;
47349                 return !start && end >= length ? array : baseSlice(array, start, end);
47350               }
47351               /**
47352                * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout).
47353                *
47354                * @private
47355                * @param {number|Object} id The timer id or timeout object of the timer to clear.
47356                */
47357
47358
47359               var clearTimeout = ctxClearTimeout || function (id) {
47360                 return root.clearTimeout(id);
47361               };
47362               /**
47363                * Creates a clone of  `buffer`.
47364                *
47365                * @private
47366                * @param {Buffer} buffer The buffer to clone.
47367                * @param {boolean} [isDeep] Specify a deep clone.
47368                * @returns {Buffer} Returns the cloned buffer.
47369                */
47370
47371
47372               function cloneBuffer(buffer, isDeep) {
47373                 if (isDeep) {
47374                   return buffer.slice();
47375                 }
47376
47377                 var length = buffer.length,
47378                     result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);
47379                 buffer.copy(result);
47380                 return result;
47381               }
47382               /**
47383                * Creates a clone of `arrayBuffer`.
47384                *
47385                * @private
47386                * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
47387                * @returns {ArrayBuffer} Returns the cloned array buffer.
47388                */
47389
47390
47391               function cloneArrayBuffer(arrayBuffer) {
47392                 var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
47393                 new Uint8Array(result).set(new Uint8Array(arrayBuffer));
47394                 return result;
47395               }
47396               /**
47397                * Creates a clone of `dataView`.
47398                *
47399                * @private
47400                * @param {Object} dataView The data view to clone.
47401                * @param {boolean} [isDeep] Specify a deep clone.
47402                * @returns {Object} Returns the cloned data view.
47403                */
47404
47405
47406               function cloneDataView(dataView, isDeep) {
47407                 var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
47408                 return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
47409               }
47410               /**
47411                * Creates a clone of `regexp`.
47412                *
47413                * @private
47414                * @param {Object} regexp The regexp to clone.
47415                * @returns {Object} Returns the cloned regexp.
47416                */
47417
47418
47419               function cloneRegExp(regexp) {
47420                 var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
47421                 result.lastIndex = regexp.lastIndex;
47422                 return result;
47423               }
47424               /**
47425                * Creates a clone of the `symbol` object.
47426                *
47427                * @private
47428                * @param {Object} symbol The symbol object to clone.
47429                * @returns {Object} Returns the cloned symbol object.
47430                */
47431
47432
47433               function cloneSymbol(symbol) {
47434                 return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
47435               }
47436               /**
47437                * Creates a clone of `typedArray`.
47438                *
47439                * @private
47440                * @param {Object} typedArray The typed array to clone.
47441                * @param {boolean} [isDeep] Specify a deep clone.
47442                * @returns {Object} Returns the cloned typed array.
47443                */
47444
47445
47446               function cloneTypedArray(typedArray, isDeep) {
47447                 var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
47448                 return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
47449               }
47450               /**
47451                * Compares values to sort them in ascending order.
47452                *
47453                * @private
47454                * @param {*} value The value to compare.
47455                * @param {*} other The other value to compare.
47456                * @returns {number} Returns the sort order indicator for `value`.
47457                */
47458
47459
47460               function compareAscending(value, other) {
47461                 if (value !== other) {
47462                   var valIsDefined = value !== undefined$1,
47463                       valIsNull = value === null,
47464                       valIsReflexive = value === value,
47465                       valIsSymbol = isSymbol(value);
47466                   var othIsDefined = other !== undefined$1,
47467                       othIsNull = other === null,
47468                       othIsReflexive = other === other,
47469                       othIsSymbol = isSymbol(other);
47470
47471                   if (!othIsNull && !othIsSymbol && !valIsSymbol && value > other || valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol || valIsNull && othIsDefined && othIsReflexive || !valIsDefined && othIsReflexive || !valIsReflexive) {
47472                     return 1;
47473                   }
47474
47475                   if (!valIsNull && !valIsSymbol && !othIsSymbol && value < other || othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol || othIsNull && valIsDefined && valIsReflexive || !othIsDefined && valIsReflexive || !othIsReflexive) {
47476                     return -1;
47477                   }
47478                 }
47479
47480                 return 0;
47481               }
47482               /**
47483                * Used by `_.orderBy` to compare multiple properties of a value to another
47484                * and stable sort them.
47485                *
47486                * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,
47487                * specify an order of "desc" for descending or "asc" for ascending sort order
47488                * of corresponding values.
47489                *
47490                * @private
47491                * @param {Object} object The object to compare.
47492                * @param {Object} other The other object to compare.
47493                * @param {boolean[]|string[]} orders The order to sort by for each property.
47494                * @returns {number} Returns the sort order indicator for `object`.
47495                */
47496
47497
47498               function compareMultiple(object, other, orders) {
47499                 var index = -1,
47500                     objCriteria = object.criteria,
47501                     othCriteria = other.criteria,
47502                     length = objCriteria.length,
47503                     ordersLength = orders.length;
47504
47505                 while (++index < length) {
47506                   var result = compareAscending(objCriteria[index], othCriteria[index]);
47507
47508                   if (result) {
47509                     if (index >= ordersLength) {
47510                       return result;
47511                     }
47512
47513                     var order = orders[index];
47514                     return result * (order == 'desc' ? -1 : 1);
47515                   }
47516                 } // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
47517                 // that causes it, under certain circumstances, to provide the same value for
47518                 // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
47519                 // for more details.
47520                 //
47521                 // This also ensures a stable sort in V8 and other engines.
47522                 // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.
47523
47524
47525                 return object.index - other.index;
47526               }
47527               /**
47528                * Creates an array that is the composition of partially applied arguments,
47529                * placeholders, and provided arguments into a single array of arguments.
47530                *
47531                * @private
47532                * @param {Array} args The provided arguments.
47533                * @param {Array} partials The arguments to prepend to those provided.
47534                * @param {Array} holders The `partials` placeholder indexes.
47535                * @params {boolean} [isCurried] Specify composing for a curried function.
47536                * @returns {Array} Returns the new array of composed arguments.
47537                */
47538
47539
47540               function composeArgs(args, partials, holders, isCurried) {
47541                 var argsIndex = -1,
47542                     argsLength = args.length,
47543                     holdersLength = holders.length,
47544                     leftIndex = -1,
47545                     leftLength = partials.length,
47546                     rangeLength = nativeMax(argsLength - holdersLength, 0),
47547                     result = Array(leftLength + rangeLength),
47548                     isUncurried = !isCurried;
47549
47550                 while (++leftIndex < leftLength) {
47551                   result[leftIndex] = partials[leftIndex];
47552                 }
47553
47554                 while (++argsIndex < holdersLength) {
47555                   if (isUncurried || argsIndex < argsLength) {
47556                     result[holders[argsIndex]] = args[argsIndex];
47557                   }
47558                 }
47559
47560                 while (rangeLength--) {
47561                   result[leftIndex++] = args[argsIndex++];
47562                 }
47563
47564                 return result;
47565               }
47566               /**
47567                * This function is like `composeArgs` except that the arguments composition
47568                * is tailored for `_.partialRight`.
47569                *
47570                * @private
47571                * @param {Array} args The provided arguments.
47572                * @param {Array} partials The arguments to append to those provided.
47573                * @param {Array} holders The `partials` placeholder indexes.
47574                * @params {boolean} [isCurried] Specify composing for a curried function.
47575                * @returns {Array} Returns the new array of composed arguments.
47576                */
47577
47578
47579               function composeArgsRight(args, partials, holders, isCurried) {
47580                 var argsIndex = -1,
47581                     argsLength = args.length,
47582                     holdersIndex = -1,
47583                     holdersLength = holders.length,
47584                     rightIndex = -1,
47585                     rightLength = partials.length,
47586                     rangeLength = nativeMax(argsLength - holdersLength, 0),
47587                     result = Array(rangeLength + rightLength),
47588                     isUncurried = !isCurried;
47589
47590                 while (++argsIndex < rangeLength) {
47591                   result[argsIndex] = args[argsIndex];
47592                 }
47593
47594                 var offset = argsIndex;
47595
47596                 while (++rightIndex < rightLength) {
47597                   result[offset + rightIndex] = partials[rightIndex];
47598                 }
47599
47600                 while (++holdersIndex < holdersLength) {
47601                   if (isUncurried || argsIndex < argsLength) {
47602                     result[offset + holders[holdersIndex]] = args[argsIndex++];
47603                   }
47604                 }
47605
47606                 return result;
47607               }
47608               /**
47609                * Copies the values of `source` to `array`.
47610                *
47611                * @private
47612                * @param {Array} source The array to copy values from.
47613                * @param {Array} [array=[]] The array to copy values to.
47614                * @returns {Array} Returns `array`.
47615                */
47616
47617
47618               function copyArray(source, array) {
47619                 var index = -1,
47620                     length = source.length;
47621                 array || (array = Array(length));
47622
47623                 while (++index < length) {
47624                   array[index] = source[index];
47625                 }
47626
47627                 return array;
47628               }
47629               /**
47630                * Copies properties of `source` to `object`.
47631                *
47632                * @private
47633                * @param {Object} source The object to copy properties from.
47634                * @param {Array} props The property identifiers to copy.
47635                * @param {Object} [object={}] The object to copy properties to.
47636                * @param {Function} [customizer] The function to customize copied values.
47637                * @returns {Object} Returns `object`.
47638                */
47639
47640
47641               function copyObject(source, props, object, customizer) {
47642                 var isNew = !object;
47643                 object || (object = {});
47644                 var index = -1,
47645                     length = props.length;
47646
47647                 while (++index < length) {
47648                   var key = props[index];
47649                   var newValue = customizer ? customizer(object[key], source[key], key, object, source) : undefined$1;
47650
47651                   if (newValue === undefined$1) {
47652                     newValue = source[key];
47653                   }
47654
47655                   if (isNew) {
47656                     baseAssignValue(object, key, newValue);
47657                   } else {
47658                     assignValue(object, key, newValue);
47659                   }
47660                 }
47661
47662                 return object;
47663               }
47664               /**
47665                * Copies own symbols of `source` to `object`.
47666                *
47667                * @private
47668                * @param {Object} source The object to copy symbols from.
47669                * @param {Object} [object={}] The object to copy symbols to.
47670                * @returns {Object} Returns `object`.
47671                */
47672
47673
47674               function copySymbols(source, object) {
47675                 return copyObject(source, getSymbols(source), object);
47676               }
47677               /**
47678                * Copies own and inherited symbols of `source` to `object`.
47679                *
47680                * @private
47681                * @param {Object} source The object to copy symbols from.
47682                * @param {Object} [object={}] The object to copy symbols to.
47683                * @returns {Object} Returns `object`.
47684                */
47685
47686
47687               function copySymbolsIn(source, object) {
47688                 return copyObject(source, getSymbolsIn(source), object);
47689               }
47690               /**
47691                * Creates a function like `_.groupBy`.
47692                *
47693                * @private
47694                * @param {Function} setter The function to set accumulator values.
47695                * @param {Function} [initializer] The accumulator object initializer.
47696                * @returns {Function} Returns the new aggregator function.
47697                */
47698
47699
47700               function createAggregator(setter, initializer) {
47701                 return function (collection, iteratee) {
47702                   var func = isArray(collection) ? arrayAggregator : baseAggregator,
47703                       accumulator = initializer ? initializer() : {};
47704                   return func(collection, setter, getIteratee(iteratee, 2), accumulator);
47705                 };
47706               }
47707               /**
47708                * Creates a function like `_.assign`.
47709                *
47710                * @private
47711                * @param {Function} assigner The function to assign values.
47712                * @returns {Function} Returns the new assigner function.
47713                */
47714
47715
47716               function createAssigner(assigner) {
47717                 return baseRest(function (object, sources) {
47718                   var index = -1,
47719                       length = sources.length,
47720                       customizer = length > 1 ? sources[length - 1] : undefined$1,
47721                       guard = length > 2 ? sources[2] : undefined$1;
47722                   customizer = assigner.length > 3 && typeof customizer == 'function' ? (length--, customizer) : undefined$1;
47723
47724                   if (guard && isIterateeCall(sources[0], sources[1], guard)) {
47725                     customizer = length < 3 ? undefined$1 : customizer;
47726                     length = 1;
47727                   }
47728
47729                   object = Object(object);
47730
47731                   while (++index < length) {
47732                     var source = sources[index];
47733
47734                     if (source) {
47735                       assigner(object, source, index, customizer);
47736                     }
47737                   }
47738
47739                   return object;
47740                 });
47741               }
47742               /**
47743                * Creates a `baseEach` or `baseEachRight` function.
47744                *
47745                * @private
47746                * @param {Function} eachFunc The function to iterate over a collection.
47747                * @param {boolean} [fromRight] Specify iterating from right to left.
47748                * @returns {Function} Returns the new base function.
47749                */
47750
47751
47752               function createBaseEach(eachFunc, fromRight) {
47753                 return function (collection, iteratee) {
47754                   if (collection == null) {
47755                     return collection;
47756                   }
47757
47758                   if (!isArrayLike(collection)) {
47759                     return eachFunc(collection, iteratee);
47760                   }
47761
47762                   var length = collection.length,
47763                       index = fromRight ? length : -1,
47764                       iterable = Object(collection);
47765
47766                   while (fromRight ? index-- : ++index < length) {
47767                     if (iteratee(iterable[index], index, iterable) === false) {
47768                       break;
47769                     }
47770                   }
47771
47772                   return collection;
47773                 };
47774               }
47775               /**
47776                * Creates a base function for methods like `_.forIn` and `_.forOwn`.
47777                *
47778                * @private
47779                * @param {boolean} [fromRight] Specify iterating from right to left.
47780                * @returns {Function} Returns the new base function.
47781                */
47782
47783
47784               function createBaseFor(fromRight) {
47785                 return function (object, iteratee, keysFunc) {
47786                   var index = -1,
47787                       iterable = Object(object),
47788                       props = keysFunc(object),
47789                       length = props.length;
47790
47791                   while (length--) {
47792                     var key = props[fromRight ? length : ++index];
47793
47794                     if (iteratee(iterable[key], key, iterable) === false) {
47795                       break;
47796                     }
47797                   }
47798
47799                   return object;
47800                 };
47801               }
47802               /**
47803                * Creates a function that wraps `func` to invoke it with the optional `this`
47804                * binding of `thisArg`.
47805                *
47806                * @private
47807                * @param {Function} func The function to wrap.
47808                * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
47809                * @param {*} [thisArg] The `this` binding of `func`.
47810                * @returns {Function} Returns the new wrapped function.
47811                */
47812
47813
47814               function createBind(func, bitmask, thisArg) {
47815                 var isBind = bitmask & WRAP_BIND_FLAG,
47816                     Ctor = createCtor(func);
47817
47818                 function wrapper() {
47819                   var fn = this && this !== root && this instanceof wrapper ? Ctor : func;
47820                   return fn.apply(isBind ? thisArg : this, arguments);
47821                 }
47822
47823                 return wrapper;
47824               }
47825               /**
47826                * Creates a function like `_.lowerFirst`.
47827                *
47828                * @private
47829                * @param {string} methodName The name of the `String` case method to use.
47830                * @returns {Function} Returns the new case function.
47831                */
47832
47833
47834               function createCaseFirst(methodName) {
47835                 return function (string) {
47836                   string = toString(string);
47837                   var strSymbols = hasUnicode(string) ? stringToArray(string) : undefined$1;
47838                   var chr = strSymbols ? strSymbols[0] : string.charAt(0);
47839                   var trailing = strSymbols ? castSlice(strSymbols, 1).join('') : string.slice(1);
47840                   return chr[methodName]() + trailing;
47841                 };
47842               }
47843               /**
47844                * Creates a function like `_.camelCase`.
47845                *
47846                * @private
47847                * @param {Function} callback The function to combine each word.
47848                * @returns {Function} Returns the new compounder function.
47849                */
47850
47851
47852               function createCompounder(callback) {
47853                 return function (string) {
47854                   return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');
47855                 };
47856               }
47857               /**
47858                * Creates a function that produces an instance of `Ctor` regardless of
47859                * whether it was invoked as part of a `new` expression or by `call` or `apply`.
47860                *
47861                * @private
47862                * @param {Function} Ctor The constructor to wrap.
47863                * @returns {Function} Returns the new wrapped function.
47864                */
47865
47866
47867               function createCtor(Ctor) {
47868                 return function () {
47869                   // Use a `switch` statement to work with class constructors. See
47870                   // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
47871                   // for more details.
47872                   var args = arguments;
47873
47874                   switch (args.length) {
47875                     case 0:
47876                       return new Ctor();
47877
47878                     case 1:
47879                       return new Ctor(args[0]);
47880
47881                     case 2:
47882                       return new Ctor(args[0], args[1]);
47883
47884                     case 3:
47885                       return new Ctor(args[0], args[1], args[2]);
47886
47887                     case 4:
47888                       return new Ctor(args[0], args[1], args[2], args[3]);
47889
47890                     case 5:
47891                       return new Ctor(args[0], args[1], args[2], args[3], args[4]);
47892
47893                     case 6:
47894                       return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
47895
47896                     case 7:
47897                       return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
47898                   }
47899
47900                   var thisBinding = baseCreate(Ctor.prototype),
47901                       result = Ctor.apply(thisBinding, args); // Mimic the constructor's `return` behavior.
47902                   // See https://es5.github.io/#x13.2.2 for more details.
47903
47904                   return isObject(result) ? result : thisBinding;
47905                 };
47906               }
47907               /**
47908                * Creates a function that wraps `func` to enable currying.
47909                *
47910                * @private
47911                * @param {Function} func The function to wrap.
47912                * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
47913                * @param {number} arity The arity of `func`.
47914                * @returns {Function} Returns the new wrapped function.
47915                */
47916
47917
47918               function createCurry(func, bitmask, arity) {
47919                 var Ctor = createCtor(func);
47920
47921                 function wrapper() {
47922                   var length = arguments.length,
47923                       args = Array(length),
47924                       index = length,
47925                       placeholder = getHolder(wrapper);
47926
47927                   while (index--) {
47928                     args[index] = arguments[index];
47929                   }
47930
47931                   var holders = length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder ? [] : replaceHolders(args, placeholder);
47932                   length -= holders.length;
47933
47934                   if (length < arity) {
47935                     return createRecurry(func, bitmask, createHybrid, wrapper.placeholder, undefined$1, args, holders, undefined$1, undefined$1, arity - length);
47936                   }
47937
47938                   var fn = this && this !== root && this instanceof wrapper ? Ctor : func;
47939                   return apply(fn, this, args);
47940                 }
47941
47942                 return wrapper;
47943               }
47944               /**
47945                * Creates a `_.find` or `_.findLast` function.
47946                *
47947                * @private
47948                * @param {Function} findIndexFunc The function to find the collection index.
47949                * @returns {Function} Returns the new find function.
47950                */
47951
47952
47953               function createFind(findIndexFunc) {
47954                 return function (collection, predicate, fromIndex) {
47955                   var iterable = Object(collection);
47956
47957                   if (!isArrayLike(collection)) {
47958                     var iteratee = getIteratee(predicate, 3);
47959                     collection = keys(collection);
47960
47961                     predicate = function predicate(key) {
47962                       return iteratee(iterable[key], key, iterable);
47963                     };
47964                   }
47965
47966                   var index = findIndexFunc(collection, predicate, fromIndex);
47967                   return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined$1;
47968                 };
47969               }
47970               /**
47971                * Creates a `_.flow` or `_.flowRight` function.
47972                *
47973                * @private
47974                * @param {boolean} [fromRight] Specify iterating from right to left.
47975                * @returns {Function} Returns the new flow function.
47976                */
47977
47978
47979               function createFlow(fromRight) {
47980                 return flatRest(function (funcs) {
47981                   var length = funcs.length,
47982                       index = length,
47983                       prereq = LodashWrapper.prototype.thru;
47984
47985                   if (fromRight) {
47986                     funcs.reverse();
47987                   }
47988
47989                   while (index--) {
47990                     var func = funcs[index];
47991
47992                     if (typeof func != 'function') {
47993                       throw new TypeError(FUNC_ERROR_TEXT);
47994                     }
47995
47996                     if (prereq && !wrapper && getFuncName(func) == 'wrapper') {
47997                       var wrapper = new LodashWrapper([], true);
47998                     }
47999                   }
48000
48001                   index = wrapper ? index : length;
48002
48003                   while (++index < length) {
48004                     func = funcs[index];
48005                     var funcName = getFuncName(func),
48006                         data = funcName == 'wrapper' ? getData(func) : undefined$1;
48007
48008                     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) {
48009                       wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
48010                     } else {
48011                       wrapper = func.length == 1 && isLaziable(func) ? wrapper[funcName]() : wrapper.thru(func);
48012                     }
48013                   }
48014
48015                   return function () {
48016                     var args = arguments,
48017                         value = args[0];
48018
48019                     if (wrapper && args.length == 1 && isArray(value)) {
48020                       return wrapper.plant(value).value();
48021                     }
48022
48023                     var index = 0,
48024                         result = length ? funcs[index].apply(this, args) : value;
48025
48026                     while (++index < length) {
48027                       result = funcs[index].call(this, result);
48028                     }
48029
48030                     return result;
48031                   };
48032                 });
48033               }
48034               /**
48035                * Creates a function that wraps `func` to invoke it with optional `this`
48036                * binding of `thisArg`, partial application, and currying.
48037                *
48038                * @private
48039                * @param {Function|string} func The function or method name to wrap.
48040                * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
48041                * @param {*} [thisArg] The `this` binding of `func`.
48042                * @param {Array} [partials] The arguments to prepend to those provided to
48043                *  the new function.
48044                * @param {Array} [holders] The `partials` placeholder indexes.
48045                * @param {Array} [partialsRight] The arguments to append to those provided
48046                *  to the new function.
48047                * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
48048                * @param {Array} [argPos] The argument positions of the new function.
48049                * @param {number} [ary] The arity cap of `func`.
48050                * @param {number} [arity] The arity of `func`.
48051                * @returns {Function} Returns the new wrapped function.
48052                */
48053
48054
48055               function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
48056                 var isAry = bitmask & WRAP_ARY_FLAG,
48057                     isBind = bitmask & WRAP_BIND_FLAG,
48058                     isBindKey = bitmask & WRAP_BIND_KEY_FLAG,
48059                     isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),
48060                     isFlip = bitmask & WRAP_FLIP_FLAG,
48061                     Ctor = isBindKey ? undefined$1 : createCtor(func);
48062
48063                 function wrapper() {
48064                   var length = arguments.length,
48065                       args = Array(length),
48066                       index = length;
48067
48068                   while (index--) {
48069                     args[index] = arguments[index];
48070                   }
48071
48072                   if (isCurried) {
48073                     var placeholder = getHolder(wrapper),
48074                         holdersCount = countHolders(args, placeholder);
48075                   }
48076
48077                   if (partials) {
48078                     args = composeArgs(args, partials, holders, isCurried);
48079                   }
48080
48081                   if (partialsRight) {
48082                     args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
48083                   }
48084
48085                   length -= holdersCount;
48086
48087                   if (isCurried && length < arity) {
48088                     var newHolders = replaceHolders(args, placeholder);
48089                     return createRecurry(func, bitmask, createHybrid, wrapper.placeholder, thisArg, args, newHolders, argPos, ary, arity - length);
48090                   }
48091
48092                   var thisBinding = isBind ? thisArg : this,
48093                       fn = isBindKey ? thisBinding[func] : func;
48094                   length = args.length;
48095
48096                   if (argPos) {
48097                     args = reorder(args, argPos);
48098                   } else if (isFlip && length > 1) {
48099                     args.reverse();
48100                   }
48101
48102                   if (isAry && ary < length) {
48103                     args.length = ary;
48104                   }
48105
48106                   if (this && this !== root && this instanceof wrapper) {
48107                     fn = Ctor || createCtor(fn);
48108                   }
48109
48110                   return fn.apply(thisBinding, args);
48111                 }
48112
48113                 return wrapper;
48114               }
48115               /**
48116                * Creates a function like `_.invertBy`.
48117                *
48118                * @private
48119                * @param {Function} setter The function to set accumulator values.
48120                * @param {Function} toIteratee The function to resolve iteratees.
48121                * @returns {Function} Returns the new inverter function.
48122                */
48123
48124
48125               function createInverter(setter, toIteratee) {
48126                 return function (object, iteratee) {
48127                   return baseInverter(object, setter, toIteratee(iteratee), {});
48128                 };
48129               }
48130               /**
48131                * Creates a function that performs a mathematical operation on two values.
48132                *
48133                * @private
48134                * @param {Function} operator The function to perform the operation.
48135                * @param {number} [defaultValue] The value used for `undefined` arguments.
48136                * @returns {Function} Returns the new mathematical operation function.
48137                */
48138
48139
48140               function createMathOperation(operator, defaultValue) {
48141                 return function (value, other) {
48142                   var result;
48143
48144                   if (value === undefined$1 && other === undefined$1) {
48145                     return defaultValue;
48146                   }
48147
48148                   if (value !== undefined$1) {
48149                     result = value;
48150                   }
48151
48152                   if (other !== undefined$1) {
48153                     if (result === undefined$1) {
48154                       return other;
48155                     }
48156
48157                     if (typeof value == 'string' || typeof other == 'string') {
48158                       value = baseToString(value);
48159                       other = baseToString(other);
48160                     } else {
48161                       value = baseToNumber(value);
48162                       other = baseToNumber(other);
48163                     }
48164
48165                     result = operator(value, other);
48166                   }
48167
48168                   return result;
48169                 };
48170               }
48171               /**
48172                * Creates a function like `_.over`.
48173                *
48174                * @private
48175                * @param {Function} arrayFunc The function to iterate over iteratees.
48176                * @returns {Function} Returns the new over function.
48177                */
48178
48179
48180               function createOver(arrayFunc) {
48181                 return flatRest(function (iteratees) {
48182                   iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
48183                   return baseRest(function (args) {
48184                     var thisArg = this;
48185                     return arrayFunc(iteratees, function (iteratee) {
48186                       return apply(iteratee, thisArg, args);
48187                     });
48188                   });
48189                 });
48190               }
48191               /**
48192                * Creates the padding for `string` based on `length`. The `chars` string
48193                * is truncated if the number of characters exceeds `length`.
48194                *
48195                * @private
48196                * @param {number} length The padding length.
48197                * @param {string} [chars=' '] The string used as padding.
48198                * @returns {string} Returns the padding for `string`.
48199                */
48200
48201
48202               function createPadding(length, chars) {
48203                 chars = chars === undefined$1 ? ' ' : baseToString(chars);
48204                 var charsLength = chars.length;
48205
48206                 if (charsLength < 2) {
48207                   return charsLength ? baseRepeat(chars, length) : chars;
48208                 }
48209
48210                 var result = baseRepeat(chars, nativeCeil(length / stringSize(chars)));
48211                 return hasUnicode(chars) ? castSlice(stringToArray(result), 0, length).join('') : result.slice(0, length);
48212               }
48213               /**
48214                * Creates a function that wraps `func` to invoke it with the `this` binding
48215                * of `thisArg` and `partials` prepended to the arguments it receives.
48216                *
48217                * @private
48218                * @param {Function} func The function to wrap.
48219                * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
48220                * @param {*} thisArg The `this` binding of `func`.
48221                * @param {Array} partials The arguments to prepend to those provided to
48222                *  the new function.
48223                * @returns {Function} Returns the new wrapped function.
48224                */
48225
48226
48227               function createPartial(func, bitmask, thisArg, partials) {
48228                 var isBind = bitmask & WRAP_BIND_FLAG,
48229                     Ctor = createCtor(func);
48230
48231                 function wrapper() {
48232                   var argsIndex = -1,
48233                       argsLength = arguments.length,
48234                       leftIndex = -1,
48235                       leftLength = partials.length,
48236                       args = Array(leftLength + argsLength),
48237                       fn = this && this !== root && this instanceof wrapper ? Ctor : func;
48238
48239                   while (++leftIndex < leftLength) {
48240                     args[leftIndex] = partials[leftIndex];
48241                   }
48242
48243                   while (argsLength--) {
48244                     args[leftIndex++] = arguments[++argsIndex];
48245                   }
48246
48247                   return apply(fn, isBind ? thisArg : this, args);
48248                 }
48249
48250                 return wrapper;
48251               }
48252               /**
48253                * Creates a `_.range` or `_.rangeRight` function.
48254                *
48255                * @private
48256                * @param {boolean} [fromRight] Specify iterating from right to left.
48257                * @returns {Function} Returns the new range function.
48258                */
48259
48260
48261               function createRange(fromRight) {
48262                 return function (start, end, step) {
48263                   if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {
48264                     end = step = undefined$1;
48265                   } // Ensure the sign of `-0` is preserved.
48266
48267
48268                   start = toFinite(start);
48269
48270                   if (end === undefined$1) {
48271                     end = start;
48272                     start = 0;
48273                   } else {
48274                     end = toFinite(end);
48275                   }
48276
48277                   step = step === undefined$1 ? start < end ? 1 : -1 : toFinite(step);
48278                   return baseRange(start, end, step, fromRight);
48279                 };
48280               }
48281               /**
48282                * Creates a function that performs a relational operation on two values.
48283                *
48284                * @private
48285                * @param {Function} operator The function to perform the operation.
48286                * @returns {Function} Returns the new relational operation function.
48287                */
48288
48289
48290               function createRelationalOperation(operator) {
48291                 return function (value, other) {
48292                   if (!(typeof value == 'string' && typeof other == 'string')) {
48293                     value = toNumber(value);
48294                     other = toNumber(other);
48295                   }
48296
48297                   return operator(value, other);
48298                 };
48299               }
48300               /**
48301                * Creates a function that wraps `func` to continue currying.
48302                *
48303                * @private
48304                * @param {Function} func The function to wrap.
48305                * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
48306                * @param {Function} wrapFunc The function to create the `func` wrapper.
48307                * @param {*} placeholder The placeholder value.
48308                * @param {*} [thisArg] The `this` binding of `func`.
48309                * @param {Array} [partials] The arguments to prepend to those provided to
48310                *  the new function.
48311                * @param {Array} [holders] The `partials` placeholder indexes.
48312                * @param {Array} [argPos] The argument positions of the new function.
48313                * @param {number} [ary] The arity cap of `func`.
48314                * @param {number} [arity] The arity of `func`.
48315                * @returns {Function} Returns the new wrapped function.
48316                */
48317
48318
48319               function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
48320                 var isCurry = bitmask & WRAP_CURRY_FLAG,
48321                     newHolders = isCurry ? holders : undefined$1,
48322                     newHoldersRight = isCurry ? undefined$1 : holders,
48323                     newPartials = isCurry ? partials : undefined$1,
48324                     newPartialsRight = isCurry ? undefined$1 : partials;
48325                 bitmask |= isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG;
48326                 bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);
48327
48328                 if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
48329                   bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
48330                 }
48331
48332                 var newData = [func, bitmask, thisArg, newPartials, newHolders, newPartialsRight, newHoldersRight, argPos, ary, arity];
48333                 var result = wrapFunc.apply(undefined$1, newData);
48334
48335                 if (isLaziable(func)) {
48336                   setData(result, newData);
48337                 }
48338
48339                 result.placeholder = placeholder;
48340                 return setWrapToString(result, func, bitmask);
48341               }
48342               /**
48343                * Creates a function like `_.round`.
48344                *
48345                * @private
48346                * @param {string} methodName The name of the `Math` method to use when rounding.
48347                * @returns {Function} Returns the new round function.
48348                */
48349
48350
48351               function createRound(methodName) {
48352                 var func = Math[methodName];
48353                 return function (number, precision) {
48354                   number = toNumber(number);
48355                   precision = precision == null ? 0 : nativeMin(toInteger(precision), 292);
48356
48357                   if (precision && nativeIsFinite(number)) {
48358                     // Shift with exponential notation to avoid floating-point issues.
48359                     // See [MDN](https://mdn.io/round#Examples) for more details.
48360                     var pair = (toString(number) + 'e').split('e'),
48361                         value = func(pair[0] + 'e' + (+pair[1] + precision));
48362                     pair = (toString(value) + 'e').split('e');
48363                     return +(pair[0] + 'e' + (+pair[1] - precision));
48364                   }
48365
48366                   return func(number);
48367                 };
48368               }
48369               /**
48370                * Creates a set object of `values`.
48371                *
48372                * @private
48373                * @param {Array} values The values to add to the set.
48374                * @returns {Object} Returns the new set.
48375                */
48376
48377
48378               var createSet = !(Set && 1 / setToArray(new Set([, -0]))[1] == INFINITY) ? noop : function (values) {
48379                 return new Set(values);
48380               };
48381               /**
48382                * Creates a `_.toPairs` or `_.toPairsIn` function.
48383                *
48384                * @private
48385                * @param {Function} keysFunc The function to get the keys of a given object.
48386                * @returns {Function} Returns the new pairs function.
48387                */
48388
48389               function createToPairs(keysFunc) {
48390                 return function (object) {
48391                   var tag = getTag(object);
48392
48393                   if (tag == mapTag) {
48394                     return mapToArray(object);
48395                   }
48396
48397                   if (tag == setTag) {
48398                     return setToPairs(object);
48399                   }
48400
48401                   return baseToPairs(object, keysFunc(object));
48402                 };
48403               }
48404               /**
48405                * Creates a function that either curries or invokes `func` with optional
48406                * `this` binding and partially applied arguments.
48407                *
48408                * @private
48409                * @param {Function|string} func The function or method name to wrap.
48410                * @param {number} bitmask The bitmask flags.
48411                *    1 - `_.bind`
48412                *    2 - `_.bindKey`
48413                *    4 - `_.curry` or `_.curryRight` of a bound function
48414                *    8 - `_.curry`
48415                *   16 - `_.curryRight`
48416                *   32 - `_.partial`
48417                *   64 - `_.partialRight`
48418                *  128 - `_.rearg`
48419                *  256 - `_.ary`
48420                *  512 - `_.flip`
48421                * @param {*} [thisArg] The `this` binding of `func`.
48422                * @param {Array} [partials] The arguments to be partially applied.
48423                * @param {Array} [holders] The `partials` placeholder indexes.
48424                * @param {Array} [argPos] The argument positions of the new function.
48425                * @param {number} [ary] The arity cap of `func`.
48426                * @param {number} [arity] The arity of `func`.
48427                * @returns {Function} Returns the new wrapped function.
48428                */
48429
48430
48431               function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
48432                 var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;
48433
48434                 if (!isBindKey && typeof func != 'function') {
48435                   throw new TypeError(FUNC_ERROR_TEXT);
48436                 }
48437
48438                 var length = partials ? partials.length : 0;
48439
48440                 if (!length) {
48441                   bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);
48442                   partials = holders = undefined$1;
48443                 }
48444
48445                 ary = ary === undefined$1 ? ary : nativeMax(toInteger(ary), 0);
48446                 arity = arity === undefined$1 ? arity : toInteger(arity);
48447                 length -= holders ? holders.length : 0;
48448
48449                 if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {
48450                   var partialsRight = partials,
48451                       holdersRight = holders;
48452                   partials = holders = undefined$1;
48453                 }
48454
48455                 var data = isBindKey ? undefined$1 : getData(func);
48456                 var newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity];
48457
48458                 if (data) {
48459                   mergeData(newData, data);
48460                 }
48461
48462                 func = newData[0];
48463                 bitmask = newData[1];
48464                 thisArg = newData[2];
48465                 partials = newData[3];
48466                 holders = newData[4];
48467                 arity = newData[9] = newData[9] === undefined$1 ? isBindKey ? 0 : func.length : nativeMax(newData[9] - length, 0);
48468
48469                 if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
48470                   bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
48471                 }
48472
48473                 if (!bitmask || bitmask == WRAP_BIND_FLAG) {
48474                   var result = createBind(func, bitmask, thisArg);
48475                 } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {
48476                   result = createCurry(func, bitmask, arity);
48477                 } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {
48478                   result = createPartial(func, bitmask, thisArg, partials);
48479                 } else {
48480                   result = createHybrid.apply(undefined$1, newData);
48481                 }
48482
48483                 var setter = data ? baseSetData : setData;
48484                 return setWrapToString(setter(result, newData), func, bitmask);
48485               }
48486               /**
48487                * Used by `_.defaults` to customize its `_.assignIn` use to assign properties
48488                * of source objects to the destination object for all destination properties
48489                * that resolve to `undefined`.
48490                *
48491                * @private
48492                * @param {*} objValue The destination value.
48493                * @param {*} srcValue The source value.
48494                * @param {string} key The key of the property to assign.
48495                * @param {Object} object The parent object of `objValue`.
48496                * @returns {*} Returns the value to assign.
48497                */
48498
48499
48500               function customDefaultsAssignIn(objValue, srcValue, key, object) {
48501                 if (objValue === undefined$1 || eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key)) {
48502                   return srcValue;
48503                 }
48504
48505                 return objValue;
48506               }
48507               /**
48508                * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source
48509                * objects into destination objects that are passed thru.
48510                *
48511                * @private
48512                * @param {*} objValue The destination value.
48513                * @param {*} srcValue The source value.
48514                * @param {string} key The key of the property to merge.
48515                * @param {Object} object The parent object of `objValue`.
48516                * @param {Object} source The parent object of `srcValue`.
48517                * @param {Object} [stack] Tracks traversed source values and their merged
48518                *  counterparts.
48519                * @returns {*} Returns the value to assign.
48520                */
48521
48522
48523               function customDefaultsMerge(objValue, srcValue, key, object, source, stack) {
48524                 if (isObject(objValue) && isObject(srcValue)) {
48525                   // Recursively merge objects and arrays (susceptible to call stack limits).
48526                   stack.set(srcValue, objValue);
48527                   baseMerge(objValue, srcValue, undefined$1, customDefaultsMerge, stack);
48528                   stack['delete'](srcValue);
48529                 }
48530
48531                 return objValue;
48532               }
48533               /**
48534                * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain
48535                * objects.
48536                *
48537                * @private
48538                * @param {*} value The value to inspect.
48539                * @param {string} key The key of the property to inspect.
48540                * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`.
48541                */
48542
48543
48544               function customOmitClone(value) {
48545                 return isPlainObject(value) ? undefined$1 : value;
48546               }
48547               /**
48548                * A specialized version of `baseIsEqualDeep` for arrays with support for
48549                * partial deep comparisons.
48550                *
48551                * @private
48552                * @param {Array} array The array to compare.
48553                * @param {Array} other The other array to compare.
48554                * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
48555                * @param {Function} customizer The function to customize comparisons.
48556                * @param {Function} equalFunc The function to determine equivalents of values.
48557                * @param {Object} stack Tracks traversed `array` and `other` objects.
48558                * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
48559                */
48560
48561
48562               function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
48563                 var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
48564                     arrLength = array.length,
48565                     othLength = other.length;
48566
48567                 if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
48568                   return false;
48569                 } // Check that cyclic values are equal.
48570
48571
48572                 var arrStacked = stack.get(array);
48573                 var othStacked = stack.get(other);
48574
48575                 if (arrStacked && othStacked) {
48576                   return arrStacked == other && othStacked == array;
48577                 }
48578
48579                 var index = -1,
48580                     result = true,
48581                     seen = bitmask & COMPARE_UNORDERED_FLAG ? new SetCache() : undefined$1;
48582                 stack.set(array, other);
48583                 stack.set(other, array); // Ignore non-index properties.
48584
48585                 while (++index < arrLength) {
48586                   var arrValue = array[index],
48587                       othValue = other[index];
48588
48589                   if (customizer) {
48590                     var compared = isPartial ? customizer(othValue, arrValue, index, other, array, stack) : customizer(arrValue, othValue, index, array, other, stack);
48591                   }
48592
48593                   if (compared !== undefined$1) {
48594                     if (compared) {
48595                       continue;
48596                     }
48597
48598                     result = false;
48599                     break;
48600                   } // Recursively compare arrays (susceptible to call stack limits).
48601
48602
48603                   if (seen) {
48604                     if (!arraySome(other, function (othValue, othIndex) {
48605                       if (!cacheHas(seen, othIndex) && (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
48606                         return seen.push(othIndex);
48607                       }
48608                     })) {
48609                       result = false;
48610                       break;
48611                     }
48612                   } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
48613                     result = false;
48614                     break;
48615                   }
48616                 }
48617
48618                 stack['delete'](array);
48619                 stack['delete'](other);
48620                 return result;
48621               }
48622               /**
48623                * A specialized version of `baseIsEqualDeep` for comparing objects of
48624                * the same `toStringTag`.
48625                *
48626                * **Note:** This function only supports comparing values with tags of
48627                * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
48628                *
48629                * @private
48630                * @param {Object} object The object to compare.
48631                * @param {Object} other The other object to compare.
48632                * @param {string} tag The `toStringTag` of the objects to compare.
48633                * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
48634                * @param {Function} customizer The function to customize comparisons.
48635                * @param {Function} equalFunc The function to determine equivalents of values.
48636                * @param {Object} stack Tracks traversed `object` and `other` objects.
48637                * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
48638                */
48639
48640
48641               function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
48642                 switch (tag) {
48643                   case dataViewTag:
48644                     if (object.byteLength != other.byteLength || object.byteOffset != other.byteOffset) {
48645                       return false;
48646                     }
48647
48648                     object = object.buffer;
48649                     other = other.buffer;
48650
48651                   case arrayBufferTag:
48652                     if (object.byteLength != other.byteLength || !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
48653                       return false;
48654                     }
48655
48656                     return true;
48657
48658                   case boolTag:
48659                   case dateTag:
48660                   case numberTag:
48661                     // Coerce booleans to `1` or `0` and dates to milliseconds.
48662                     // Invalid dates are coerced to `NaN`.
48663                     return eq(+object, +other);
48664
48665                   case errorTag:
48666                     return object.name == other.name && object.message == other.message;
48667
48668                   case regexpTag:
48669                   case stringTag:
48670                     // Coerce regexes to strings and treat strings, primitives and objects,
48671                     // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
48672                     // for more details.
48673                     return object == other + '';
48674
48675                   case mapTag:
48676                     var convert = mapToArray;
48677
48678                   case setTag:
48679                     var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
48680                     convert || (convert = setToArray);
48681
48682                     if (object.size != other.size && !isPartial) {
48683                       return false;
48684                     } // Assume cyclic values are equal.
48685
48686
48687                     var stacked = stack.get(object);
48688
48689                     if (stacked) {
48690                       return stacked == other;
48691                     }
48692
48693                     bitmask |= COMPARE_UNORDERED_FLAG; // Recursively compare objects (susceptible to call stack limits).
48694
48695                     stack.set(object, other);
48696                     var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
48697                     stack['delete'](object);
48698                     return result;
48699
48700                   case symbolTag:
48701                     if (symbolValueOf) {
48702                       return symbolValueOf.call(object) == symbolValueOf.call(other);
48703                     }
48704
48705                 }
48706
48707                 return false;
48708               }
48709               /**
48710                * A specialized version of `baseIsEqualDeep` for objects with support for
48711                * partial deep comparisons.
48712                *
48713                * @private
48714                * @param {Object} object The object to compare.
48715                * @param {Object} other The other object to compare.
48716                * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
48717                * @param {Function} customizer The function to customize comparisons.
48718                * @param {Function} equalFunc The function to determine equivalents of values.
48719                * @param {Object} stack Tracks traversed `object` and `other` objects.
48720                * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
48721                */
48722
48723
48724               function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
48725                 var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
48726                     objProps = getAllKeys(object),
48727                     objLength = objProps.length,
48728                     othProps = getAllKeys(other),
48729                     othLength = othProps.length;
48730
48731                 if (objLength != othLength && !isPartial) {
48732                   return false;
48733                 }
48734
48735                 var index = objLength;
48736
48737                 while (index--) {
48738                   var key = objProps[index];
48739
48740                   if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
48741                     return false;
48742                   }
48743                 } // Check that cyclic values are equal.
48744
48745
48746                 var objStacked = stack.get(object);
48747                 var othStacked = stack.get(other);
48748
48749                 if (objStacked && othStacked) {
48750                   return objStacked == other && othStacked == object;
48751                 }
48752
48753                 var result = true;
48754                 stack.set(object, other);
48755                 stack.set(other, object);
48756                 var skipCtor = isPartial;
48757
48758                 while (++index < objLength) {
48759                   key = objProps[index];
48760                   var objValue = object[key],
48761                       othValue = other[key];
48762
48763                   if (customizer) {
48764                     var compared = isPartial ? customizer(othValue, objValue, key, other, object, stack) : customizer(objValue, othValue, key, object, other, stack);
48765                   } // Recursively compare objects (susceptible to call stack limits).
48766
48767
48768                   if (!(compared === undefined$1 ? objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack) : compared)) {
48769                     result = false;
48770                     break;
48771                   }
48772
48773                   skipCtor || (skipCtor = key == 'constructor');
48774                 }
48775
48776                 if (result && !skipCtor) {
48777                   var objCtor = object.constructor,
48778                       othCtor = other.constructor; // Non `Object` object instances with different constructors are not equal.
48779
48780                   if (objCtor != othCtor && 'constructor' in object && 'constructor' in other && !(typeof objCtor == 'function' && objCtor instanceof objCtor && typeof othCtor == 'function' && othCtor instanceof othCtor)) {
48781                     result = false;
48782                   }
48783                 }
48784
48785                 stack['delete'](object);
48786                 stack['delete'](other);
48787                 return result;
48788               }
48789               /**
48790                * A specialized version of `baseRest` which flattens the rest array.
48791                *
48792                * @private
48793                * @param {Function} func The function to apply a rest parameter to.
48794                * @returns {Function} Returns the new function.
48795                */
48796
48797
48798               function flatRest(func) {
48799                 return setToString(overRest(func, undefined$1, flatten), func + '');
48800               }
48801               /**
48802                * Creates an array of own enumerable property names and symbols of `object`.
48803                *
48804                * @private
48805                * @param {Object} object The object to query.
48806                * @returns {Array} Returns the array of property names and symbols.
48807                */
48808
48809
48810               function getAllKeys(object) {
48811                 return baseGetAllKeys(object, keys, getSymbols);
48812               }
48813               /**
48814                * Creates an array of own and inherited enumerable property names and
48815                * symbols of `object`.
48816                *
48817                * @private
48818                * @param {Object} object The object to query.
48819                * @returns {Array} Returns the array of property names and symbols.
48820                */
48821
48822
48823               function getAllKeysIn(object) {
48824                 return baseGetAllKeys(object, keysIn, getSymbolsIn);
48825               }
48826               /**
48827                * Gets metadata for `func`.
48828                *
48829                * @private
48830                * @param {Function} func The function to query.
48831                * @returns {*} Returns the metadata for `func`.
48832                */
48833
48834
48835               var getData = !metaMap ? noop : function (func) {
48836                 return metaMap.get(func);
48837               };
48838               /**
48839                * Gets the name of `func`.
48840                *
48841                * @private
48842                * @param {Function} func The function to query.
48843                * @returns {string} Returns the function name.
48844                */
48845
48846               function getFuncName(func) {
48847                 var result = func.name + '',
48848                     array = realNames[result],
48849                     length = hasOwnProperty.call(realNames, result) ? array.length : 0;
48850
48851                 while (length--) {
48852                   var data = array[length],
48853                       otherFunc = data.func;
48854
48855                   if (otherFunc == null || otherFunc == func) {
48856                     return data.name;
48857                   }
48858                 }
48859
48860                 return result;
48861               }
48862               /**
48863                * Gets the argument placeholder value for `func`.
48864                *
48865                * @private
48866                * @param {Function} func The function to inspect.
48867                * @returns {*} Returns the placeholder value.
48868                */
48869
48870
48871               function getHolder(func) {
48872                 var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;
48873                 return object.placeholder;
48874               }
48875               /**
48876                * Gets the appropriate "iteratee" function. If `_.iteratee` is customized,
48877                * this function returns the custom method, otherwise it returns `baseIteratee`.
48878                * If arguments are provided, the chosen function is invoked with them and
48879                * its result is returned.
48880                *
48881                * @private
48882                * @param {*} [value] The value to convert to an iteratee.
48883                * @param {number} [arity] The arity of the created iteratee.
48884                * @returns {Function} Returns the chosen function or its result.
48885                */
48886
48887
48888               function getIteratee() {
48889                 var result = lodash.iteratee || iteratee;
48890                 result = result === iteratee ? baseIteratee : result;
48891                 return arguments.length ? result(arguments[0], arguments[1]) : result;
48892               }
48893               /**
48894                * Gets the data for `map`.
48895                *
48896                * @private
48897                * @param {Object} map The map to query.
48898                * @param {string} key The reference key.
48899                * @returns {*} Returns the map data.
48900                */
48901
48902
48903               function getMapData(map, key) {
48904                 var data = map.__data__;
48905                 return isKeyable(key) ? data[typeof key == 'string' ? 'string' : 'hash'] : data.map;
48906               }
48907               /**
48908                * Gets the property names, values, and compare flags of `object`.
48909                *
48910                * @private
48911                * @param {Object} object The object to query.
48912                * @returns {Array} Returns the match data of `object`.
48913                */
48914
48915
48916               function getMatchData(object) {
48917                 var result = keys(object),
48918                     length = result.length;
48919
48920                 while (length--) {
48921                   var key = result[length],
48922                       value = object[key];
48923                   result[length] = [key, value, isStrictComparable(value)];
48924                 }
48925
48926                 return result;
48927               }
48928               /**
48929                * Gets the native function at `key` of `object`.
48930                *
48931                * @private
48932                * @param {Object} object The object to query.
48933                * @param {string} key The key of the method to get.
48934                * @returns {*} Returns the function if it's native, else `undefined`.
48935                */
48936
48937
48938               function getNative(object, key) {
48939                 var value = getValue(object, key);
48940                 return baseIsNative(value) ? value : undefined$1;
48941               }
48942               /**
48943                * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
48944                *
48945                * @private
48946                * @param {*} value The value to query.
48947                * @returns {string} Returns the raw `toStringTag`.
48948                */
48949
48950
48951               function getRawTag(value) {
48952                 var isOwn = hasOwnProperty.call(value, symToStringTag),
48953                     tag = value[symToStringTag];
48954
48955                 try {
48956                   value[symToStringTag] = undefined$1;
48957                   var unmasked = true;
48958                 } catch (e) {}
48959
48960                 var result = nativeObjectToString.call(value);
48961
48962                 if (unmasked) {
48963                   if (isOwn) {
48964                     value[symToStringTag] = tag;
48965                   } else {
48966                     delete value[symToStringTag];
48967                   }
48968                 }
48969
48970                 return result;
48971               }
48972               /**
48973                * Creates an array of the own enumerable symbols of `object`.
48974                *
48975                * @private
48976                * @param {Object} object The object to query.
48977                * @returns {Array} Returns the array of symbols.
48978                */
48979
48980
48981               var getSymbols = !nativeGetSymbols ? stubArray : function (object) {
48982                 if (object == null) {
48983                   return [];
48984                 }
48985
48986                 object = Object(object);
48987                 return arrayFilter(nativeGetSymbols(object), function (symbol) {
48988                   return propertyIsEnumerable.call(object, symbol);
48989                 });
48990               };
48991               /**
48992                * Creates an array of the own and inherited enumerable symbols of `object`.
48993                *
48994                * @private
48995                * @param {Object} object The object to query.
48996                * @returns {Array} Returns the array of symbols.
48997                */
48998
48999               var getSymbolsIn = !nativeGetSymbols ? stubArray : function (object) {
49000                 var result = [];
49001
49002                 while (object) {
49003                   arrayPush(result, getSymbols(object));
49004                   object = getPrototype(object);
49005                 }
49006
49007                 return result;
49008               };
49009               /**
49010                * Gets the `toStringTag` of `value`.
49011                *
49012                * @private
49013                * @param {*} value The value to query.
49014                * @returns {string} Returns the `toStringTag`.
49015                */
49016
49017               var getTag = baseGetTag; // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
49018
49019               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) {
49020                 getTag = function getTag(value) {
49021                   var result = baseGetTag(value),
49022                       Ctor = result == objectTag ? value.constructor : undefined$1,
49023                       ctorString = Ctor ? toSource(Ctor) : '';
49024
49025                   if (ctorString) {
49026                     switch (ctorString) {
49027                       case dataViewCtorString:
49028                         return dataViewTag;
49029
49030                       case mapCtorString:
49031                         return mapTag;
49032
49033                       case promiseCtorString:
49034                         return promiseTag;
49035
49036                       case setCtorString:
49037                         return setTag;
49038
49039                       case weakMapCtorString:
49040                         return weakMapTag;
49041                     }
49042                   }
49043
49044                   return result;
49045                 };
49046               }
49047               /**
49048                * Gets the view, applying any `transforms` to the `start` and `end` positions.
49049                *
49050                * @private
49051                * @param {number} start The start of the view.
49052                * @param {number} end The end of the view.
49053                * @param {Array} transforms The transformations to apply to the view.
49054                * @returns {Object} Returns an object containing the `start` and `end`
49055                *  positions of the view.
49056                */
49057
49058
49059               function getView(start, end, transforms) {
49060                 var index = -1,
49061                     length = transforms.length;
49062
49063                 while (++index < length) {
49064                   var data = transforms[index],
49065                       size = data.size;
49066
49067                   switch (data.type) {
49068                     case 'drop':
49069                       start += size;
49070                       break;
49071
49072                     case 'dropRight':
49073                       end -= size;
49074                       break;
49075
49076                     case 'take':
49077                       end = nativeMin(end, start + size);
49078                       break;
49079
49080                     case 'takeRight':
49081                       start = nativeMax(start, end - size);
49082                       break;
49083                   }
49084                 }
49085
49086                 return {
49087                   'start': start,
49088                   'end': end
49089                 };
49090               }
49091               /**
49092                * Extracts wrapper details from the `source` body comment.
49093                *
49094                * @private
49095                * @param {string} source The source to inspect.
49096                * @returns {Array} Returns the wrapper details.
49097                */
49098
49099
49100               function getWrapDetails(source) {
49101                 var match = source.match(reWrapDetails);
49102                 return match ? match[1].split(reSplitDetails) : [];
49103               }
49104               /**
49105                * Checks if `path` exists on `object`.
49106                *
49107                * @private
49108                * @param {Object} object The object to query.
49109                * @param {Array|string} path The path to check.
49110                * @param {Function} hasFunc The function to check properties.
49111                * @returns {boolean} Returns `true` if `path` exists, else `false`.
49112                */
49113
49114
49115               function hasPath(object, path, hasFunc) {
49116                 path = castPath(path, object);
49117                 var index = -1,
49118                     length = path.length,
49119                     result = false;
49120
49121                 while (++index < length) {
49122                   var key = toKey(path[index]);
49123
49124                   if (!(result = object != null && hasFunc(object, key))) {
49125                     break;
49126                   }
49127
49128                   object = object[key];
49129                 }
49130
49131                 if (result || ++index != length) {
49132                   return result;
49133                 }
49134
49135                 length = object == null ? 0 : object.length;
49136                 return !!length && isLength(length) && isIndex(key, length) && (isArray(object) || isArguments(object));
49137               }
49138               /**
49139                * Initializes an array clone.
49140                *
49141                * @private
49142                * @param {Array} array The array to clone.
49143                * @returns {Array} Returns the initialized clone.
49144                */
49145
49146
49147               function initCloneArray(array) {
49148                 var length = array.length,
49149                     result = new array.constructor(length); // Add properties assigned by `RegExp#exec`.
49150
49151                 if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
49152                   result.index = array.index;
49153                   result.input = array.input;
49154                 }
49155
49156                 return result;
49157               }
49158               /**
49159                * Initializes an object clone.
49160                *
49161                * @private
49162                * @param {Object} object The object to clone.
49163                * @returns {Object} Returns the initialized clone.
49164                */
49165
49166
49167               function initCloneObject(object) {
49168                 return typeof object.constructor == 'function' && !isPrototype(object) ? baseCreate(getPrototype(object)) : {};
49169               }
49170               /**
49171                * Initializes an object clone based on its `toStringTag`.
49172                *
49173                * **Note:** This function only supports cloning values with tags of
49174                * `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`.
49175                *
49176                * @private
49177                * @param {Object} object The object to clone.
49178                * @param {string} tag The `toStringTag` of the object to clone.
49179                * @param {boolean} [isDeep] Specify a deep clone.
49180                * @returns {Object} Returns the initialized clone.
49181                */
49182
49183
49184               function initCloneByTag(object, tag, isDeep) {
49185                 var Ctor = object.constructor;
49186
49187                 switch (tag) {
49188                   case arrayBufferTag:
49189                     return cloneArrayBuffer(object);
49190
49191                   case boolTag:
49192                   case dateTag:
49193                     return new Ctor(+object);
49194
49195                   case dataViewTag:
49196                     return cloneDataView(object, isDeep);
49197
49198                   case float32Tag:
49199                   case float64Tag:
49200                   case int8Tag:
49201                   case int16Tag:
49202                   case int32Tag:
49203                   case uint8Tag:
49204                   case uint8ClampedTag:
49205                   case uint16Tag:
49206                   case uint32Tag:
49207                     return cloneTypedArray(object, isDeep);
49208
49209                   case mapTag:
49210                     return new Ctor();
49211
49212                   case numberTag:
49213                   case stringTag:
49214                     return new Ctor(object);
49215
49216                   case regexpTag:
49217                     return cloneRegExp(object);
49218
49219                   case setTag:
49220                     return new Ctor();
49221
49222                   case symbolTag:
49223                     return cloneSymbol(object);
49224                 }
49225               }
49226               /**
49227                * Inserts wrapper `details` in a comment at the top of the `source` body.
49228                *
49229                * @private
49230                * @param {string} source The source to modify.
49231                * @returns {Array} details The details to insert.
49232                * @returns {string} Returns the modified source.
49233                */
49234
49235
49236               function insertWrapDetails(source, details) {
49237                 var length = details.length;
49238
49239                 if (!length) {
49240                   return source;
49241                 }
49242
49243                 var lastIndex = length - 1;
49244                 details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex];
49245                 details = details.join(length > 2 ? ', ' : ' ');
49246                 return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n');
49247               }
49248               /**
49249                * Checks if `value` is a flattenable `arguments` object or array.
49250                *
49251                * @private
49252                * @param {*} value The value to check.
49253                * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
49254                */
49255
49256
49257               function isFlattenable(value) {
49258                 return isArray(value) || isArguments(value) || !!(spreadableSymbol && value && value[spreadableSymbol]);
49259               }
49260               /**
49261                * Checks if `value` is a valid array-like index.
49262                *
49263                * @private
49264                * @param {*} value The value to check.
49265                * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
49266                * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
49267                */
49268
49269
49270               function isIndex(value, length) {
49271                 var type = _typeof(value);
49272
49273                 length = length == null ? MAX_SAFE_INTEGER : length;
49274                 return !!length && (type == 'number' || type != 'symbol' && reIsUint.test(value)) && value > -1 && value % 1 == 0 && value < length;
49275               }
49276               /**
49277                * Checks if the given arguments are from an iteratee call.
49278                *
49279                * @private
49280                * @param {*} value The potential iteratee value argument.
49281                * @param {*} index The potential iteratee index or key argument.
49282                * @param {*} object The potential iteratee object argument.
49283                * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
49284                *  else `false`.
49285                */
49286
49287
49288               function isIterateeCall(value, index, object) {
49289                 if (!isObject(object)) {
49290                   return false;
49291                 }
49292
49293                 var type = _typeof(index);
49294
49295                 if (type == 'number' ? isArrayLike(object) && isIndex(index, object.length) : type == 'string' && index in object) {
49296                   return eq(object[index], value);
49297                 }
49298
49299                 return false;
49300               }
49301               /**
49302                * Checks if `value` is a property name and not a property path.
49303                *
49304                * @private
49305                * @param {*} value The value to check.
49306                * @param {Object} [object] The object to query keys on.
49307                * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
49308                */
49309
49310
49311               function isKey(value, object) {
49312                 if (isArray(value)) {
49313                   return false;
49314                 }
49315
49316                 var type = _typeof(value);
49317
49318                 if (type == 'number' || type == 'symbol' || type == 'boolean' || value == null || isSymbol(value)) {
49319                   return true;
49320                 }
49321
49322                 return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || object != null && value in Object(object);
49323               }
49324               /**
49325                * Checks if `value` is suitable for use as unique object key.
49326                *
49327                * @private
49328                * @param {*} value The value to check.
49329                * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
49330                */
49331
49332
49333               function isKeyable(value) {
49334                 var type = _typeof(value);
49335
49336                 return type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean' ? value !== '__proto__' : value === null;
49337               }
49338               /**
49339                * Checks if `func` has a lazy counterpart.
49340                *
49341                * @private
49342                * @param {Function} func The function to check.
49343                * @returns {boolean} Returns `true` if `func` has a lazy counterpart,
49344                *  else `false`.
49345                */
49346
49347
49348               function isLaziable(func) {
49349                 var funcName = getFuncName(func),
49350                     other = lodash[funcName];
49351
49352                 if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
49353                   return false;
49354                 }
49355
49356                 if (func === other) {
49357                   return true;
49358                 }
49359
49360                 var data = getData(other);
49361                 return !!data && func === data[0];
49362               }
49363               /**
49364                * Checks if `func` has its source masked.
49365                *
49366                * @private
49367                * @param {Function} func The function to check.
49368                * @returns {boolean} Returns `true` if `func` is masked, else `false`.
49369                */
49370
49371
49372               function isMasked(func) {
49373                 return !!maskSrcKey && maskSrcKey in func;
49374               }
49375               /**
49376                * Checks if `func` is capable of being masked.
49377                *
49378                * @private
49379                * @param {*} value The value to check.
49380                * @returns {boolean} Returns `true` if `func` is maskable, else `false`.
49381                */
49382
49383
49384               var isMaskable = coreJsData ? isFunction : stubFalse;
49385               /**
49386                * Checks if `value` is likely a prototype object.
49387                *
49388                * @private
49389                * @param {*} value The value to check.
49390                * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
49391                */
49392
49393               function isPrototype(value) {
49394                 var Ctor = value && value.constructor,
49395                     proto = typeof Ctor == 'function' && Ctor.prototype || objectProto;
49396                 return value === proto;
49397               }
49398               /**
49399                * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
49400                *
49401                * @private
49402                * @param {*} value The value to check.
49403                * @returns {boolean} Returns `true` if `value` if suitable for strict
49404                *  equality comparisons, else `false`.
49405                */
49406
49407
49408               function isStrictComparable(value) {
49409                 return value === value && !isObject(value);
49410               }
49411               /**
49412                * A specialized version of `matchesProperty` for source values suitable
49413                * for strict equality comparisons, i.e. `===`.
49414                *
49415                * @private
49416                * @param {string} key The key of the property to get.
49417                * @param {*} srcValue The value to match.
49418                * @returns {Function} Returns the new spec function.
49419                */
49420
49421
49422               function matchesStrictComparable(key, srcValue) {
49423                 return function (object) {
49424                   if (object == null) {
49425                     return false;
49426                   }
49427
49428                   return object[key] === srcValue && (srcValue !== undefined$1 || key in Object(object));
49429                 };
49430               }
49431               /**
49432                * A specialized version of `_.memoize` which clears the memoized function's
49433                * cache when it exceeds `MAX_MEMOIZE_SIZE`.
49434                *
49435                * @private
49436                * @param {Function} func The function to have its output memoized.
49437                * @returns {Function} Returns the new memoized function.
49438                */
49439
49440
49441               function memoizeCapped(func) {
49442                 var result = memoize(func, function (key) {
49443                   if (cache.size === MAX_MEMOIZE_SIZE) {
49444                     cache.clear();
49445                   }
49446
49447                   return key;
49448                 });
49449                 var cache = result.cache;
49450                 return result;
49451               }
49452               /**
49453                * Merges the function metadata of `source` into `data`.
49454                *
49455                * Merging metadata reduces the number of wrappers used to invoke a function.
49456                * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
49457                * may be applied regardless of execution order. Methods like `_.ary` and
49458                * `_.rearg` modify function arguments, making the order in which they are
49459                * executed important, preventing the merging of metadata. However, we make
49460                * an exception for a safe combined case where curried functions have `_.ary`
49461                * and or `_.rearg` applied.
49462                *
49463                * @private
49464                * @param {Array} data The destination metadata.
49465                * @param {Array} source The source metadata.
49466                * @returns {Array} Returns `data`.
49467                */
49468
49469
49470               function mergeData(data, source) {
49471                 var bitmask = data[1],
49472                     srcBitmask = source[1],
49473                     newBitmask = bitmask | srcBitmask,
49474                     isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);
49475                 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.
49476
49477                 if (!(isCommon || isCombo)) {
49478                   return data;
49479                 } // Use source `thisArg` if available.
49480
49481
49482                 if (srcBitmask & WRAP_BIND_FLAG) {
49483                   data[2] = source[2]; // Set when currying a bound function.
49484
49485                   newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;
49486                 } // Compose partial arguments.
49487
49488
49489                 var value = source[3];
49490
49491                 if (value) {
49492                   var partials = data[3];
49493                   data[3] = partials ? composeArgs(partials, value, source[4]) : value;
49494                   data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
49495                 } // Compose partial right arguments.
49496
49497
49498                 value = source[5];
49499
49500                 if (value) {
49501                   partials = data[5];
49502                   data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
49503                   data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
49504                 } // Use source `argPos` if available.
49505
49506
49507                 value = source[7];
49508
49509                 if (value) {
49510                   data[7] = value;
49511                 } // Use source `ary` if it's smaller.
49512
49513
49514                 if (srcBitmask & WRAP_ARY_FLAG) {
49515                   data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
49516                 } // Use source `arity` if one is not provided.
49517
49518
49519                 if (data[9] == null) {
49520                   data[9] = source[9];
49521                 } // Use source `func` and merge bitmasks.
49522
49523
49524                 data[0] = source[0];
49525                 data[1] = newBitmask;
49526                 return data;
49527               }
49528               /**
49529                * This function is like
49530                * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
49531                * except that it includes inherited enumerable properties.
49532                *
49533                * @private
49534                * @param {Object} object The object to query.
49535                * @returns {Array} Returns the array of property names.
49536                */
49537
49538
49539               function nativeKeysIn(object) {
49540                 var result = [];
49541
49542                 if (object != null) {
49543                   for (var key in Object(object)) {
49544                     result.push(key);
49545                   }
49546                 }
49547
49548                 return result;
49549               }
49550               /**
49551                * Converts `value` to a string using `Object.prototype.toString`.
49552                *
49553                * @private
49554                * @param {*} value The value to convert.
49555                * @returns {string} Returns the converted string.
49556                */
49557
49558
49559               function objectToString(value) {
49560                 return nativeObjectToString.call(value);
49561               }
49562               /**
49563                * A specialized version of `baseRest` which transforms the rest array.
49564                *
49565                * @private
49566                * @param {Function} func The function to apply a rest parameter to.
49567                * @param {number} [start=func.length-1] The start position of the rest parameter.
49568                * @param {Function} transform The rest array transform.
49569                * @returns {Function} Returns the new function.
49570                */
49571
49572
49573               function overRest(func, start, transform) {
49574                 start = nativeMax(start === undefined$1 ? func.length - 1 : start, 0);
49575                 return function () {
49576                   var args = arguments,
49577                       index = -1,
49578                       length = nativeMax(args.length - start, 0),
49579                       array = Array(length);
49580
49581                   while (++index < length) {
49582                     array[index] = args[start + index];
49583                   }
49584
49585                   index = -1;
49586                   var otherArgs = Array(start + 1);
49587
49588                   while (++index < start) {
49589                     otherArgs[index] = args[index];
49590                   }
49591
49592                   otherArgs[start] = transform(array);
49593                   return apply(func, this, otherArgs);
49594                 };
49595               }
49596               /**
49597                * Gets the parent value at `path` of `object`.
49598                *
49599                * @private
49600                * @param {Object} object The object to query.
49601                * @param {Array} path The path to get the parent value of.
49602                * @returns {*} Returns the parent value.
49603                */
49604
49605
49606               function parent(object, path) {
49607                 return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
49608               }
49609               /**
49610                * Reorder `array` according to the specified indexes where the element at
49611                * the first index is assigned as the first element, the element at
49612                * the second index is assigned as the second element, and so on.
49613                *
49614                * @private
49615                * @param {Array} array The array to reorder.
49616                * @param {Array} indexes The arranged array indexes.
49617                * @returns {Array} Returns `array`.
49618                */
49619
49620
49621               function reorder(array, indexes) {
49622                 var arrLength = array.length,
49623                     length = nativeMin(indexes.length, arrLength),
49624                     oldArray = copyArray(array);
49625
49626                 while (length--) {
49627                   var index = indexes[length];
49628                   array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined$1;
49629                 }
49630
49631                 return array;
49632               }
49633               /**
49634                * Gets the value at `key`, unless `key` is "__proto__" or "constructor".
49635                *
49636                * @private
49637                * @param {Object} object The object to query.
49638                * @param {string} key The key of the property to get.
49639                * @returns {*} Returns the property value.
49640                */
49641
49642
49643               function safeGet(object, key) {
49644                 if (key === 'constructor' && typeof object[key] === 'function') {
49645                   return;
49646                 }
49647
49648                 if (key == '__proto__') {
49649                   return;
49650                 }
49651
49652                 return object[key];
49653               }
49654               /**
49655                * Sets metadata for `func`.
49656                *
49657                * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
49658                * period of time, it will trip its breaker and transition to an identity
49659                * function to avoid garbage collection pauses in V8. See
49660                * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070)
49661                * for more details.
49662                *
49663                * @private
49664                * @param {Function} func The function to associate metadata with.
49665                * @param {*} data The metadata.
49666                * @returns {Function} Returns `func`.
49667                */
49668
49669
49670               var setData = shortOut(baseSetData);
49671               /**
49672                * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout).
49673                *
49674                * @private
49675                * @param {Function} func The function to delay.
49676                * @param {number} wait The number of milliseconds to delay invocation.
49677                * @returns {number|Object} Returns the timer id or timeout object.
49678                */
49679
49680               var setTimeout = ctxSetTimeout || function (func, wait) {
49681                 return root.setTimeout(func, wait);
49682               };
49683               /**
49684                * Sets the `toString` method of `func` to return `string`.
49685                *
49686                * @private
49687                * @param {Function} func The function to modify.
49688                * @param {Function} string The `toString` result.
49689                * @returns {Function} Returns `func`.
49690                */
49691
49692
49693               var setToString = shortOut(baseSetToString);
49694               /**
49695                * Sets the `toString` method of `wrapper` to mimic the source of `reference`
49696                * with wrapper details in a comment at the top of the source body.
49697                *
49698                * @private
49699                * @param {Function} wrapper The function to modify.
49700                * @param {Function} reference The reference function.
49701                * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
49702                * @returns {Function} Returns `wrapper`.
49703                */
49704
49705               function setWrapToString(wrapper, reference, bitmask) {
49706                 var source = reference + '';
49707                 return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));
49708               }
49709               /**
49710                * Creates a function that'll short out and invoke `identity` instead
49711                * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
49712                * milliseconds.
49713                *
49714                * @private
49715                * @param {Function} func The function to restrict.
49716                * @returns {Function} Returns the new shortable function.
49717                */
49718
49719
49720               function shortOut(func) {
49721                 var count = 0,
49722                     lastCalled = 0;
49723                 return function () {
49724                   var stamp = nativeNow(),
49725                       remaining = HOT_SPAN - (stamp - lastCalled);
49726                   lastCalled = stamp;
49727
49728                   if (remaining > 0) {
49729                     if (++count >= HOT_COUNT) {
49730                       return arguments[0];
49731                     }
49732                   } else {
49733                     count = 0;
49734                   }
49735
49736                   return func.apply(undefined$1, arguments);
49737                 };
49738               }
49739               /**
49740                * A specialized version of `_.shuffle` which mutates and sets the size of `array`.
49741                *
49742                * @private
49743                * @param {Array} array The array to shuffle.
49744                * @param {number} [size=array.length] The size of `array`.
49745                * @returns {Array} Returns `array`.
49746                */
49747
49748
49749               function shuffleSelf(array, size) {
49750                 var index = -1,
49751                     length = array.length,
49752                     lastIndex = length - 1;
49753                 size = size === undefined$1 ? length : size;
49754
49755                 while (++index < size) {
49756                   var rand = baseRandom(index, lastIndex),
49757                       value = array[rand];
49758                   array[rand] = array[index];
49759                   array[index] = value;
49760                 }
49761
49762                 array.length = size;
49763                 return array;
49764               }
49765               /**
49766                * Converts `string` to a property path array.
49767                *
49768                * @private
49769                * @param {string} string The string to convert.
49770                * @returns {Array} Returns the property path array.
49771                */
49772
49773
49774               var stringToPath = memoizeCapped(function (string) {
49775                 var result = [];
49776
49777                 if (string.charCodeAt(0) === 46
49778                 /* . */
49779                 ) {
49780                   result.push('');
49781                 }
49782
49783                 string.replace(rePropName, function (match, number, quote, subString) {
49784                   result.push(quote ? subString.replace(reEscapeChar, '$1') : number || match);
49785                 });
49786                 return result;
49787               });
49788               /**
49789                * Converts `value` to a string key if it's not a string or symbol.
49790                *
49791                * @private
49792                * @param {*} value The value to inspect.
49793                * @returns {string|symbol} Returns the key.
49794                */
49795
49796               function toKey(value) {
49797                 if (typeof value == 'string' || isSymbol(value)) {
49798                   return value;
49799                 }
49800
49801                 var result = value + '';
49802                 return result == '0' && 1 / value == -INFINITY ? '-0' : result;
49803               }
49804               /**
49805                * Converts `func` to its source code.
49806                *
49807                * @private
49808                * @param {Function} func The function to convert.
49809                * @returns {string} Returns the source code.
49810                */
49811
49812
49813               function toSource(func) {
49814                 if (func != null) {
49815                   try {
49816                     return funcToString.call(func);
49817                   } catch (e) {}
49818
49819                   try {
49820                     return func + '';
49821                   } catch (e) {}
49822                 }
49823
49824                 return '';
49825               }
49826               /**
49827                * Updates wrapper `details` based on `bitmask` flags.
49828                *
49829                * @private
49830                * @returns {Array} details The details to modify.
49831                * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
49832                * @returns {Array} Returns `details`.
49833                */
49834
49835
49836               function updateWrapDetails(details, bitmask) {
49837                 arrayEach(wrapFlags, function (pair) {
49838                   var value = '_.' + pair[0];
49839
49840                   if (bitmask & pair[1] && !arrayIncludes(details, value)) {
49841                     details.push(value);
49842                   }
49843                 });
49844                 return details.sort();
49845               }
49846               /**
49847                * Creates a clone of `wrapper`.
49848                *
49849                * @private
49850                * @param {Object} wrapper The wrapper to clone.
49851                * @returns {Object} Returns the cloned wrapper.
49852                */
49853
49854
49855               function wrapperClone(wrapper) {
49856                 if (wrapper instanceof LazyWrapper) {
49857                   return wrapper.clone();
49858                 }
49859
49860                 var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
49861                 result.__actions__ = copyArray(wrapper.__actions__);
49862                 result.__index__ = wrapper.__index__;
49863                 result.__values__ = wrapper.__values__;
49864                 return result;
49865               }
49866               /*------------------------------------------------------------------------*/
49867
49868               /**
49869                * Creates an array of elements split into groups the length of `size`.
49870                * If `array` can't be split evenly, the final chunk will be the remaining
49871                * elements.
49872                *
49873                * @static
49874                * @memberOf _
49875                * @since 3.0.0
49876                * @category Array
49877                * @param {Array} array The array to process.
49878                * @param {number} [size=1] The length of each chunk
49879                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
49880                * @returns {Array} Returns the new array of chunks.
49881                * @example
49882                *
49883                * _.chunk(['a', 'b', 'c', 'd'], 2);
49884                * // => [['a', 'b'], ['c', 'd']]
49885                *
49886                * _.chunk(['a', 'b', 'c', 'd'], 3);
49887                * // => [['a', 'b', 'c'], ['d']]
49888                */
49889
49890
49891               function chunk(array, size, guard) {
49892                 if (guard ? isIterateeCall(array, size, guard) : size === undefined$1) {
49893                   size = 1;
49894                 } else {
49895                   size = nativeMax(toInteger(size), 0);
49896                 }
49897
49898                 var length = array == null ? 0 : array.length;
49899
49900                 if (!length || size < 1) {
49901                   return [];
49902                 }
49903
49904                 var index = 0,
49905                     resIndex = 0,
49906                     result = Array(nativeCeil(length / size));
49907
49908                 while (index < length) {
49909                   result[resIndex++] = baseSlice(array, index, index += size);
49910                 }
49911
49912                 return result;
49913               }
49914               /**
49915                * Creates an array with all falsey values removed. The values `false`, `null`,
49916                * `0`, `""`, `undefined`, and `NaN` are falsey.
49917                *
49918                * @static
49919                * @memberOf _
49920                * @since 0.1.0
49921                * @category Array
49922                * @param {Array} array The array to compact.
49923                * @returns {Array} Returns the new array of filtered values.
49924                * @example
49925                *
49926                * _.compact([0, 1, false, 2, '', 3]);
49927                * // => [1, 2, 3]
49928                */
49929
49930
49931               function compact(array) {
49932                 var index = -1,
49933                     length = array == null ? 0 : array.length,
49934                     resIndex = 0,
49935                     result = [];
49936
49937                 while (++index < length) {
49938                   var value = array[index];
49939
49940                   if (value) {
49941                     result[resIndex++] = value;
49942                   }
49943                 }
49944
49945                 return result;
49946               }
49947               /**
49948                * Creates a new array concatenating `array` with any additional arrays
49949                * and/or values.
49950                *
49951                * @static
49952                * @memberOf _
49953                * @since 4.0.0
49954                * @category Array
49955                * @param {Array} array The array to concatenate.
49956                * @param {...*} [values] The values to concatenate.
49957                * @returns {Array} Returns the new concatenated array.
49958                * @example
49959                *
49960                * var array = [1];
49961                * var other = _.concat(array, 2, [3], [[4]]);
49962                *
49963                * console.log(other);
49964                * // => [1, 2, 3, [4]]
49965                *
49966                * console.log(array);
49967                * // => [1]
49968                */
49969
49970
49971               function concat() {
49972                 var length = arguments.length;
49973
49974                 if (!length) {
49975                   return [];
49976                 }
49977
49978                 var args = Array(length - 1),
49979                     array = arguments[0],
49980                     index = length;
49981
49982                 while (index--) {
49983                   args[index - 1] = arguments[index];
49984                 }
49985
49986                 return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
49987               }
49988               /**
49989                * Creates an array of `array` values not included in the other given arrays
49990                * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
49991                * for equality comparisons. The order and references of result values are
49992                * determined by the first array.
49993                *
49994                * **Note:** Unlike `_.pullAll`, this method returns a new array.
49995                *
49996                * @static
49997                * @memberOf _
49998                * @since 0.1.0
49999                * @category Array
50000                * @param {Array} array The array to inspect.
50001                * @param {...Array} [values] The values to exclude.
50002                * @returns {Array} Returns the new array of filtered values.
50003                * @see _.without, _.xor
50004                * @example
50005                *
50006                * _.difference([2, 1], [2, 3]);
50007                * // => [1]
50008                */
50009
50010
50011               var difference = baseRest(function (array, values) {
50012                 return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true)) : [];
50013               });
50014               /**
50015                * This method is like `_.difference` except that it accepts `iteratee` which
50016                * is invoked for each element of `array` and `values` to generate the criterion
50017                * by which they're compared. The order and references of result values are
50018                * determined by the first array. The iteratee is invoked with one argument:
50019                * (value).
50020                *
50021                * **Note:** Unlike `_.pullAllBy`, this method returns a new array.
50022                *
50023                * @static
50024                * @memberOf _
50025                * @since 4.0.0
50026                * @category Array
50027                * @param {Array} array The array to inspect.
50028                * @param {...Array} [values] The values to exclude.
50029                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
50030                * @returns {Array} Returns the new array of filtered values.
50031                * @example
50032                *
50033                * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor);
50034                * // => [1.2]
50035                *
50036                * // The `_.property` iteratee shorthand.
50037                * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
50038                * // => [{ 'x': 2 }]
50039                */
50040
50041               var differenceBy = baseRest(function (array, values) {
50042                 var iteratee = last(values);
50043
50044                 if (isArrayLikeObject(iteratee)) {
50045                   iteratee = undefined$1;
50046                 }
50047
50048                 return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)) : [];
50049               });
50050               /**
50051                * This method is like `_.difference` except that it accepts `comparator`
50052                * which is invoked to compare elements of `array` to `values`. The order and
50053                * references of result values are determined by the first array. The comparator
50054                * is invoked with two arguments: (arrVal, othVal).
50055                *
50056                * **Note:** Unlike `_.pullAllWith`, this method returns a new array.
50057                *
50058                * @static
50059                * @memberOf _
50060                * @since 4.0.0
50061                * @category Array
50062                * @param {Array} array The array to inspect.
50063                * @param {...Array} [values] The values to exclude.
50064                * @param {Function} [comparator] The comparator invoked per element.
50065                * @returns {Array} Returns the new array of filtered values.
50066                * @example
50067                *
50068                * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
50069                *
50070                * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
50071                * // => [{ 'x': 2, 'y': 1 }]
50072                */
50073
50074               var differenceWith = baseRest(function (array, values) {
50075                 var comparator = last(values);
50076
50077                 if (isArrayLikeObject(comparator)) {
50078                   comparator = undefined$1;
50079                 }
50080
50081                 return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined$1, comparator) : [];
50082               });
50083               /**
50084                * Creates a slice of `array` with `n` elements dropped from the beginning.
50085                *
50086                * @static
50087                * @memberOf _
50088                * @since 0.5.0
50089                * @category Array
50090                * @param {Array} array The array to query.
50091                * @param {number} [n=1] The number of elements to drop.
50092                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
50093                * @returns {Array} Returns the slice of `array`.
50094                * @example
50095                *
50096                * _.drop([1, 2, 3]);
50097                * // => [2, 3]
50098                *
50099                * _.drop([1, 2, 3], 2);
50100                * // => [3]
50101                *
50102                * _.drop([1, 2, 3], 5);
50103                * // => []
50104                *
50105                * _.drop([1, 2, 3], 0);
50106                * // => [1, 2, 3]
50107                */
50108
50109               function drop(array, n, guard) {
50110                 var length = array == null ? 0 : array.length;
50111
50112                 if (!length) {
50113                   return [];
50114                 }
50115
50116                 n = guard || n === undefined$1 ? 1 : toInteger(n);
50117                 return baseSlice(array, n < 0 ? 0 : n, length);
50118               }
50119               /**
50120                * Creates a slice of `array` with `n` elements dropped from the end.
50121                *
50122                * @static
50123                * @memberOf _
50124                * @since 3.0.0
50125                * @category Array
50126                * @param {Array} array The array to query.
50127                * @param {number} [n=1] The number of elements to drop.
50128                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
50129                * @returns {Array} Returns the slice of `array`.
50130                * @example
50131                *
50132                * _.dropRight([1, 2, 3]);
50133                * // => [1, 2]
50134                *
50135                * _.dropRight([1, 2, 3], 2);
50136                * // => [1]
50137                *
50138                * _.dropRight([1, 2, 3], 5);
50139                * // => []
50140                *
50141                * _.dropRight([1, 2, 3], 0);
50142                * // => [1, 2, 3]
50143                */
50144
50145
50146               function dropRight(array, n, guard) {
50147                 var length = array == null ? 0 : array.length;
50148
50149                 if (!length) {
50150                   return [];
50151                 }
50152
50153                 n = guard || n === undefined$1 ? 1 : toInteger(n);
50154                 n = length - n;
50155                 return baseSlice(array, 0, n < 0 ? 0 : n);
50156               }
50157               /**
50158                * Creates a slice of `array` excluding elements dropped from the end.
50159                * Elements are dropped until `predicate` returns falsey. The predicate is
50160                * invoked with three arguments: (value, index, array).
50161                *
50162                * @static
50163                * @memberOf _
50164                * @since 3.0.0
50165                * @category Array
50166                * @param {Array} array The array to query.
50167                * @param {Function} [predicate=_.identity] The function invoked per iteration.
50168                * @returns {Array} Returns the slice of `array`.
50169                * @example
50170                *
50171                * var users = [
50172                *   { 'user': 'barney',  'active': true },
50173                *   { 'user': 'fred',    'active': false },
50174                *   { 'user': 'pebbles', 'active': false }
50175                * ];
50176                *
50177                * _.dropRightWhile(users, function(o) { return !o.active; });
50178                * // => objects for ['barney']
50179                *
50180                * // The `_.matches` iteratee shorthand.
50181                * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });
50182                * // => objects for ['barney', 'fred']
50183                *
50184                * // The `_.matchesProperty` iteratee shorthand.
50185                * _.dropRightWhile(users, ['active', false]);
50186                * // => objects for ['barney']
50187                *
50188                * // The `_.property` iteratee shorthand.
50189                * _.dropRightWhile(users, 'active');
50190                * // => objects for ['barney', 'fred', 'pebbles']
50191                */
50192
50193
50194               function dropRightWhile(array, predicate) {
50195                 return array && array.length ? baseWhile(array, getIteratee(predicate, 3), true, true) : [];
50196               }
50197               /**
50198                * Creates a slice of `array` excluding elements dropped from the beginning.
50199                * Elements are dropped until `predicate` returns falsey. The predicate is
50200                * invoked with three arguments: (value, index, array).
50201                *
50202                * @static
50203                * @memberOf _
50204                * @since 3.0.0
50205                * @category Array
50206                * @param {Array} array The array to query.
50207                * @param {Function} [predicate=_.identity] The function invoked per iteration.
50208                * @returns {Array} Returns the slice of `array`.
50209                * @example
50210                *
50211                * var users = [
50212                *   { 'user': 'barney',  'active': false },
50213                *   { 'user': 'fred',    'active': false },
50214                *   { 'user': 'pebbles', 'active': true }
50215                * ];
50216                *
50217                * _.dropWhile(users, function(o) { return !o.active; });
50218                * // => objects for ['pebbles']
50219                *
50220                * // The `_.matches` iteratee shorthand.
50221                * _.dropWhile(users, { 'user': 'barney', 'active': false });
50222                * // => objects for ['fred', 'pebbles']
50223                *
50224                * // The `_.matchesProperty` iteratee shorthand.
50225                * _.dropWhile(users, ['active', false]);
50226                * // => objects for ['pebbles']
50227                *
50228                * // The `_.property` iteratee shorthand.
50229                * _.dropWhile(users, 'active');
50230                * // => objects for ['barney', 'fred', 'pebbles']
50231                */
50232
50233
50234               function dropWhile(array, predicate) {
50235                 return array && array.length ? baseWhile(array, getIteratee(predicate, 3), true) : [];
50236               }
50237               /**
50238                * Fills elements of `array` with `value` from `start` up to, but not
50239                * including, `end`.
50240                *
50241                * **Note:** This method mutates `array`.
50242                *
50243                * @static
50244                * @memberOf _
50245                * @since 3.2.0
50246                * @category Array
50247                * @param {Array} array The array to fill.
50248                * @param {*} value The value to fill `array` with.
50249                * @param {number} [start=0] The start position.
50250                * @param {number} [end=array.length] The end position.
50251                * @returns {Array} Returns `array`.
50252                * @example
50253                *
50254                * var array = [1, 2, 3];
50255                *
50256                * _.fill(array, 'a');
50257                * console.log(array);
50258                * // => ['a', 'a', 'a']
50259                *
50260                * _.fill(Array(3), 2);
50261                * // => [2, 2, 2]
50262                *
50263                * _.fill([4, 6, 8, 10], '*', 1, 3);
50264                * // => [4, '*', '*', 10]
50265                */
50266
50267
50268               function fill(array, value, start, end) {
50269                 var length = array == null ? 0 : array.length;
50270
50271                 if (!length) {
50272                   return [];
50273                 }
50274
50275                 if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
50276                   start = 0;
50277                   end = length;
50278                 }
50279
50280                 return baseFill(array, value, start, end);
50281               }
50282               /**
50283                * This method is like `_.find` except that it returns the index of the first
50284                * element `predicate` returns truthy for instead of the element itself.
50285                *
50286                * @static
50287                * @memberOf _
50288                * @since 1.1.0
50289                * @category Array
50290                * @param {Array} array The array to inspect.
50291                * @param {Function} [predicate=_.identity] The function invoked per iteration.
50292                * @param {number} [fromIndex=0] The index to search from.
50293                * @returns {number} Returns the index of the found element, else `-1`.
50294                * @example
50295                *
50296                * var users = [
50297                *   { 'user': 'barney',  'active': false },
50298                *   { 'user': 'fred',    'active': false },
50299                *   { 'user': 'pebbles', 'active': true }
50300                * ];
50301                *
50302                * _.findIndex(users, function(o) { return o.user == 'barney'; });
50303                * // => 0
50304                *
50305                * // The `_.matches` iteratee shorthand.
50306                * _.findIndex(users, { 'user': 'fred', 'active': false });
50307                * // => 1
50308                *
50309                * // The `_.matchesProperty` iteratee shorthand.
50310                * _.findIndex(users, ['active', false]);
50311                * // => 0
50312                *
50313                * // The `_.property` iteratee shorthand.
50314                * _.findIndex(users, 'active');
50315                * // => 2
50316                */
50317
50318
50319               function findIndex(array, predicate, fromIndex) {
50320                 var length = array == null ? 0 : array.length;
50321
50322                 if (!length) {
50323                   return -1;
50324                 }
50325
50326                 var index = fromIndex == null ? 0 : toInteger(fromIndex);
50327
50328                 if (index < 0) {
50329                   index = nativeMax(length + index, 0);
50330                 }
50331
50332                 return baseFindIndex(array, getIteratee(predicate, 3), index);
50333               }
50334               /**
50335                * This method is like `_.findIndex` except that it iterates over elements
50336                * of `collection` from right to left.
50337                *
50338                * @static
50339                * @memberOf _
50340                * @since 2.0.0
50341                * @category Array
50342                * @param {Array} array The array to inspect.
50343                * @param {Function} [predicate=_.identity] The function invoked per iteration.
50344                * @param {number} [fromIndex=array.length-1] The index to search from.
50345                * @returns {number} Returns the index of the found element, else `-1`.
50346                * @example
50347                *
50348                * var users = [
50349                *   { 'user': 'barney',  'active': true },
50350                *   { 'user': 'fred',    'active': false },
50351                *   { 'user': 'pebbles', 'active': false }
50352                * ];
50353                *
50354                * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });
50355                * // => 2
50356                *
50357                * // The `_.matches` iteratee shorthand.
50358                * _.findLastIndex(users, { 'user': 'barney', 'active': true });
50359                * // => 0
50360                *
50361                * // The `_.matchesProperty` iteratee shorthand.
50362                * _.findLastIndex(users, ['active', false]);
50363                * // => 2
50364                *
50365                * // The `_.property` iteratee shorthand.
50366                * _.findLastIndex(users, 'active');
50367                * // => 0
50368                */
50369
50370
50371               function findLastIndex(array, predicate, fromIndex) {
50372                 var length = array == null ? 0 : array.length;
50373
50374                 if (!length) {
50375                   return -1;
50376                 }
50377
50378                 var index = length - 1;
50379
50380                 if (fromIndex !== undefined$1) {
50381                   index = toInteger(fromIndex);
50382                   index = fromIndex < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
50383                 }
50384
50385                 return baseFindIndex(array, getIteratee(predicate, 3), index, true);
50386               }
50387               /**
50388                * Flattens `array` a single level deep.
50389                *
50390                * @static
50391                * @memberOf _
50392                * @since 0.1.0
50393                * @category Array
50394                * @param {Array} array The array to flatten.
50395                * @returns {Array} Returns the new flattened array.
50396                * @example
50397                *
50398                * _.flatten([1, [2, [3, [4]], 5]]);
50399                * // => [1, 2, [3, [4]], 5]
50400                */
50401
50402
50403               function flatten(array) {
50404                 var length = array == null ? 0 : array.length;
50405                 return length ? baseFlatten(array, 1) : [];
50406               }
50407               /**
50408                * Recursively flattens `array`.
50409                *
50410                * @static
50411                * @memberOf _
50412                * @since 3.0.0
50413                * @category Array
50414                * @param {Array} array The array to flatten.
50415                * @returns {Array} Returns the new flattened array.
50416                * @example
50417                *
50418                * _.flattenDeep([1, [2, [3, [4]], 5]]);
50419                * // => [1, 2, 3, 4, 5]
50420                */
50421
50422
50423               function flattenDeep(array) {
50424                 var length = array == null ? 0 : array.length;
50425                 return length ? baseFlatten(array, INFINITY) : [];
50426               }
50427               /**
50428                * Recursively flatten `array` up to `depth` times.
50429                *
50430                * @static
50431                * @memberOf _
50432                * @since 4.4.0
50433                * @category Array
50434                * @param {Array} array The array to flatten.
50435                * @param {number} [depth=1] The maximum recursion depth.
50436                * @returns {Array} Returns the new flattened array.
50437                * @example
50438                *
50439                * var array = [1, [2, [3, [4]], 5]];
50440                *
50441                * _.flattenDepth(array, 1);
50442                * // => [1, 2, [3, [4]], 5]
50443                *
50444                * _.flattenDepth(array, 2);
50445                * // => [1, 2, 3, [4], 5]
50446                */
50447
50448
50449               function flattenDepth(array, depth) {
50450                 var length = array == null ? 0 : array.length;
50451
50452                 if (!length) {
50453                   return [];
50454                 }
50455
50456                 depth = depth === undefined$1 ? 1 : toInteger(depth);
50457                 return baseFlatten(array, depth);
50458               }
50459               /**
50460                * The inverse of `_.toPairs`; this method returns an object composed
50461                * from key-value `pairs`.
50462                *
50463                * @static
50464                * @memberOf _
50465                * @since 4.0.0
50466                * @category Array
50467                * @param {Array} pairs The key-value pairs.
50468                * @returns {Object} Returns the new object.
50469                * @example
50470                *
50471                * _.fromPairs([['a', 1], ['b', 2]]);
50472                * // => { 'a': 1, 'b': 2 }
50473                */
50474
50475
50476               function fromPairs(pairs) {
50477                 var index = -1,
50478                     length = pairs == null ? 0 : pairs.length,
50479                     result = {};
50480
50481                 while (++index < length) {
50482                   var pair = pairs[index];
50483                   result[pair[0]] = pair[1];
50484                 }
50485
50486                 return result;
50487               }
50488               /**
50489                * Gets the first element of `array`.
50490                *
50491                * @static
50492                * @memberOf _
50493                * @since 0.1.0
50494                * @alias first
50495                * @category Array
50496                * @param {Array} array The array to query.
50497                * @returns {*} Returns the first element of `array`.
50498                * @example
50499                *
50500                * _.head([1, 2, 3]);
50501                * // => 1
50502                *
50503                * _.head([]);
50504                * // => undefined
50505                */
50506
50507
50508               function head(array) {
50509                 return array && array.length ? array[0] : undefined$1;
50510               }
50511               /**
50512                * Gets the index at which the first occurrence of `value` is found in `array`
50513                * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
50514                * for equality comparisons. If `fromIndex` is negative, it's used as the
50515                * offset from the end of `array`.
50516                *
50517                * @static
50518                * @memberOf _
50519                * @since 0.1.0
50520                * @category Array
50521                * @param {Array} array The array to inspect.
50522                * @param {*} value The value to search for.
50523                * @param {number} [fromIndex=0] The index to search from.
50524                * @returns {number} Returns the index of the matched value, else `-1`.
50525                * @example
50526                *
50527                * _.indexOf([1, 2, 1, 2], 2);
50528                * // => 1
50529                *
50530                * // Search from the `fromIndex`.
50531                * _.indexOf([1, 2, 1, 2], 2, 2);
50532                * // => 3
50533                */
50534
50535
50536               function indexOf(array, value, fromIndex) {
50537                 var length = array == null ? 0 : array.length;
50538
50539                 if (!length) {
50540                   return -1;
50541                 }
50542
50543                 var index = fromIndex == null ? 0 : toInteger(fromIndex);
50544
50545                 if (index < 0) {
50546                   index = nativeMax(length + index, 0);
50547                 }
50548
50549                 return baseIndexOf(array, value, index);
50550               }
50551               /**
50552                * Gets all but the last element of `array`.
50553                *
50554                * @static
50555                * @memberOf _
50556                * @since 0.1.0
50557                * @category Array
50558                * @param {Array} array The array to query.
50559                * @returns {Array} Returns the slice of `array`.
50560                * @example
50561                *
50562                * _.initial([1, 2, 3]);
50563                * // => [1, 2]
50564                */
50565
50566
50567               function initial(array) {
50568                 var length = array == null ? 0 : array.length;
50569                 return length ? baseSlice(array, 0, -1) : [];
50570               }
50571               /**
50572                * Creates an array of unique values that are included in all given arrays
50573                * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
50574                * for equality comparisons. The order and references of result values are
50575                * determined by the first array.
50576                *
50577                * @static
50578                * @memberOf _
50579                * @since 0.1.0
50580                * @category Array
50581                * @param {...Array} [arrays] The arrays to inspect.
50582                * @returns {Array} Returns the new array of intersecting values.
50583                * @example
50584                *
50585                * _.intersection([2, 1], [2, 3]);
50586                * // => [2]
50587                */
50588
50589
50590               var intersection = baseRest(function (arrays) {
50591                 var mapped = arrayMap(arrays, castArrayLikeObject);
50592                 return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped) : [];
50593               });
50594               /**
50595                * This method is like `_.intersection` except that it accepts `iteratee`
50596                * which is invoked for each element of each `arrays` to generate the criterion
50597                * by which they're compared. The order and references of result values are
50598                * determined by the first array. The iteratee is invoked with one argument:
50599                * (value).
50600                *
50601                * @static
50602                * @memberOf _
50603                * @since 4.0.0
50604                * @category Array
50605                * @param {...Array} [arrays] The arrays to inspect.
50606                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
50607                * @returns {Array} Returns the new array of intersecting values.
50608                * @example
50609                *
50610                * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor);
50611                * // => [2.1]
50612                *
50613                * // The `_.property` iteratee shorthand.
50614                * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
50615                * // => [{ 'x': 1 }]
50616                */
50617
50618               var intersectionBy = baseRest(function (arrays) {
50619                 var iteratee = last(arrays),
50620                     mapped = arrayMap(arrays, castArrayLikeObject);
50621
50622                 if (iteratee === last(mapped)) {
50623                   iteratee = undefined$1;
50624                 } else {
50625                   mapped.pop();
50626                 }
50627
50628                 return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, getIteratee(iteratee, 2)) : [];
50629               });
50630               /**
50631                * This method is like `_.intersection` except that it accepts `comparator`
50632                * which is invoked to compare elements of `arrays`. The order and references
50633                * of result values are determined by the first array. The comparator is
50634                * invoked with two arguments: (arrVal, othVal).
50635                *
50636                * @static
50637                * @memberOf _
50638                * @since 4.0.0
50639                * @category Array
50640                * @param {...Array} [arrays] The arrays to inspect.
50641                * @param {Function} [comparator] The comparator invoked per element.
50642                * @returns {Array} Returns the new array of intersecting values.
50643                * @example
50644                *
50645                * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
50646                * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
50647                *
50648                * _.intersectionWith(objects, others, _.isEqual);
50649                * // => [{ 'x': 1, 'y': 2 }]
50650                */
50651
50652               var intersectionWith = baseRest(function (arrays) {
50653                 var comparator = last(arrays),
50654                     mapped = arrayMap(arrays, castArrayLikeObject);
50655                 comparator = typeof comparator == 'function' ? comparator : undefined$1;
50656
50657                 if (comparator) {
50658                   mapped.pop();
50659                 }
50660
50661                 return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, undefined$1, comparator) : [];
50662               });
50663               /**
50664                * Converts all elements in `array` into a string separated by `separator`.
50665                *
50666                * @static
50667                * @memberOf _
50668                * @since 4.0.0
50669                * @category Array
50670                * @param {Array} array The array to convert.
50671                * @param {string} [separator=','] The element separator.
50672                * @returns {string} Returns the joined string.
50673                * @example
50674                *
50675                * _.join(['a', 'b', 'c'], '~');
50676                * // => 'a~b~c'
50677                */
50678
50679               function join(array, separator) {
50680                 return array == null ? '' : nativeJoin.call(array, separator);
50681               }
50682               /**
50683                * Gets the last element of `array`.
50684                *
50685                * @static
50686                * @memberOf _
50687                * @since 0.1.0
50688                * @category Array
50689                * @param {Array} array The array to query.
50690                * @returns {*} Returns the last element of `array`.
50691                * @example
50692                *
50693                * _.last([1, 2, 3]);
50694                * // => 3
50695                */
50696
50697
50698               function last(array) {
50699                 var length = array == null ? 0 : array.length;
50700                 return length ? array[length - 1] : undefined$1;
50701               }
50702               /**
50703                * This method is like `_.indexOf` except that it iterates over elements of
50704                * `array` from right to left.
50705                *
50706                * @static
50707                * @memberOf _
50708                * @since 0.1.0
50709                * @category Array
50710                * @param {Array} array The array to inspect.
50711                * @param {*} value The value to search for.
50712                * @param {number} [fromIndex=array.length-1] The index to search from.
50713                * @returns {number} Returns the index of the matched value, else `-1`.
50714                * @example
50715                *
50716                * _.lastIndexOf([1, 2, 1, 2], 2);
50717                * // => 3
50718                *
50719                * // Search from the `fromIndex`.
50720                * _.lastIndexOf([1, 2, 1, 2], 2, 2);
50721                * // => 1
50722                */
50723
50724
50725               function lastIndexOf(array, value, fromIndex) {
50726                 var length = array == null ? 0 : array.length;
50727
50728                 if (!length) {
50729                   return -1;
50730                 }
50731
50732                 var index = length;
50733
50734                 if (fromIndex !== undefined$1) {
50735                   index = toInteger(fromIndex);
50736                   index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
50737                 }
50738
50739                 return value === value ? strictLastIndexOf(array, value, index) : baseFindIndex(array, baseIsNaN, index, true);
50740               }
50741               /**
50742                * Gets the element at index `n` of `array`. If `n` is negative, the nth
50743                * element from the end is returned.
50744                *
50745                * @static
50746                * @memberOf _
50747                * @since 4.11.0
50748                * @category Array
50749                * @param {Array} array The array to query.
50750                * @param {number} [n=0] The index of the element to return.
50751                * @returns {*} Returns the nth element of `array`.
50752                * @example
50753                *
50754                * var array = ['a', 'b', 'c', 'd'];
50755                *
50756                * _.nth(array, 1);
50757                * // => 'b'
50758                *
50759                * _.nth(array, -2);
50760                * // => 'c';
50761                */
50762
50763
50764               function nth(array, n) {
50765                 return array && array.length ? baseNth(array, toInteger(n)) : undefined$1;
50766               }
50767               /**
50768                * Removes all given values from `array` using
50769                * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
50770                * for equality comparisons.
50771                *
50772                * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`
50773                * to remove elements from an array by predicate.
50774                *
50775                * @static
50776                * @memberOf _
50777                * @since 2.0.0
50778                * @category Array
50779                * @param {Array} array The array to modify.
50780                * @param {...*} [values] The values to remove.
50781                * @returns {Array} Returns `array`.
50782                * @example
50783                *
50784                * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
50785                *
50786                * _.pull(array, 'a', 'c');
50787                * console.log(array);
50788                * // => ['b', 'b']
50789                */
50790
50791
50792               var pull = baseRest(pullAll);
50793               /**
50794                * This method is like `_.pull` except that it accepts an array of values to remove.
50795                *
50796                * **Note:** Unlike `_.difference`, this method mutates `array`.
50797                *
50798                * @static
50799                * @memberOf _
50800                * @since 4.0.0
50801                * @category Array
50802                * @param {Array} array The array to modify.
50803                * @param {Array} values The values to remove.
50804                * @returns {Array} Returns `array`.
50805                * @example
50806                *
50807                * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
50808                *
50809                * _.pullAll(array, ['a', 'c']);
50810                * console.log(array);
50811                * // => ['b', 'b']
50812                */
50813
50814               function pullAll(array, values) {
50815                 return array && array.length && values && values.length ? basePullAll(array, values) : array;
50816               }
50817               /**
50818                * This method is like `_.pullAll` except that it accepts `iteratee` which is
50819                * invoked for each element of `array` and `values` to generate the criterion
50820                * by which they're compared. The iteratee is invoked with one argument: (value).
50821                *
50822                * **Note:** Unlike `_.differenceBy`, this method mutates `array`.
50823                *
50824                * @static
50825                * @memberOf _
50826                * @since 4.0.0
50827                * @category Array
50828                * @param {Array} array The array to modify.
50829                * @param {Array} values The values to remove.
50830                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
50831                * @returns {Array} Returns `array`.
50832                * @example
50833                *
50834                * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];
50835                *
50836                * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');
50837                * console.log(array);
50838                * // => [{ 'x': 2 }]
50839                */
50840
50841
50842               function pullAllBy(array, values, iteratee) {
50843                 return array && array.length && values && values.length ? basePullAll(array, values, getIteratee(iteratee, 2)) : array;
50844               }
50845               /**
50846                * This method is like `_.pullAll` except that it accepts `comparator` which
50847                * is invoked to compare elements of `array` to `values`. The comparator is
50848                * invoked with two arguments: (arrVal, othVal).
50849                *
50850                * **Note:** Unlike `_.differenceWith`, this method mutates `array`.
50851                *
50852                * @static
50853                * @memberOf _
50854                * @since 4.6.0
50855                * @category Array
50856                * @param {Array} array The array to modify.
50857                * @param {Array} values The values to remove.
50858                * @param {Function} [comparator] The comparator invoked per element.
50859                * @returns {Array} Returns `array`.
50860                * @example
50861                *
50862                * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }];
50863                *
50864                * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual);
50865                * console.log(array);
50866                * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }]
50867                */
50868
50869
50870               function pullAllWith(array, values, comparator) {
50871                 return array && array.length && values && values.length ? basePullAll(array, values, undefined$1, comparator) : array;
50872               }
50873               /**
50874                * Removes elements from `array` corresponding to `indexes` and returns an
50875                * array of removed elements.
50876                *
50877                * **Note:** Unlike `_.at`, this method mutates `array`.
50878                *
50879                * @static
50880                * @memberOf _
50881                * @since 3.0.0
50882                * @category Array
50883                * @param {Array} array The array to modify.
50884                * @param {...(number|number[])} [indexes] The indexes of elements to remove.
50885                * @returns {Array} Returns the new array of removed elements.
50886                * @example
50887                *
50888                * var array = ['a', 'b', 'c', 'd'];
50889                * var pulled = _.pullAt(array, [1, 3]);
50890                *
50891                * console.log(array);
50892                * // => ['a', 'c']
50893                *
50894                * console.log(pulled);
50895                * // => ['b', 'd']
50896                */
50897
50898
50899               var pullAt = flatRest(function (array, indexes) {
50900                 var length = array == null ? 0 : array.length,
50901                     result = baseAt(array, indexes);
50902                 basePullAt(array, arrayMap(indexes, function (index) {
50903                   return isIndex(index, length) ? +index : index;
50904                 }).sort(compareAscending));
50905                 return result;
50906               });
50907               /**
50908                * Removes all elements from `array` that `predicate` returns truthy for
50909                * and returns an array of the removed elements. The predicate is invoked
50910                * with three arguments: (value, index, array).
50911                *
50912                * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`
50913                * to pull elements from an array by value.
50914                *
50915                * @static
50916                * @memberOf _
50917                * @since 2.0.0
50918                * @category Array
50919                * @param {Array} array The array to modify.
50920                * @param {Function} [predicate=_.identity] The function invoked per iteration.
50921                * @returns {Array} Returns the new array of removed elements.
50922                * @example
50923                *
50924                * var array = [1, 2, 3, 4];
50925                * var evens = _.remove(array, function(n) {
50926                *   return n % 2 == 0;
50927                * });
50928                *
50929                * console.log(array);
50930                * // => [1, 3]
50931                *
50932                * console.log(evens);
50933                * // => [2, 4]
50934                */
50935
50936               function remove(array, predicate) {
50937                 var result = [];
50938
50939                 if (!(array && array.length)) {
50940                   return result;
50941                 }
50942
50943                 var index = -1,
50944                     indexes = [],
50945                     length = array.length;
50946                 predicate = getIteratee(predicate, 3);
50947
50948                 while (++index < length) {
50949                   var value = array[index];
50950
50951                   if (predicate(value, index, array)) {
50952                     result.push(value);
50953                     indexes.push(index);
50954                   }
50955                 }
50956
50957                 basePullAt(array, indexes);
50958                 return result;
50959               }
50960               /**
50961                * Reverses `array` so that the first element becomes the last, the second
50962                * element becomes the second to last, and so on.
50963                *
50964                * **Note:** This method mutates `array` and is based on
50965                * [`Array#reverse`](https://mdn.io/Array/reverse).
50966                *
50967                * @static
50968                * @memberOf _
50969                * @since 4.0.0
50970                * @category Array
50971                * @param {Array} array The array to modify.
50972                * @returns {Array} Returns `array`.
50973                * @example
50974                *
50975                * var array = [1, 2, 3];
50976                *
50977                * _.reverse(array);
50978                * // => [3, 2, 1]
50979                *
50980                * console.log(array);
50981                * // => [3, 2, 1]
50982                */
50983
50984
50985               function reverse(array) {
50986                 return array == null ? array : nativeReverse.call(array);
50987               }
50988               /**
50989                * Creates a slice of `array` from `start` up to, but not including, `end`.
50990                *
50991                * **Note:** This method is used instead of
50992                * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are
50993                * returned.
50994                *
50995                * @static
50996                * @memberOf _
50997                * @since 3.0.0
50998                * @category Array
50999                * @param {Array} array The array to slice.
51000                * @param {number} [start=0] The start position.
51001                * @param {number} [end=array.length] The end position.
51002                * @returns {Array} Returns the slice of `array`.
51003                */
51004
51005
51006               function slice(array, start, end) {
51007                 var length = array == null ? 0 : array.length;
51008
51009                 if (!length) {
51010                   return [];
51011                 }
51012
51013                 if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
51014                   start = 0;
51015                   end = length;
51016                 } else {
51017                   start = start == null ? 0 : toInteger(start);
51018                   end = end === undefined$1 ? length : toInteger(end);
51019                 }
51020
51021                 return baseSlice(array, start, end);
51022               }
51023               /**
51024                * Uses a binary search to determine the lowest index at which `value`
51025                * should be inserted into `array` in order to maintain its sort order.
51026                *
51027                * @static
51028                * @memberOf _
51029                * @since 0.1.0
51030                * @category Array
51031                * @param {Array} array The sorted array to inspect.
51032                * @param {*} value The value to evaluate.
51033                * @returns {number} Returns the index at which `value` should be inserted
51034                *  into `array`.
51035                * @example
51036                *
51037                * _.sortedIndex([30, 50], 40);
51038                * // => 1
51039                */
51040
51041
51042               function sortedIndex(array, value) {
51043                 return baseSortedIndex(array, value);
51044               }
51045               /**
51046                * This method is like `_.sortedIndex` except that it accepts `iteratee`
51047                * which is invoked for `value` and each element of `array` to compute their
51048                * sort ranking. The iteratee is invoked with one argument: (value).
51049                *
51050                * @static
51051                * @memberOf _
51052                * @since 4.0.0
51053                * @category Array
51054                * @param {Array} array The sorted array to inspect.
51055                * @param {*} value The value to evaluate.
51056                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
51057                * @returns {number} Returns the index at which `value` should be inserted
51058                *  into `array`.
51059                * @example
51060                *
51061                * var objects = [{ 'x': 4 }, { 'x': 5 }];
51062                *
51063                * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
51064                * // => 0
51065                *
51066                * // The `_.property` iteratee shorthand.
51067                * _.sortedIndexBy(objects, { 'x': 4 }, 'x');
51068                * // => 0
51069                */
51070
51071
51072               function sortedIndexBy(array, value, iteratee) {
51073                 return baseSortedIndexBy(array, value, getIteratee(iteratee, 2));
51074               }
51075               /**
51076                * This method is like `_.indexOf` except that it performs a binary
51077                * search on a sorted `array`.
51078                *
51079                * @static
51080                * @memberOf _
51081                * @since 4.0.0
51082                * @category Array
51083                * @param {Array} array The array to inspect.
51084                * @param {*} value The value to search for.
51085                * @returns {number} Returns the index of the matched value, else `-1`.
51086                * @example
51087                *
51088                * _.sortedIndexOf([4, 5, 5, 5, 6], 5);
51089                * // => 1
51090                */
51091
51092
51093               function sortedIndexOf(array, value) {
51094                 var length = array == null ? 0 : array.length;
51095
51096                 if (length) {
51097                   var index = baseSortedIndex(array, value);
51098
51099                   if (index < length && eq(array[index], value)) {
51100                     return index;
51101                   }
51102                 }
51103
51104                 return -1;
51105               }
51106               /**
51107                * This method is like `_.sortedIndex` except that it returns the highest
51108                * index at which `value` should be inserted into `array` in order to
51109                * maintain its sort order.
51110                *
51111                * @static
51112                * @memberOf _
51113                * @since 3.0.0
51114                * @category Array
51115                * @param {Array} array The sorted array to inspect.
51116                * @param {*} value The value to evaluate.
51117                * @returns {number} Returns the index at which `value` should be inserted
51118                *  into `array`.
51119                * @example
51120                *
51121                * _.sortedLastIndex([4, 5, 5, 5, 6], 5);
51122                * // => 4
51123                */
51124
51125
51126               function sortedLastIndex(array, value) {
51127                 return baseSortedIndex(array, value, true);
51128               }
51129               /**
51130                * This method is like `_.sortedLastIndex` except that it accepts `iteratee`
51131                * which is invoked for `value` and each element of `array` to compute their
51132                * sort ranking. The iteratee is invoked with one argument: (value).
51133                *
51134                * @static
51135                * @memberOf _
51136                * @since 4.0.0
51137                * @category Array
51138                * @param {Array} array The sorted array to inspect.
51139                * @param {*} value The value to evaluate.
51140                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
51141                * @returns {number} Returns the index at which `value` should be inserted
51142                *  into `array`.
51143                * @example
51144                *
51145                * var objects = [{ 'x': 4 }, { 'x': 5 }];
51146                *
51147                * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
51148                * // => 1
51149                *
51150                * // The `_.property` iteratee shorthand.
51151                * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x');
51152                * // => 1
51153                */
51154
51155
51156               function sortedLastIndexBy(array, value, iteratee) {
51157                 return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true);
51158               }
51159               /**
51160                * This method is like `_.lastIndexOf` except that it performs a binary
51161                * search on a sorted `array`.
51162                *
51163                * @static
51164                * @memberOf _
51165                * @since 4.0.0
51166                * @category Array
51167                * @param {Array} array The array to inspect.
51168                * @param {*} value The value to search for.
51169                * @returns {number} Returns the index of the matched value, else `-1`.
51170                * @example
51171                *
51172                * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5);
51173                * // => 3
51174                */
51175
51176
51177               function sortedLastIndexOf(array, value) {
51178                 var length = array == null ? 0 : array.length;
51179
51180                 if (length) {
51181                   var index = baseSortedIndex(array, value, true) - 1;
51182
51183                   if (eq(array[index], value)) {
51184                     return index;
51185                   }
51186                 }
51187
51188                 return -1;
51189               }
51190               /**
51191                * This method is like `_.uniq` except that it's designed and optimized
51192                * for sorted arrays.
51193                *
51194                * @static
51195                * @memberOf _
51196                * @since 4.0.0
51197                * @category Array
51198                * @param {Array} array The array to inspect.
51199                * @returns {Array} Returns the new duplicate free array.
51200                * @example
51201                *
51202                * _.sortedUniq([1, 1, 2]);
51203                * // => [1, 2]
51204                */
51205
51206
51207               function sortedUniq(array) {
51208                 return array && array.length ? baseSortedUniq(array) : [];
51209               }
51210               /**
51211                * This method is like `_.uniqBy` except that it's designed and optimized
51212                * for sorted arrays.
51213                *
51214                * @static
51215                * @memberOf _
51216                * @since 4.0.0
51217                * @category Array
51218                * @param {Array} array The array to inspect.
51219                * @param {Function} [iteratee] The iteratee invoked per element.
51220                * @returns {Array} Returns the new duplicate free array.
51221                * @example
51222                *
51223                * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);
51224                * // => [1.1, 2.3]
51225                */
51226
51227
51228               function sortedUniqBy(array, iteratee) {
51229                 return array && array.length ? baseSortedUniq(array, getIteratee(iteratee, 2)) : [];
51230               }
51231               /**
51232                * Gets all but the first element of `array`.
51233                *
51234                * @static
51235                * @memberOf _
51236                * @since 4.0.0
51237                * @category Array
51238                * @param {Array} array The array to query.
51239                * @returns {Array} Returns the slice of `array`.
51240                * @example
51241                *
51242                * _.tail([1, 2, 3]);
51243                * // => [2, 3]
51244                */
51245
51246
51247               function tail(array) {
51248                 var length = array == null ? 0 : array.length;
51249                 return length ? baseSlice(array, 1, length) : [];
51250               }
51251               /**
51252                * Creates a slice of `array` with `n` elements taken from the beginning.
51253                *
51254                * @static
51255                * @memberOf _
51256                * @since 0.1.0
51257                * @category Array
51258                * @param {Array} array The array to query.
51259                * @param {number} [n=1] The number of elements to take.
51260                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
51261                * @returns {Array} Returns the slice of `array`.
51262                * @example
51263                *
51264                * _.take([1, 2, 3]);
51265                * // => [1]
51266                *
51267                * _.take([1, 2, 3], 2);
51268                * // => [1, 2]
51269                *
51270                * _.take([1, 2, 3], 5);
51271                * // => [1, 2, 3]
51272                *
51273                * _.take([1, 2, 3], 0);
51274                * // => []
51275                */
51276
51277
51278               function take(array, n, guard) {
51279                 if (!(array && array.length)) {
51280                   return [];
51281                 }
51282
51283                 n = guard || n === undefined$1 ? 1 : toInteger(n);
51284                 return baseSlice(array, 0, n < 0 ? 0 : n);
51285               }
51286               /**
51287                * Creates a slice of `array` with `n` elements taken from the end.
51288                *
51289                * @static
51290                * @memberOf _
51291                * @since 3.0.0
51292                * @category Array
51293                * @param {Array} array The array to query.
51294                * @param {number} [n=1] The number of elements to take.
51295                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
51296                * @returns {Array} Returns the slice of `array`.
51297                * @example
51298                *
51299                * _.takeRight([1, 2, 3]);
51300                * // => [3]
51301                *
51302                * _.takeRight([1, 2, 3], 2);
51303                * // => [2, 3]
51304                *
51305                * _.takeRight([1, 2, 3], 5);
51306                * // => [1, 2, 3]
51307                *
51308                * _.takeRight([1, 2, 3], 0);
51309                * // => []
51310                */
51311
51312
51313               function takeRight(array, n, guard) {
51314                 var length = array == null ? 0 : array.length;
51315
51316                 if (!length) {
51317                   return [];
51318                 }
51319
51320                 n = guard || n === undefined$1 ? 1 : toInteger(n);
51321                 n = length - n;
51322                 return baseSlice(array, n < 0 ? 0 : n, length);
51323               }
51324               /**
51325                * Creates a slice of `array` with elements taken from the end. Elements are
51326                * taken until `predicate` returns falsey. The predicate is invoked with
51327                * three arguments: (value, index, array).
51328                *
51329                * @static
51330                * @memberOf _
51331                * @since 3.0.0
51332                * @category Array
51333                * @param {Array} array The array to query.
51334                * @param {Function} [predicate=_.identity] The function invoked per iteration.
51335                * @returns {Array} Returns the slice of `array`.
51336                * @example
51337                *
51338                * var users = [
51339                *   { 'user': 'barney',  'active': true },
51340                *   { 'user': 'fred',    'active': false },
51341                *   { 'user': 'pebbles', 'active': false }
51342                * ];
51343                *
51344                * _.takeRightWhile(users, function(o) { return !o.active; });
51345                * // => objects for ['fred', 'pebbles']
51346                *
51347                * // The `_.matches` iteratee shorthand.
51348                * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });
51349                * // => objects for ['pebbles']
51350                *
51351                * // The `_.matchesProperty` iteratee shorthand.
51352                * _.takeRightWhile(users, ['active', false]);
51353                * // => objects for ['fred', 'pebbles']
51354                *
51355                * // The `_.property` iteratee shorthand.
51356                * _.takeRightWhile(users, 'active');
51357                * // => []
51358                */
51359
51360
51361               function takeRightWhile(array, predicate) {
51362                 return array && array.length ? baseWhile(array, getIteratee(predicate, 3), false, true) : [];
51363               }
51364               /**
51365                * Creates a slice of `array` with elements taken from the beginning. Elements
51366                * are taken until `predicate` returns falsey. The predicate is invoked with
51367                * three arguments: (value, index, array).
51368                *
51369                * @static
51370                * @memberOf _
51371                * @since 3.0.0
51372                * @category Array
51373                * @param {Array} array The array to query.
51374                * @param {Function} [predicate=_.identity] The function invoked per iteration.
51375                * @returns {Array} Returns the slice of `array`.
51376                * @example
51377                *
51378                * var users = [
51379                *   { 'user': 'barney',  'active': false },
51380                *   { 'user': 'fred',    'active': false },
51381                *   { 'user': 'pebbles', 'active': true }
51382                * ];
51383                *
51384                * _.takeWhile(users, function(o) { return !o.active; });
51385                * // => objects for ['barney', 'fred']
51386                *
51387                * // The `_.matches` iteratee shorthand.
51388                * _.takeWhile(users, { 'user': 'barney', 'active': false });
51389                * // => objects for ['barney']
51390                *
51391                * // The `_.matchesProperty` iteratee shorthand.
51392                * _.takeWhile(users, ['active', false]);
51393                * // => objects for ['barney', 'fred']
51394                *
51395                * // The `_.property` iteratee shorthand.
51396                * _.takeWhile(users, 'active');
51397                * // => []
51398                */
51399
51400
51401               function takeWhile(array, predicate) {
51402                 return array && array.length ? baseWhile(array, getIteratee(predicate, 3)) : [];
51403               }
51404               /**
51405                * Creates an array of unique values, in order, from all given arrays using
51406                * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
51407                * for equality comparisons.
51408                *
51409                * @static
51410                * @memberOf _
51411                * @since 0.1.0
51412                * @category Array
51413                * @param {...Array} [arrays] The arrays to inspect.
51414                * @returns {Array} Returns the new array of combined values.
51415                * @example
51416                *
51417                * _.union([2], [1, 2]);
51418                * // => [2, 1]
51419                */
51420
51421
51422               var union = baseRest(function (arrays) {
51423                 return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
51424               });
51425               /**
51426                * This method is like `_.union` except that it accepts `iteratee` which is
51427                * invoked for each element of each `arrays` to generate the criterion by
51428                * which uniqueness is computed. Result values are chosen from the first
51429                * array in which the value occurs. The iteratee is invoked with one argument:
51430                * (value).
51431                *
51432                * @static
51433                * @memberOf _
51434                * @since 4.0.0
51435                * @category Array
51436                * @param {...Array} [arrays] The arrays to inspect.
51437                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
51438                * @returns {Array} Returns the new array of combined values.
51439                * @example
51440                *
51441                * _.unionBy([2.1], [1.2, 2.3], Math.floor);
51442                * // => [2.1, 1.2]
51443                *
51444                * // The `_.property` iteratee shorthand.
51445                * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
51446                * // => [{ 'x': 1 }, { 'x': 2 }]
51447                */
51448
51449               var unionBy = baseRest(function (arrays) {
51450                 var iteratee = last(arrays);
51451
51452                 if (isArrayLikeObject(iteratee)) {
51453                   iteratee = undefined$1;
51454                 }
51455
51456                 return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2));
51457               });
51458               /**
51459                * This method is like `_.union` except that it accepts `comparator` which
51460                * is invoked to compare elements of `arrays`. Result values are chosen from
51461                * the first array in which the value occurs. The comparator is invoked
51462                * with two arguments: (arrVal, othVal).
51463                *
51464                * @static
51465                * @memberOf _
51466                * @since 4.0.0
51467                * @category Array
51468                * @param {...Array} [arrays] The arrays to inspect.
51469                * @param {Function} [comparator] The comparator invoked per element.
51470                * @returns {Array} Returns the new array of combined values.
51471                * @example
51472                *
51473                * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
51474                * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
51475                *
51476                * _.unionWith(objects, others, _.isEqual);
51477                * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
51478                */
51479
51480               var unionWith = baseRest(function (arrays) {
51481                 var comparator = last(arrays);
51482                 comparator = typeof comparator == 'function' ? comparator : undefined$1;
51483                 return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined$1, comparator);
51484               });
51485               /**
51486                * Creates a duplicate-free version of an array, using
51487                * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
51488                * for equality comparisons, in which only the first occurrence of each element
51489                * is kept. The order of result values is determined by the order they occur
51490                * in the array.
51491                *
51492                * @static
51493                * @memberOf _
51494                * @since 0.1.0
51495                * @category Array
51496                * @param {Array} array The array to inspect.
51497                * @returns {Array} Returns the new duplicate free array.
51498                * @example
51499                *
51500                * _.uniq([2, 1, 2]);
51501                * // => [2, 1]
51502                */
51503
51504               function uniq(array) {
51505                 return array && array.length ? baseUniq(array) : [];
51506               }
51507               /**
51508                * This method is like `_.uniq` except that it accepts `iteratee` which is
51509                * invoked for each element in `array` to generate the criterion by which
51510                * uniqueness is computed. The order of result values is determined by the
51511                * order they occur in the array. The iteratee is invoked with one argument:
51512                * (value).
51513                *
51514                * @static
51515                * @memberOf _
51516                * @since 4.0.0
51517                * @category Array
51518                * @param {Array} array The array to inspect.
51519                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
51520                * @returns {Array} Returns the new duplicate free array.
51521                * @example
51522                *
51523                * _.uniqBy([2.1, 1.2, 2.3], Math.floor);
51524                * // => [2.1, 1.2]
51525                *
51526                * // The `_.property` iteratee shorthand.
51527                * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
51528                * // => [{ 'x': 1 }, { 'x': 2 }]
51529                */
51530
51531
51532               function uniqBy(array, iteratee) {
51533                 return array && array.length ? baseUniq(array, getIteratee(iteratee, 2)) : [];
51534               }
51535               /**
51536                * This method is like `_.uniq` except that it accepts `comparator` which
51537                * is invoked to compare elements of `array`. The order of result values is
51538                * determined by the order they occur in the array.The comparator is invoked
51539                * with two arguments: (arrVal, othVal).
51540                *
51541                * @static
51542                * @memberOf _
51543                * @since 4.0.0
51544                * @category Array
51545                * @param {Array} array The array to inspect.
51546                * @param {Function} [comparator] The comparator invoked per element.
51547                * @returns {Array} Returns the new duplicate free array.
51548                * @example
51549                *
51550                * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
51551                *
51552                * _.uniqWith(objects, _.isEqual);
51553                * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
51554                */
51555
51556
51557               function uniqWith(array, comparator) {
51558                 comparator = typeof comparator == 'function' ? comparator : undefined$1;
51559                 return array && array.length ? baseUniq(array, undefined$1, comparator) : [];
51560               }
51561               /**
51562                * This method is like `_.zip` except that it accepts an array of grouped
51563                * elements and creates an array regrouping the elements to their pre-zip
51564                * configuration.
51565                *
51566                * @static
51567                * @memberOf _
51568                * @since 1.2.0
51569                * @category Array
51570                * @param {Array} array The array of grouped elements to process.
51571                * @returns {Array} Returns the new array of regrouped elements.
51572                * @example
51573                *
51574                * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]);
51575                * // => [['a', 1, true], ['b', 2, false]]
51576                *
51577                * _.unzip(zipped);
51578                * // => [['a', 'b'], [1, 2], [true, false]]
51579                */
51580
51581
51582               function unzip(array) {
51583                 if (!(array && array.length)) {
51584                   return [];
51585                 }
51586
51587                 var length = 0;
51588                 array = arrayFilter(array, function (group) {
51589                   if (isArrayLikeObject(group)) {
51590                     length = nativeMax(group.length, length);
51591                     return true;
51592                   }
51593                 });
51594                 return baseTimes(length, function (index) {
51595                   return arrayMap(array, baseProperty(index));
51596                 });
51597               }
51598               /**
51599                * This method is like `_.unzip` except that it accepts `iteratee` to specify
51600                * how regrouped values should be combined. The iteratee is invoked with the
51601                * elements of each group: (...group).
51602                *
51603                * @static
51604                * @memberOf _
51605                * @since 3.8.0
51606                * @category Array
51607                * @param {Array} array The array of grouped elements to process.
51608                * @param {Function} [iteratee=_.identity] The function to combine
51609                *  regrouped values.
51610                * @returns {Array} Returns the new array of regrouped elements.
51611                * @example
51612                *
51613                * var zipped = _.zip([1, 2], [10, 20], [100, 200]);
51614                * // => [[1, 10, 100], [2, 20, 200]]
51615                *
51616                * _.unzipWith(zipped, _.add);
51617                * // => [3, 30, 300]
51618                */
51619
51620
51621               function unzipWith(array, iteratee) {
51622                 if (!(array && array.length)) {
51623                   return [];
51624                 }
51625
51626                 var result = unzip(array);
51627
51628                 if (iteratee == null) {
51629                   return result;
51630                 }
51631
51632                 return arrayMap(result, function (group) {
51633                   return apply(iteratee, undefined$1, group);
51634                 });
51635               }
51636               /**
51637                * Creates an array excluding all given values using
51638                * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
51639                * for equality comparisons.
51640                *
51641                * **Note:** Unlike `_.pull`, this method returns a new array.
51642                *
51643                * @static
51644                * @memberOf _
51645                * @since 0.1.0
51646                * @category Array
51647                * @param {Array} array The array to inspect.
51648                * @param {...*} [values] The values to exclude.
51649                * @returns {Array} Returns the new array of filtered values.
51650                * @see _.difference, _.xor
51651                * @example
51652                *
51653                * _.without([2, 1, 2, 3], 1, 2);
51654                * // => [3]
51655                */
51656
51657
51658               var without = baseRest(function (array, values) {
51659                 return isArrayLikeObject(array) ? baseDifference(array, values) : [];
51660               });
51661               /**
51662                * Creates an array of unique values that is the
51663                * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
51664                * of the given arrays. The order of result values is determined by the order
51665                * they occur in the arrays.
51666                *
51667                * @static
51668                * @memberOf _
51669                * @since 2.4.0
51670                * @category Array
51671                * @param {...Array} [arrays] The arrays to inspect.
51672                * @returns {Array} Returns the new array of filtered values.
51673                * @see _.difference, _.without
51674                * @example
51675                *
51676                * _.xor([2, 1], [2, 3]);
51677                * // => [1, 3]
51678                */
51679
51680               var xor = baseRest(function (arrays) {
51681                 return baseXor(arrayFilter(arrays, isArrayLikeObject));
51682               });
51683               /**
51684                * This method is like `_.xor` except that it accepts `iteratee` which is
51685                * invoked for each element of each `arrays` to generate the criterion by
51686                * which by which they're compared. The order of result values is determined
51687                * by the order they occur in the arrays. The iteratee is invoked with one
51688                * argument: (value).
51689                *
51690                * @static
51691                * @memberOf _
51692                * @since 4.0.0
51693                * @category Array
51694                * @param {...Array} [arrays] The arrays to inspect.
51695                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
51696                * @returns {Array} Returns the new array of filtered values.
51697                * @example
51698                *
51699                * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor);
51700                * // => [1.2, 3.4]
51701                *
51702                * // The `_.property` iteratee shorthand.
51703                * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
51704                * // => [{ 'x': 2 }]
51705                */
51706
51707               var xorBy = baseRest(function (arrays) {
51708                 var iteratee = last(arrays);
51709
51710                 if (isArrayLikeObject(iteratee)) {
51711                   iteratee = undefined$1;
51712                 }
51713
51714                 return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2));
51715               });
51716               /**
51717                * This method is like `_.xor` except that it accepts `comparator` which is
51718                * invoked to compare elements of `arrays`. The order of result values is
51719                * determined by the order they occur in the arrays. The comparator is invoked
51720                * with two arguments: (arrVal, othVal).
51721                *
51722                * @static
51723                * @memberOf _
51724                * @since 4.0.0
51725                * @category Array
51726                * @param {...Array} [arrays] The arrays to inspect.
51727                * @param {Function} [comparator] The comparator invoked per element.
51728                * @returns {Array} Returns the new array of filtered values.
51729                * @example
51730                *
51731                * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
51732                * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
51733                *
51734                * _.xorWith(objects, others, _.isEqual);
51735                * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
51736                */
51737
51738               var xorWith = baseRest(function (arrays) {
51739                 var comparator = last(arrays);
51740                 comparator = typeof comparator == 'function' ? comparator : undefined$1;
51741                 return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined$1, comparator);
51742               });
51743               /**
51744                * Creates an array of grouped elements, the first of which contains the
51745                * first elements of the given arrays, the second of which contains the
51746                * second elements of the given arrays, and so on.
51747                *
51748                * @static
51749                * @memberOf _
51750                * @since 0.1.0
51751                * @category Array
51752                * @param {...Array} [arrays] The arrays to process.
51753                * @returns {Array} Returns the new array of grouped elements.
51754                * @example
51755                *
51756                * _.zip(['a', 'b'], [1, 2], [true, false]);
51757                * // => [['a', 1, true], ['b', 2, false]]
51758                */
51759
51760               var zip = baseRest(unzip);
51761               /**
51762                * This method is like `_.fromPairs` except that it accepts two arrays,
51763                * one of property identifiers and one of corresponding values.
51764                *
51765                * @static
51766                * @memberOf _
51767                * @since 0.4.0
51768                * @category Array
51769                * @param {Array} [props=[]] The property identifiers.
51770                * @param {Array} [values=[]] The property values.
51771                * @returns {Object} Returns the new object.
51772                * @example
51773                *
51774                * _.zipObject(['a', 'b'], [1, 2]);
51775                * // => { 'a': 1, 'b': 2 }
51776                */
51777
51778               function zipObject(props, values) {
51779                 return baseZipObject(props || [], values || [], assignValue);
51780               }
51781               /**
51782                * This method is like `_.zipObject` except that it supports property paths.
51783                *
51784                * @static
51785                * @memberOf _
51786                * @since 4.1.0
51787                * @category Array
51788                * @param {Array} [props=[]] The property identifiers.
51789                * @param {Array} [values=[]] The property values.
51790                * @returns {Object} Returns the new object.
51791                * @example
51792                *
51793                * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);
51794                * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }
51795                */
51796
51797
51798               function zipObjectDeep(props, values) {
51799                 return baseZipObject(props || [], values || [], baseSet);
51800               }
51801               /**
51802                * This method is like `_.zip` except that it accepts `iteratee` to specify
51803                * how grouped values should be combined. The iteratee is invoked with the
51804                * elements of each group: (...group).
51805                *
51806                * @static
51807                * @memberOf _
51808                * @since 3.8.0
51809                * @category Array
51810                * @param {...Array} [arrays] The arrays to process.
51811                * @param {Function} [iteratee=_.identity] The function to combine
51812                *  grouped values.
51813                * @returns {Array} Returns the new array of grouped elements.
51814                * @example
51815                *
51816                * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {
51817                *   return a + b + c;
51818                * });
51819                * // => [111, 222]
51820                */
51821
51822
51823               var zipWith = baseRest(function (arrays) {
51824                 var length = arrays.length,
51825                     iteratee = length > 1 ? arrays[length - 1] : undefined$1;
51826                 iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined$1;
51827                 return unzipWith(arrays, iteratee);
51828               });
51829               /*------------------------------------------------------------------------*/
51830
51831               /**
51832                * Creates a `lodash` wrapper instance that wraps `value` with explicit method
51833                * chain sequences enabled. The result of such sequences must be unwrapped
51834                * with `_#value`.
51835                *
51836                * @static
51837                * @memberOf _
51838                * @since 1.3.0
51839                * @category Seq
51840                * @param {*} value The value to wrap.
51841                * @returns {Object} Returns the new `lodash` wrapper instance.
51842                * @example
51843                *
51844                * var users = [
51845                *   { 'user': 'barney',  'age': 36 },
51846                *   { 'user': 'fred',    'age': 40 },
51847                *   { 'user': 'pebbles', 'age': 1 }
51848                * ];
51849                *
51850                * var youngest = _
51851                *   .chain(users)
51852                *   .sortBy('age')
51853                *   .map(function(o) {
51854                *     return o.user + ' is ' + o.age;
51855                *   })
51856                *   .head()
51857                *   .value();
51858                * // => 'pebbles is 1'
51859                */
51860
51861               function chain(value) {
51862                 var result = lodash(value);
51863                 result.__chain__ = true;
51864                 return result;
51865               }
51866               /**
51867                * This method invokes `interceptor` and returns `value`. The interceptor
51868                * is invoked with one argument; (value). The purpose of this method is to
51869                * "tap into" a method chain sequence in order to modify intermediate results.
51870                *
51871                * @static
51872                * @memberOf _
51873                * @since 0.1.0
51874                * @category Seq
51875                * @param {*} value The value to provide to `interceptor`.
51876                * @param {Function} interceptor The function to invoke.
51877                * @returns {*} Returns `value`.
51878                * @example
51879                *
51880                * _([1, 2, 3])
51881                *  .tap(function(array) {
51882                *    // Mutate input array.
51883                *    array.pop();
51884                *  })
51885                *  .reverse()
51886                *  .value();
51887                * // => [2, 1]
51888                */
51889
51890
51891               function tap(value, interceptor) {
51892                 interceptor(value);
51893                 return value;
51894               }
51895               /**
51896                * This method is like `_.tap` except that it returns the result of `interceptor`.
51897                * The purpose of this method is to "pass thru" values replacing intermediate
51898                * results in a method chain sequence.
51899                *
51900                * @static
51901                * @memberOf _
51902                * @since 3.0.0
51903                * @category Seq
51904                * @param {*} value The value to provide to `interceptor`.
51905                * @param {Function} interceptor The function to invoke.
51906                * @returns {*} Returns the result of `interceptor`.
51907                * @example
51908                *
51909                * _('  abc  ')
51910                *  .chain()
51911                *  .trim()
51912                *  .thru(function(value) {
51913                *    return [value];
51914                *  })
51915                *  .value();
51916                * // => ['abc']
51917                */
51918
51919
51920               function thru(value, interceptor) {
51921                 return interceptor(value);
51922               }
51923               /**
51924                * This method is the wrapper version of `_.at`.
51925                *
51926                * @name at
51927                * @memberOf _
51928                * @since 1.0.0
51929                * @category Seq
51930                * @param {...(string|string[])} [paths] The property paths to pick.
51931                * @returns {Object} Returns the new `lodash` wrapper instance.
51932                * @example
51933                *
51934                * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
51935                *
51936                * _(object).at(['a[0].b.c', 'a[1]']).value();
51937                * // => [3, 4]
51938                */
51939
51940
51941               var wrapperAt = flatRest(function (paths) {
51942                 var length = paths.length,
51943                     start = length ? paths[0] : 0,
51944                     value = this.__wrapped__,
51945                     interceptor = function interceptor(object) {
51946                   return baseAt(object, paths);
51947                 };
51948
51949                 if (length > 1 || this.__actions__.length || !(value instanceof LazyWrapper) || !isIndex(start)) {
51950                   return this.thru(interceptor);
51951                 }
51952
51953                 value = value.slice(start, +start + (length ? 1 : 0));
51954
51955                 value.__actions__.push({
51956                   'func': thru,
51957                   'args': [interceptor],
51958                   'thisArg': undefined$1
51959                 });
51960
51961                 return new LodashWrapper(value, this.__chain__).thru(function (array) {
51962                   if (length && !array.length) {
51963                     array.push(undefined$1);
51964                   }
51965
51966                   return array;
51967                 });
51968               });
51969               /**
51970                * Creates a `lodash` wrapper instance with explicit method chain sequences enabled.
51971                *
51972                * @name chain
51973                * @memberOf _
51974                * @since 0.1.0
51975                * @category Seq
51976                * @returns {Object} Returns the new `lodash` wrapper instance.
51977                * @example
51978                *
51979                * var users = [
51980                *   { 'user': 'barney', 'age': 36 },
51981                *   { 'user': 'fred',   'age': 40 }
51982                * ];
51983                *
51984                * // A sequence without explicit chaining.
51985                * _(users).head();
51986                * // => { 'user': 'barney', 'age': 36 }
51987                *
51988                * // A sequence with explicit chaining.
51989                * _(users)
51990                *   .chain()
51991                *   .head()
51992                *   .pick('user')
51993                *   .value();
51994                * // => { 'user': 'barney' }
51995                */
51996
51997               function wrapperChain() {
51998                 return chain(this);
51999               }
52000               /**
52001                * Executes the chain sequence and returns the wrapped result.
52002                *
52003                * @name commit
52004                * @memberOf _
52005                * @since 3.2.0
52006                * @category Seq
52007                * @returns {Object} Returns the new `lodash` wrapper instance.
52008                * @example
52009                *
52010                * var array = [1, 2];
52011                * var wrapped = _(array).push(3);
52012                *
52013                * console.log(array);
52014                * // => [1, 2]
52015                *
52016                * wrapped = wrapped.commit();
52017                * console.log(array);
52018                * // => [1, 2, 3]
52019                *
52020                * wrapped.last();
52021                * // => 3
52022                *
52023                * console.log(array);
52024                * // => [1, 2, 3]
52025                */
52026
52027
52028               function wrapperCommit() {
52029                 return new LodashWrapper(this.value(), this.__chain__);
52030               }
52031               /**
52032                * Gets the next value on a wrapped object following the
52033                * [iterator protocol](https://mdn.io/iteration_protocols#iterator).
52034                *
52035                * @name next
52036                * @memberOf _
52037                * @since 4.0.0
52038                * @category Seq
52039                * @returns {Object} Returns the next iterator value.
52040                * @example
52041                *
52042                * var wrapped = _([1, 2]);
52043                *
52044                * wrapped.next();
52045                * // => { 'done': false, 'value': 1 }
52046                *
52047                * wrapped.next();
52048                * // => { 'done': false, 'value': 2 }
52049                *
52050                * wrapped.next();
52051                * // => { 'done': true, 'value': undefined }
52052                */
52053
52054
52055               function wrapperNext() {
52056                 if (this.__values__ === undefined$1) {
52057                   this.__values__ = toArray(this.value());
52058                 }
52059
52060                 var done = this.__index__ >= this.__values__.length,
52061                     value = done ? undefined$1 : this.__values__[this.__index__++];
52062                 return {
52063                   'done': done,
52064                   'value': value
52065                 };
52066               }
52067               /**
52068                * Enables the wrapper to be iterable.
52069                *
52070                * @name Symbol.iterator
52071                * @memberOf _
52072                * @since 4.0.0
52073                * @category Seq
52074                * @returns {Object} Returns the wrapper object.
52075                * @example
52076                *
52077                * var wrapped = _([1, 2]);
52078                *
52079                * wrapped[Symbol.iterator]() === wrapped;
52080                * // => true
52081                *
52082                * Array.from(wrapped);
52083                * // => [1, 2]
52084                */
52085
52086
52087               function wrapperToIterator() {
52088                 return this;
52089               }
52090               /**
52091                * Creates a clone of the chain sequence planting `value` as the wrapped value.
52092                *
52093                * @name plant
52094                * @memberOf _
52095                * @since 3.2.0
52096                * @category Seq
52097                * @param {*} value The value to plant.
52098                * @returns {Object} Returns the new `lodash` wrapper instance.
52099                * @example
52100                *
52101                * function square(n) {
52102                *   return n * n;
52103                * }
52104                *
52105                * var wrapped = _([1, 2]).map(square);
52106                * var other = wrapped.plant([3, 4]);
52107                *
52108                * other.value();
52109                * // => [9, 16]
52110                *
52111                * wrapped.value();
52112                * // => [1, 4]
52113                */
52114
52115
52116               function wrapperPlant(value) {
52117                 var result,
52118                     parent = this;
52119
52120                 while (parent instanceof baseLodash) {
52121                   var clone = wrapperClone(parent);
52122                   clone.__index__ = 0;
52123                   clone.__values__ = undefined$1;
52124
52125                   if (result) {
52126                     previous.__wrapped__ = clone;
52127                   } else {
52128                     result = clone;
52129                   }
52130
52131                   var previous = clone;
52132                   parent = parent.__wrapped__;
52133                 }
52134
52135                 previous.__wrapped__ = value;
52136                 return result;
52137               }
52138               /**
52139                * This method is the wrapper version of `_.reverse`.
52140                *
52141                * **Note:** This method mutates the wrapped array.
52142                *
52143                * @name reverse
52144                * @memberOf _
52145                * @since 0.1.0
52146                * @category Seq
52147                * @returns {Object} Returns the new `lodash` wrapper instance.
52148                * @example
52149                *
52150                * var array = [1, 2, 3];
52151                *
52152                * _(array).reverse().value()
52153                * // => [3, 2, 1]
52154                *
52155                * console.log(array);
52156                * // => [3, 2, 1]
52157                */
52158
52159
52160               function wrapperReverse() {
52161                 var value = this.__wrapped__;
52162
52163                 if (value instanceof LazyWrapper) {
52164                   var wrapped = value;
52165
52166                   if (this.__actions__.length) {
52167                     wrapped = new LazyWrapper(this);
52168                   }
52169
52170                   wrapped = wrapped.reverse();
52171
52172                   wrapped.__actions__.push({
52173                     'func': thru,
52174                     'args': [reverse],
52175                     'thisArg': undefined$1
52176                   });
52177
52178                   return new LodashWrapper(wrapped, this.__chain__);
52179                 }
52180
52181                 return this.thru(reverse);
52182               }
52183               /**
52184                * Executes the chain sequence to resolve the unwrapped value.
52185                *
52186                * @name value
52187                * @memberOf _
52188                * @since 0.1.0
52189                * @alias toJSON, valueOf
52190                * @category Seq
52191                * @returns {*} Returns the resolved unwrapped value.
52192                * @example
52193                *
52194                * _([1, 2, 3]).value();
52195                * // => [1, 2, 3]
52196                */
52197
52198
52199               function wrapperValue() {
52200                 return baseWrapperValue(this.__wrapped__, this.__actions__);
52201               }
52202               /*------------------------------------------------------------------------*/
52203
52204               /**
52205                * Creates an object composed of keys generated from the results of running
52206                * each element of `collection` thru `iteratee`. The corresponding value of
52207                * each key is the number of times the key was returned by `iteratee`. The
52208                * iteratee is invoked with one argument: (value).
52209                *
52210                * @static
52211                * @memberOf _
52212                * @since 0.5.0
52213                * @category Collection
52214                * @param {Array|Object} collection The collection to iterate over.
52215                * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
52216                * @returns {Object} Returns the composed aggregate object.
52217                * @example
52218                *
52219                * _.countBy([6.1, 4.2, 6.3], Math.floor);
52220                * // => { '4': 1, '6': 2 }
52221                *
52222                * // The `_.property` iteratee shorthand.
52223                * _.countBy(['one', 'two', 'three'], 'length');
52224                * // => { '3': 2, '5': 1 }
52225                */
52226
52227
52228               var countBy = createAggregator(function (result, value, key) {
52229                 if (hasOwnProperty.call(result, key)) {
52230                   ++result[key];
52231                 } else {
52232                   baseAssignValue(result, key, 1);
52233                 }
52234               });
52235               /**
52236                * Checks if `predicate` returns truthy for **all** elements of `collection`.
52237                * Iteration is stopped once `predicate` returns falsey. The predicate is
52238                * invoked with three arguments: (value, index|key, collection).
52239                *
52240                * **Note:** This method returns `true` for
52241                * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because
52242                * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of
52243                * elements of empty collections.
52244                *
52245                * @static
52246                * @memberOf _
52247                * @since 0.1.0
52248                * @category Collection
52249                * @param {Array|Object} collection The collection to iterate over.
52250                * @param {Function} [predicate=_.identity] The function invoked per iteration.
52251                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
52252                * @returns {boolean} Returns `true` if all elements pass the predicate check,
52253                *  else `false`.
52254                * @example
52255                *
52256                * _.every([true, 1, null, 'yes'], Boolean);
52257                * // => false
52258                *
52259                * var users = [
52260                *   { 'user': 'barney', 'age': 36, 'active': false },
52261                *   { 'user': 'fred',   'age': 40, 'active': false }
52262                * ];
52263                *
52264                * // The `_.matches` iteratee shorthand.
52265                * _.every(users, { 'user': 'barney', 'active': false });
52266                * // => false
52267                *
52268                * // The `_.matchesProperty` iteratee shorthand.
52269                * _.every(users, ['active', false]);
52270                * // => true
52271                *
52272                * // The `_.property` iteratee shorthand.
52273                * _.every(users, 'active');
52274                * // => false
52275                */
52276
52277               function every(collection, predicate, guard) {
52278                 var func = isArray(collection) ? arrayEvery : baseEvery;
52279
52280                 if (guard && isIterateeCall(collection, predicate, guard)) {
52281                   predicate = undefined$1;
52282                 }
52283
52284                 return func(collection, getIteratee(predicate, 3));
52285               }
52286               /**
52287                * Iterates over elements of `collection`, returning an array of all elements
52288                * `predicate` returns truthy for. The predicate is invoked with three
52289                * arguments: (value, index|key, collection).
52290                *
52291                * **Note:** Unlike `_.remove`, this method returns a new array.
52292                *
52293                * @static
52294                * @memberOf _
52295                * @since 0.1.0
52296                * @category Collection
52297                * @param {Array|Object} collection The collection to iterate over.
52298                * @param {Function} [predicate=_.identity] The function invoked per iteration.
52299                * @returns {Array} Returns the new filtered array.
52300                * @see _.reject
52301                * @example
52302                *
52303                * var users = [
52304                *   { 'user': 'barney', 'age': 36, 'active': true },
52305                *   { 'user': 'fred',   'age': 40, 'active': false }
52306                * ];
52307                *
52308                * _.filter(users, function(o) { return !o.active; });
52309                * // => objects for ['fred']
52310                *
52311                * // The `_.matches` iteratee shorthand.
52312                * _.filter(users, { 'age': 36, 'active': true });
52313                * // => objects for ['barney']
52314                *
52315                * // The `_.matchesProperty` iteratee shorthand.
52316                * _.filter(users, ['active', false]);
52317                * // => objects for ['fred']
52318                *
52319                * // The `_.property` iteratee shorthand.
52320                * _.filter(users, 'active');
52321                * // => objects for ['barney']
52322                *
52323                * // Combining several predicates using `_.overEvery` or `_.overSome`.
52324                * _.filter(users, _.overSome([{ 'age': 36 }, ['age', 40]]));
52325                * // => objects for ['fred', 'barney']
52326                */
52327
52328
52329               function filter(collection, predicate) {
52330                 var func = isArray(collection) ? arrayFilter : baseFilter;
52331                 return func(collection, getIteratee(predicate, 3));
52332               }
52333               /**
52334                * Iterates over elements of `collection`, returning the first element
52335                * `predicate` returns truthy for. The predicate is invoked with three
52336                * arguments: (value, index|key, collection).
52337                *
52338                * @static
52339                * @memberOf _
52340                * @since 0.1.0
52341                * @category Collection
52342                * @param {Array|Object} collection The collection to inspect.
52343                * @param {Function} [predicate=_.identity] The function invoked per iteration.
52344                * @param {number} [fromIndex=0] The index to search from.
52345                * @returns {*} Returns the matched element, else `undefined`.
52346                * @example
52347                *
52348                * var users = [
52349                *   { 'user': 'barney',  'age': 36, 'active': true },
52350                *   { 'user': 'fred',    'age': 40, 'active': false },
52351                *   { 'user': 'pebbles', 'age': 1,  'active': true }
52352                * ];
52353                *
52354                * _.find(users, function(o) { return o.age < 40; });
52355                * // => object for 'barney'
52356                *
52357                * // The `_.matches` iteratee shorthand.
52358                * _.find(users, { 'age': 1, 'active': true });
52359                * // => object for 'pebbles'
52360                *
52361                * // The `_.matchesProperty` iteratee shorthand.
52362                * _.find(users, ['active', false]);
52363                * // => object for 'fred'
52364                *
52365                * // The `_.property` iteratee shorthand.
52366                * _.find(users, 'active');
52367                * // => object for 'barney'
52368                */
52369
52370
52371               var find = createFind(findIndex);
52372               /**
52373                * This method is like `_.find` except that it iterates over elements of
52374                * `collection` from right to left.
52375                *
52376                * @static
52377                * @memberOf _
52378                * @since 2.0.0
52379                * @category Collection
52380                * @param {Array|Object} collection The collection to inspect.
52381                * @param {Function} [predicate=_.identity] The function invoked per iteration.
52382                * @param {number} [fromIndex=collection.length-1] The index to search from.
52383                * @returns {*} Returns the matched element, else `undefined`.
52384                * @example
52385                *
52386                * _.findLast([1, 2, 3, 4], function(n) {
52387                *   return n % 2 == 1;
52388                * });
52389                * // => 3
52390                */
52391
52392               var findLast = createFind(findLastIndex);
52393               /**
52394                * Creates a flattened array of values by running each element in `collection`
52395                * thru `iteratee` and flattening the mapped results. The iteratee is invoked
52396                * with three arguments: (value, index|key, collection).
52397                *
52398                * @static
52399                * @memberOf _
52400                * @since 4.0.0
52401                * @category Collection
52402                * @param {Array|Object} collection The collection to iterate over.
52403                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
52404                * @returns {Array} Returns the new flattened array.
52405                * @example
52406                *
52407                * function duplicate(n) {
52408                *   return [n, n];
52409                * }
52410                *
52411                * _.flatMap([1, 2], duplicate);
52412                * // => [1, 1, 2, 2]
52413                */
52414
52415               function flatMap(collection, iteratee) {
52416                 return baseFlatten(map(collection, iteratee), 1);
52417               }
52418               /**
52419                * This method is like `_.flatMap` except that it recursively flattens the
52420                * mapped results.
52421                *
52422                * @static
52423                * @memberOf _
52424                * @since 4.7.0
52425                * @category Collection
52426                * @param {Array|Object} collection The collection to iterate over.
52427                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
52428                * @returns {Array} Returns the new flattened array.
52429                * @example
52430                *
52431                * function duplicate(n) {
52432                *   return [[[n, n]]];
52433                * }
52434                *
52435                * _.flatMapDeep([1, 2], duplicate);
52436                * // => [1, 1, 2, 2]
52437                */
52438
52439
52440               function flatMapDeep(collection, iteratee) {
52441                 return baseFlatten(map(collection, iteratee), INFINITY);
52442               }
52443               /**
52444                * This method is like `_.flatMap` except that it recursively flattens the
52445                * mapped results up to `depth` times.
52446                *
52447                * @static
52448                * @memberOf _
52449                * @since 4.7.0
52450                * @category Collection
52451                * @param {Array|Object} collection The collection to iterate over.
52452                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
52453                * @param {number} [depth=1] The maximum recursion depth.
52454                * @returns {Array} Returns the new flattened array.
52455                * @example
52456                *
52457                * function duplicate(n) {
52458                *   return [[[n, n]]];
52459                * }
52460                *
52461                * _.flatMapDepth([1, 2], duplicate, 2);
52462                * // => [[1, 1], [2, 2]]
52463                */
52464
52465
52466               function flatMapDepth(collection, iteratee, depth) {
52467                 depth = depth === undefined$1 ? 1 : toInteger(depth);
52468                 return baseFlatten(map(collection, iteratee), depth);
52469               }
52470               /**
52471                * Iterates over elements of `collection` and invokes `iteratee` for each element.
52472                * The iteratee is invoked with three arguments: (value, index|key, collection).
52473                * Iteratee functions may exit iteration early by explicitly returning `false`.
52474                *
52475                * **Note:** As with other "Collections" methods, objects with a "length"
52476                * property are iterated like arrays. To avoid this behavior use `_.forIn`
52477                * or `_.forOwn` for object iteration.
52478                *
52479                * @static
52480                * @memberOf _
52481                * @since 0.1.0
52482                * @alias each
52483                * @category Collection
52484                * @param {Array|Object} collection The collection to iterate over.
52485                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
52486                * @returns {Array|Object} Returns `collection`.
52487                * @see _.forEachRight
52488                * @example
52489                *
52490                * _.forEach([1, 2], function(value) {
52491                *   console.log(value);
52492                * });
52493                * // => Logs `1` then `2`.
52494                *
52495                * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
52496                *   console.log(key);
52497                * });
52498                * // => Logs 'a' then 'b' (iteration order is not guaranteed).
52499                */
52500
52501
52502               function forEach(collection, iteratee) {
52503                 var func = isArray(collection) ? arrayEach : baseEach;
52504                 return func(collection, getIteratee(iteratee, 3));
52505               }
52506               /**
52507                * This method is like `_.forEach` except that it iterates over elements of
52508                * `collection` from right to left.
52509                *
52510                * @static
52511                * @memberOf _
52512                * @since 2.0.0
52513                * @alias eachRight
52514                * @category Collection
52515                * @param {Array|Object} collection The collection to iterate over.
52516                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
52517                * @returns {Array|Object} Returns `collection`.
52518                * @see _.forEach
52519                * @example
52520                *
52521                * _.forEachRight([1, 2], function(value) {
52522                *   console.log(value);
52523                * });
52524                * // => Logs `2` then `1`.
52525                */
52526
52527
52528               function forEachRight(collection, iteratee) {
52529                 var func = isArray(collection) ? arrayEachRight : baseEachRight;
52530                 return func(collection, getIteratee(iteratee, 3));
52531               }
52532               /**
52533                * Creates an object composed of keys generated from the results of running
52534                * each element of `collection` thru `iteratee`. The order of grouped values
52535                * is determined by the order they occur in `collection`. The corresponding
52536                * value of each key is an array of elements responsible for generating the
52537                * key. The iteratee is invoked with one argument: (value).
52538                *
52539                * @static
52540                * @memberOf _
52541                * @since 0.1.0
52542                * @category Collection
52543                * @param {Array|Object} collection The collection to iterate over.
52544                * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
52545                * @returns {Object} Returns the composed aggregate object.
52546                * @example
52547                *
52548                * _.groupBy([6.1, 4.2, 6.3], Math.floor);
52549                * // => { '4': [4.2], '6': [6.1, 6.3] }
52550                *
52551                * // The `_.property` iteratee shorthand.
52552                * _.groupBy(['one', 'two', 'three'], 'length');
52553                * // => { '3': ['one', 'two'], '5': ['three'] }
52554                */
52555
52556
52557               var groupBy = createAggregator(function (result, value, key) {
52558                 if (hasOwnProperty.call(result, key)) {
52559                   result[key].push(value);
52560                 } else {
52561                   baseAssignValue(result, key, [value]);
52562                 }
52563               });
52564               /**
52565                * Checks if `value` is in `collection`. If `collection` is a string, it's
52566                * checked for a substring of `value`, otherwise
52567                * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
52568                * is used for equality comparisons. If `fromIndex` is negative, it's used as
52569                * the offset from the end of `collection`.
52570                *
52571                * @static
52572                * @memberOf _
52573                * @since 0.1.0
52574                * @category Collection
52575                * @param {Array|Object|string} collection The collection to inspect.
52576                * @param {*} value The value to search for.
52577                * @param {number} [fromIndex=0] The index to search from.
52578                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
52579                * @returns {boolean} Returns `true` if `value` is found, else `false`.
52580                * @example
52581                *
52582                * _.includes([1, 2, 3], 1);
52583                * // => true
52584                *
52585                * _.includes([1, 2, 3], 1, 2);
52586                * // => false
52587                *
52588                * _.includes({ 'a': 1, 'b': 2 }, 1);
52589                * // => true
52590                *
52591                * _.includes('abcd', 'bc');
52592                * // => true
52593                */
52594
52595               function includes(collection, value, fromIndex, guard) {
52596                 collection = isArrayLike(collection) ? collection : values(collection);
52597                 fromIndex = fromIndex && !guard ? toInteger(fromIndex) : 0;
52598                 var length = collection.length;
52599
52600                 if (fromIndex < 0) {
52601                   fromIndex = nativeMax(length + fromIndex, 0);
52602                 }
52603
52604                 return isString(collection) ? fromIndex <= length && collection.indexOf(value, fromIndex) > -1 : !!length && baseIndexOf(collection, value, fromIndex) > -1;
52605               }
52606               /**
52607                * Invokes the method at `path` of each element in `collection`, returning
52608                * an array of the results of each invoked method. Any additional arguments
52609                * are provided to each invoked method. If `path` is a function, it's invoked
52610                * for, and `this` bound to, each element in `collection`.
52611                *
52612                * @static
52613                * @memberOf _
52614                * @since 4.0.0
52615                * @category Collection
52616                * @param {Array|Object} collection The collection to iterate over.
52617                * @param {Array|Function|string} path The path of the method to invoke or
52618                *  the function invoked per iteration.
52619                * @param {...*} [args] The arguments to invoke each method with.
52620                * @returns {Array} Returns the array of results.
52621                * @example
52622                *
52623                * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort');
52624                * // => [[1, 5, 7], [1, 2, 3]]
52625                *
52626                * _.invokeMap([123, 456], String.prototype.split, '');
52627                * // => [['1', '2', '3'], ['4', '5', '6']]
52628                */
52629
52630
52631               var invokeMap = baseRest(function (collection, path, args) {
52632                 var index = -1,
52633                     isFunc = typeof path == 'function',
52634                     result = isArrayLike(collection) ? Array(collection.length) : [];
52635                 baseEach(collection, function (value) {
52636                   result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);
52637                 });
52638                 return result;
52639               });
52640               /**
52641                * Creates an object composed of keys generated from the results of running
52642                * each element of `collection` thru `iteratee`. The corresponding value of
52643                * each key is the last element responsible for generating the key. The
52644                * iteratee is invoked with one argument: (value).
52645                *
52646                * @static
52647                * @memberOf _
52648                * @since 4.0.0
52649                * @category Collection
52650                * @param {Array|Object} collection The collection to iterate over.
52651                * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
52652                * @returns {Object} Returns the composed aggregate object.
52653                * @example
52654                *
52655                * var array = [
52656                *   { 'dir': 'left', 'code': 97 },
52657                *   { 'dir': 'right', 'code': 100 }
52658                * ];
52659                *
52660                * _.keyBy(array, function(o) {
52661                *   return String.fromCharCode(o.code);
52662                * });
52663                * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
52664                *
52665                * _.keyBy(array, 'dir');
52666                * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
52667                */
52668
52669               var keyBy = createAggregator(function (result, value, key) {
52670                 baseAssignValue(result, key, value);
52671               });
52672               /**
52673                * Creates an array of values by running each element in `collection` thru
52674                * `iteratee`. The iteratee is invoked with three arguments:
52675                * (value, index|key, collection).
52676                *
52677                * Many lodash methods are guarded to work as iteratees for methods like
52678                * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
52679                *
52680                * The guarded methods are:
52681                * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
52682                * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
52683                * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
52684                * `template`, `trim`, `trimEnd`, `trimStart`, and `words`
52685                *
52686                * @static
52687                * @memberOf _
52688                * @since 0.1.0
52689                * @category Collection
52690                * @param {Array|Object} collection The collection to iterate over.
52691                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
52692                * @returns {Array} Returns the new mapped array.
52693                * @example
52694                *
52695                * function square(n) {
52696                *   return n * n;
52697                * }
52698                *
52699                * _.map([4, 8], square);
52700                * // => [16, 64]
52701                *
52702                * _.map({ 'a': 4, 'b': 8 }, square);
52703                * // => [16, 64] (iteration order is not guaranteed)
52704                *
52705                * var users = [
52706                *   { 'user': 'barney' },
52707                *   { 'user': 'fred' }
52708                * ];
52709                *
52710                * // The `_.property` iteratee shorthand.
52711                * _.map(users, 'user');
52712                * // => ['barney', 'fred']
52713                */
52714
52715               function map(collection, iteratee) {
52716                 var func = isArray(collection) ? arrayMap : baseMap;
52717                 return func(collection, getIteratee(iteratee, 3));
52718               }
52719               /**
52720                * This method is like `_.sortBy` except that it allows specifying the sort
52721                * orders of the iteratees to sort by. If `orders` is unspecified, all values
52722                * are sorted in ascending order. Otherwise, specify an order of "desc" for
52723                * descending or "asc" for ascending sort order of corresponding values.
52724                *
52725                * @static
52726                * @memberOf _
52727                * @since 4.0.0
52728                * @category Collection
52729                * @param {Array|Object} collection The collection to iterate over.
52730                * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]]
52731                *  The iteratees to sort by.
52732                * @param {string[]} [orders] The sort orders of `iteratees`.
52733                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
52734                * @returns {Array} Returns the new sorted array.
52735                * @example
52736                *
52737                * var users = [
52738                *   { 'user': 'fred',   'age': 48 },
52739                *   { 'user': 'barney', 'age': 34 },
52740                *   { 'user': 'fred',   'age': 40 },
52741                *   { 'user': 'barney', 'age': 36 }
52742                * ];
52743                *
52744                * // Sort by `user` in ascending order and by `age` in descending order.
52745                * _.orderBy(users, ['user', 'age'], ['asc', 'desc']);
52746                * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
52747                */
52748
52749
52750               function orderBy(collection, iteratees, orders, guard) {
52751                 if (collection == null) {
52752                   return [];
52753                 }
52754
52755                 if (!isArray(iteratees)) {
52756                   iteratees = iteratees == null ? [] : [iteratees];
52757                 }
52758
52759                 orders = guard ? undefined$1 : orders;
52760
52761                 if (!isArray(orders)) {
52762                   orders = orders == null ? [] : [orders];
52763                 }
52764
52765                 return baseOrderBy(collection, iteratees, orders);
52766               }
52767               /**
52768                * Creates an array of elements split into two groups, the first of which
52769                * contains elements `predicate` returns truthy for, the second of which
52770                * contains elements `predicate` returns falsey for. The predicate is
52771                * invoked with one argument: (value).
52772                *
52773                * @static
52774                * @memberOf _
52775                * @since 3.0.0
52776                * @category Collection
52777                * @param {Array|Object} collection The collection to iterate over.
52778                * @param {Function} [predicate=_.identity] The function invoked per iteration.
52779                * @returns {Array} Returns the array of grouped elements.
52780                * @example
52781                *
52782                * var users = [
52783                *   { 'user': 'barney',  'age': 36, 'active': false },
52784                *   { 'user': 'fred',    'age': 40, 'active': true },
52785                *   { 'user': 'pebbles', 'age': 1,  'active': false }
52786                * ];
52787                *
52788                * _.partition(users, function(o) { return o.active; });
52789                * // => objects for [['fred'], ['barney', 'pebbles']]
52790                *
52791                * // The `_.matches` iteratee shorthand.
52792                * _.partition(users, { 'age': 1, 'active': false });
52793                * // => objects for [['pebbles'], ['barney', 'fred']]
52794                *
52795                * // The `_.matchesProperty` iteratee shorthand.
52796                * _.partition(users, ['active', false]);
52797                * // => objects for [['barney', 'pebbles'], ['fred']]
52798                *
52799                * // The `_.property` iteratee shorthand.
52800                * _.partition(users, 'active');
52801                * // => objects for [['fred'], ['barney', 'pebbles']]
52802                */
52803
52804
52805               var partition = createAggregator(function (result, value, key) {
52806                 result[key ? 0 : 1].push(value);
52807               }, function () {
52808                 return [[], []];
52809               });
52810               /**
52811                * Reduces `collection` to a value which is the accumulated result of running
52812                * each element in `collection` thru `iteratee`, where each successive
52813                * invocation is supplied the return value of the previous. If `accumulator`
52814                * is not given, the first element of `collection` is used as the initial
52815                * value. The iteratee is invoked with four arguments:
52816                * (accumulator, value, index|key, collection).
52817                *
52818                * Many lodash methods are guarded to work as iteratees for methods like
52819                * `_.reduce`, `_.reduceRight`, and `_.transform`.
52820                *
52821                * The guarded methods are:
52822                * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
52823                * and `sortBy`
52824                *
52825                * @static
52826                * @memberOf _
52827                * @since 0.1.0
52828                * @category Collection
52829                * @param {Array|Object} collection The collection to iterate over.
52830                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
52831                * @param {*} [accumulator] The initial value.
52832                * @returns {*} Returns the accumulated value.
52833                * @see _.reduceRight
52834                * @example
52835                *
52836                * _.reduce([1, 2], function(sum, n) {
52837                *   return sum + n;
52838                * }, 0);
52839                * // => 3
52840                *
52841                * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
52842                *   (result[value] || (result[value] = [])).push(key);
52843                *   return result;
52844                * }, {});
52845                * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
52846                */
52847
52848               function reduce(collection, iteratee, accumulator) {
52849                 var func = isArray(collection) ? arrayReduce : baseReduce,
52850                     initAccum = arguments.length < 3;
52851                 return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);
52852               }
52853               /**
52854                * This method is like `_.reduce` except that it iterates over elements of
52855                * `collection` from right to left.
52856                *
52857                * @static
52858                * @memberOf _
52859                * @since 0.1.0
52860                * @category Collection
52861                * @param {Array|Object} collection The collection to iterate over.
52862                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
52863                * @param {*} [accumulator] The initial value.
52864                * @returns {*} Returns the accumulated value.
52865                * @see _.reduce
52866                * @example
52867                *
52868                * var array = [[0, 1], [2, 3], [4, 5]];
52869                *
52870                * _.reduceRight(array, function(flattened, other) {
52871                *   return flattened.concat(other);
52872                * }, []);
52873                * // => [4, 5, 2, 3, 0, 1]
52874                */
52875
52876
52877               function reduceRight(collection, iteratee, accumulator) {
52878                 var func = isArray(collection) ? arrayReduceRight : baseReduce,
52879                     initAccum = arguments.length < 3;
52880                 return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);
52881               }
52882               /**
52883                * The opposite of `_.filter`; this method returns the elements of `collection`
52884                * that `predicate` does **not** return truthy for.
52885                *
52886                * @static
52887                * @memberOf _
52888                * @since 0.1.0
52889                * @category Collection
52890                * @param {Array|Object} collection The collection to iterate over.
52891                * @param {Function} [predicate=_.identity] The function invoked per iteration.
52892                * @returns {Array} Returns the new filtered array.
52893                * @see _.filter
52894                * @example
52895                *
52896                * var users = [
52897                *   { 'user': 'barney', 'age': 36, 'active': false },
52898                *   { 'user': 'fred',   'age': 40, 'active': true }
52899                * ];
52900                *
52901                * _.reject(users, function(o) { return !o.active; });
52902                * // => objects for ['fred']
52903                *
52904                * // The `_.matches` iteratee shorthand.
52905                * _.reject(users, { 'age': 40, 'active': true });
52906                * // => objects for ['barney']
52907                *
52908                * // The `_.matchesProperty` iteratee shorthand.
52909                * _.reject(users, ['active', false]);
52910                * // => objects for ['fred']
52911                *
52912                * // The `_.property` iteratee shorthand.
52913                * _.reject(users, 'active');
52914                * // => objects for ['barney']
52915                */
52916
52917
52918               function reject(collection, predicate) {
52919                 var func = isArray(collection) ? arrayFilter : baseFilter;
52920                 return func(collection, negate(getIteratee(predicate, 3)));
52921               }
52922               /**
52923                * Gets a random element from `collection`.
52924                *
52925                * @static
52926                * @memberOf _
52927                * @since 2.0.0
52928                * @category Collection
52929                * @param {Array|Object} collection The collection to sample.
52930                * @returns {*} Returns the random element.
52931                * @example
52932                *
52933                * _.sample([1, 2, 3, 4]);
52934                * // => 2
52935                */
52936
52937
52938               function sample(collection) {
52939                 var func = isArray(collection) ? arraySample : baseSample;
52940                 return func(collection);
52941               }
52942               /**
52943                * Gets `n` random elements at unique keys from `collection` up to the
52944                * size of `collection`.
52945                *
52946                * @static
52947                * @memberOf _
52948                * @since 4.0.0
52949                * @category Collection
52950                * @param {Array|Object} collection The collection to sample.
52951                * @param {number} [n=1] The number of elements to sample.
52952                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
52953                * @returns {Array} Returns the random elements.
52954                * @example
52955                *
52956                * _.sampleSize([1, 2, 3], 2);
52957                * // => [3, 1]
52958                *
52959                * _.sampleSize([1, 2, 3], 4);
52960                * // => [2, 3, 1]
52961                */
52962
52963
52964               function sampleSize(collection, n, guard) {
52965                 if (guard ? isIterateeCall(collection, n, guard) : n === undefined$1) {
52966                   n = 1;
52967                 } else {
52968                   n = toInteger(n);
52969                 }
52970
52971                 var func = isArray(collection) ? arraySampleSize : baseSampleSize;
52972                 return func(collection, n);
52973               }
52974               /**
52975                * Creates an array of shuffled values, using a version of the
52976                * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
52977                *
52978                * @static
52979                * @memberOf _
52980                * @since 0.1.0
52981                * @category Collection
52982                * @param {Array|Object} collection The collection to shuffle.
52983                * @returns {Array} Returns the new shuffled array.
52984                * @example
52985                *
52986                * _.shuffle([1, 2, 3, 4]);
52987                * // => [4, 1, 3, 2]
52988                */
52989
52990
52991               function shuffle(collection) {
52992                 var func = isArray(collection) ? arrayShuffle : baseShuffle;
52993                 return func(collection);
52994               }
52995               /**
52996                * Gets the size of `collection` by returning its length for array-like
52997                * values or the number of own enumerable string keyed properties for objects.
52998                *
52999                * @static
53000                * @memberOf _
53001                * @since 0.1.0
53002                * @category Collection
53003                * @param {Array|Object|string} collection The collection to inspect.
53004                * @returns {number} Returns the collection size.
53005                * @example
53006                *
53007                * _.size([1, 2, 3]);
53008                * // => 3
53009                *
53010                * _.size({ 'a': 1, 'b': 2 });
53011                * // => 2
53012                *
53013                * _.size('pebbles');
53014                * // => 7
53015                */
53016
53017
53018               function size(collection) {
53019                 if (collection == null) {
53020                   return 0;
53021                 }
53022
53023                 if (isArrayLike(collection)) {
53024                   return isString(collection) ? stringSize(collection) : collection.length;
53025                 }
53026
53027                 var tag = getTag(collection);
53028
53029                 if (tag == mapTag || tag == setTag) {
53030                   return collection.size;
53031                 }
53032
53033                 return baseKeys(collection).length;
53034               }
53035               /**
53036                * Checks if `predicate` returns truthy for **any** element of `collection`.
53037                * Iteration is stopped once `predicate` returns truthy. The predicate is
53038                * invoked with three arguments: (value, index|key, collection).
53039                *
53040                * @static
53041                * @memberOf _
53042                * @since 0.1.0
53043                * @category Collection
53044                * @param {Array|Object} collection The collection to iterate over.
53045                * @param {Function} [predicate=_.identity] The function invoked per iteration.
53046                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
53047                * @returns {boolean} Returns `true` if any element passes the predicate check,
53048                *  else `false`.
53049                * @example
53050                *
53051                * _.some([null, 0, 'yes', false], Boolean);
53052                * // => true
53053                *
53054                * var users = [
53055                *   { 'user': 'barney', 'active': true },
53056                *   { 'user': 'fred',   'active': false }
53057                * ];
53058                *
53059                * // The `_.matches` iteratee shorthand.
53060                * _.some(users, { 'user': 'barney', 'active': false });
53061                * // => false
53062                *
53063                * // The `_.matchesProperty` iteratee shorthand.
53064                * _.some(users, ['active', false]);
53065                * // => true
53066                *
53067                * // The `_.property` iteratee shorthand.
53068                * _.some(users, 'active');
53069                * // => true
53070                */
53071
53072
53073               function some(collection, predicate, guard) {
53074                 var func = isArray(collection) ? arraySome : baseSome;
53075
53076                 if (guard && isIterateeCall(collection, predicate, guard)) {
53077                   predicate = undefined$1;
53078                 }
53079
53080                 return func(collection, getIteratee(predicate, 3));
53081               }
53082               /**
53083                * Creates an array of elements, sorted in ascending order by the results of
53084                * running each element in a collection thru each iteratee. This method
53085                * performs a stable sort, that is, it preserves the original sort order of
53086                * equal elements. The iteratees are invoked with one argument: (value).
53087                *
53088                * @static
53089                * @memberOf _
53090                * @since 0.1.0
53091                * @category Collection
53092                * @param {Array|Object} collection The collection to iterate over.
53093                * @param {...(Function|Function[])} [iteratees=[_.identity]]
53094                *  The iteratees to sort by.
53095                * @returns {Array} Returns the new sorted array.
53096                * @example
53097                *
53098                * var users = [
53099                *   { 'user': 'fred',   'age': 48 },
53100                *   { 'user': 'barney', 'age': 36 },
53101                *   { 'user': 'fred',   'age': 30 },
53102                *   { 'user': 'barney', 'age': 34 }
53103                * ];
53104                *
53105                * _.sortBy(users, [function(o) { return o.user; }]);
53106                * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 30]]
53107                *
53108                * _.sortBy(users, ['user', 'age']);
53109                * // => objects for [['barney', 34], ['barney', 36], ['fred', 30], ['fred', 48]]
53110                */
53111
53112
53113               var sortBy = baseRest(function (collection, iteratees) {
53114                 if (collection == null) {
53115                   return [];
53116                 }
53117
53118                 var length = iteratees.length;
53119
53120                 if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
53121                   iteratees = [];
53122                 } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
53123                   iteratees = [iteratees[0]];
53124                 }
53125
53126                 return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
53127               });
53128               /*------------------------------------------------------------------------*/
53129
53130               /**
53131                * Gets the timestamp of the number of milliseconds that have elapsed since
53132                * the Unix epoch (1 January 1970 00:00:00 UTC).
53133                *
53134                * @static
53135                * @memberOf _
53136                * @since 2.4.0
53137                * @category Date
53138                * @returns {number} Returns the timestamp.
53139                * @example
53140                *
53141                * _.defer(function(stamp) {
53142                *   console.log(_.now() - stamp);
53143                * }, _.now());
53144                * // => Logs the number of milliseconds it took for the deferred invocation.
53145                */
53146
53147               var now = ctxNow || function () {
53148                 return root.Date.now();
53149               };
53150               /*------------------------------------------------------------------------*/
53151
53152               /**
53153                * The opposite of `_.before`; this method creates a function that invokes
53154                * `func` once it's called `n` or more times.
53155                *
53156                * @static
53157                * @memberOf _
53158                * @since 0.1.0
53159                * @category Function
53160                * @param {number} n The number of calls before `func` is invoked.
53161                * @param {Function} func The function to restrict.
53162                * @returns {Function} Returns the new restricted function.
53163                * @example
53164                *
53165                * var saves = ['profile', 'settings'];
53166                *
53167                * var done = _.after(saves.length, function() {
53168                *   console.log('done saving!');
53169                * });
53170                *
53171                * _.forEach(saves, function(type) {
53172                *   asyncSave({ 'type': type, 'complete': done });
53173                * });
53174                * // => Logs 'done saving!' after the two async saves have completed.
53175                */
53176
53177
53178               function after(n, func) {
53179                 if (typeof func != 'function') {
53180                   throw new TypeError(FUNC_ERROR_TEXT);
53181                 }
53182
53183                 n = toInteger(n);
53184                 return function () {
53185                   if (--n < 1) {
53186                     return func.apply(this, arguments);
53187                   }
53188                 };
53189               }
53190               /**
53191                * Creates a function that invokes `func`, with up to `n` arguments,
53192                * ignoring any additional arguments.
53193                *
53194                * @static
53195                * @memberOf _
53196                * @since 3.0.0
53197                * @category Function
53198                * @param {Function} func The function to cap arguments for.
53199                * @param {number} [n=func.length] The arity cap.
53200                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
53201                * @returns {Function} Returns the new capped function.
53202                * @example
53203                *
53204                * _.map(['6', '8', '10'], _.ary(parseInt, 1));
53205                * // => [6, 8, 10]
53206                */
53207
53208
53209               function ary(func, n, guard) {
53210                 n = guard ? undefined$1 : n;
53211                 n = func && n == null ? func.length : n;
53212                 return createWrap(func, WRAP_ARY_FLAG, undefined$1, undefined$1, undefined$1, undefined$1, n);
53213               }
53214               /**
53215                * Creates a function that invokes `func`, with the `this` binding and arguments
53216                * of the created function, while it's called less than `n` times. Subsequent
53217                * calls to the created function return the result of the last `func` invocation.
53218                *
53219                * @static
53220                * @memberOf _
53221                * @since 3.0.0
53222                * @category Function
53223                * @param {number} n The number of calls at which `func` is no longer invoked.
53224                * @param {Function} func The function to restrict.
53225                * @returns {Function} Returns the new restricted function.
53226                * @example
53227                *
53228                * jQuery(element).on('click', _.before(5, addContactToList));
53229                * // => Allows adding up to 4 contacts to the list.
53230                */
53231
53232
53233               function before(n, func) {
53234                 var result;
53235
53236                 if (typeof func != 'function') {
53237                   throw new TypeError(FUNC_ERROR_TEXT);
53238                 }
53239
53240                 n = toInteger(n);
53241                 return function () {
53242                   if (--n > 0) {
53243                     result = func.apply(this, arguments);
53244                   }
53245
53246                   if (n <= 1) {
53247                     func = undefined$1;
53248                   }
53249
53250                   return result;
53251                 };
53252               }
53253               /**
53254                * Creates a function that invokes `func` with the `this` binding of `thisArg`
53255                * and `partials` prepended to the arguments it receives.
53256                *
53257                * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
53258                * may be used as a placeholder for partially applied arguments.
53259                *
53260                * **Note:** Unlike native `Function#bind`, this method doesn't set the "length"
53261                * property of bound functions.
53262                *
53263                * @static
53264                * @memberOf _
53265                * @since 0.1.0
53266                * @category Function
53267                * @param {Function} func The function to bind.
53268                * @param {*} thisArg The `this` binding of `func`.
53269                * @param {...*} [partials] The arguments to be partially applied.
53270                * @returns {Function} Returns the new bound function.
53271                * @example
53272                *
53273                * function greet(greeting, punctuation) {
53274                *   return greeting + ' ' + this.user + punctuation;
53275                * }
53276                *
53277                * var object = { 'user': 'fred' };
53278                *
53279                * var bound = _.bind(greet, object, 'hi');
53280                * bound('!');
53281                * // => 'hi fred!'
53282                *
53283                * // Bound with placeholders.
53284                * var bound = _.bind(greet, object, _, '!');
53285                * bound('hi');
53286                * // => 'hi fred!'
53287                */
53288
53289
53290               var bind = baseRest(function (func, thisArg, partials) {
53291                 var bitmask = WRAP_BIND_FLAG;
53292
53293                 if (partials.length) {
53294                   var holders = replaceHolders(partials, getHolder(bind));
53295                   bitmask |= WRAP_PARTIAL_FLAG;
53296                 }
53297
53298                 return createWrap(func, bitmask, thisArg, partials, holders);
53299               });
53300               /**
53301                * Creates a function that invokes the method at `object[key]` with `partials`
53302                * prepended to the arguments it receives.
53303                *
53304                * This method differs from `_.bind` by allowing bound functions to reference
53305                * methods that may be redefined or don't yet exist. See
53306                * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
53307                * for more details.
53308                *
53309                * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
53310                * builds, may be used as a placeholder for partially applied arguments.
53311                *
53312                * @static
53313                * @memberOf _
53314                * @since 0.10.0
53315                * @category Function
53316                * @param {Object} object The object to invoke the method on.
53317                * @param {string} key The key of the method.
53318                * @param {...*} [partials] The arguments to be partially applied.
53319                * @returns {Function} Returns the new bound function.
53320                * @example
53321                *
53322                * var object = {
53323                *   'user': 'fred',
53324                *   'greet': function(greeting, punctuation) {
53325                *     return greeting + ' ' + this.user + punctuation;
53326                *   }
53327                * };
53328                *
53329                * var bound = _.bindKey(object, 'greet', 'hi');
53330                * bound('!');
53331                * // => 'hi fred!'
53332                *
53333                * object.greet = function(greeting, punctuation) {
53334                *   return greeting + 'ya ' + this.user + punctuation;
53335                * };
53336                *
53337                * bound('!');
53338                * // => 'hiya fred!'
53339                *
53340                * // Bound with placeholders.
53341                * var bound = _.bindKey(object, 'greet', _, '!');
53342                * bound('hi');
53343                * // => 'hiya fred!'
53344                */
53345
53346               var bindKey = baseRest(function (object, key, partials) {
53347                 var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;
53348
53349                 if (partials.length) {
53350                   var holders = replaceHolders(partials, getHolder(bindKey));
53351                   bitmask |= WRAP_PARTIAL_FLAG;
53352                 }
53353
53354                 return createWrap(key, bitmask, object, partials, holders);
53355               });
53356               /**
53357                * Creates a function that accepts arguments of `func` and either invokes
53358                * `func` returning its result, if at least `arity` number of arguments have
53359                * been provided, or returns a function that accepts the remaining `func`
53360                * arguments, and so on. The arity of `func` may be specified if `func.length`
53361                * is not sufficient.
53362                *
53363                * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
53364                * may be used as a placeholder for provided arguments.
53365                *
53366                * **Note:** This method doesn't set the "length" property of curried functions.
53367                *
53368                * @static
53369                * @memberOf _
53370                * @since 2.0.0
53371                * @category Function
53372                * @param {Function} func The function to curry.
53373                * @param {number} [arity=func.length] The arity of `func`.
53374                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
53375                * @returns {Function} Returns the new curried function.
53376                * @example
53377                *
53378                * var abc = function(a, b, c) {
53379                *   return [a, b, c];
53380                * };
53381                *
53382                * var curried = _.curry(abc);
53383                *
53384                * curried(1)(2)(3);
53385                * // => [1, 2, 3]
53386                *
53387                * curried(1, 2)(3);
53388                * // => [1, 2, 3]
53389                *
53390                * curried(1, 2, 3);
53391                * // => [1, 2, 3]
53392                *
53393                * // Curried with placeholders.
53394                * curried(1)(_, 3)(2);
53395                * // => [1, 2, 3]
53396                */
53397
53398               function curry(func, arity, guard) {
53399                 arity = guard ? undefined$1 : arity;
53400                 var result = createWrap(func, WRAP_CURRY_FLAG, undefined$1, undefined$1, undefined$1, undefined$1, undefined$1, arity);
53401                 result.placeholder = curry.placeholder;
53402                 return result;
53403               }
53404               /**
53405                * This method is like `_.curry` except that arguments are applied to `func`
53406                * in the manner of `_.partialRight` instead of `_.partial`.
53407                *
53408                * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
53409                * builds, may be used as a placeholder for provided arguments.
53410                *
53411                * **Note:** This method doesn't set the "length" property of curried functions.
53412                *
53413                * @static
53414                * @memberOf _
53415                * @since 3.0.0
53416                * @category Function
53417                * @param {Function} func The function to curry.
53418                * @param {number} [arity=func.length] The arity of `func`.
53419                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
53420                * @returns {Function} Returns the new curried function.
53421                * @example
53422                *
53423                * var abc = function(a, b, c) {
53424                *   return [a, b, c];
53425                * };
53426                *
53427                * var curried = _.curryRight(abc);
53428                *
53429                * curried(3)(2)(1);
53430                * // => [1, 2, 3]
53431                *
53432                * curried(2, 3)(1);
53433                * // => [1, 2, 3]
53434                *
53435                * curried(1, 2, 3);
53436                * // => [1, 2, 3]
53437                *
53438                * // Curried with placeholders.
53439                * curried(3)(1, _)(2);
53440                * // => [1, 2, 3]
53441                */
53442
53443
53444               function curryRight(func, arity, guard) {
53445                 arity = guard ? undefined$1 : arity;
53446                 var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined$1, undefined$1, undefined$1, undefined$1, undefined$1, arity);
53447                 result.placeholder = curryRight.placeholder;
53448                 return result;
53449               }
53450               /**
53451                * Creates a debounced function that delays invoking `func` until after `wait`
53452                * milliseconds have elapsed since the last time the debounced function was
53453                * invoked. The debounced function comes with a `cancel` method to cancel
53454                * delayed `func` invocations and a `flush` method to immediately invoke them.
53455                * Provide `options` to indicate whether `func` should be invoked on the
53456                * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
53457                * with the last arguments provided to the debounced function. Subsequent
53458                * calls to the debounced function return the result of the last `func`
53459                * invocation.
53460                *
53461                * **Note:** If `leading` and `trailing` options are `true`, `func` is
53462                * invoked on the trailing edge of the timeout only if the debounced function
53463                * is invoked more than once during the `wait` timeout.
53464                *
53465                * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
53466                * until to the next tick, similar to `setTimeout` with a timeout of `0`.
53467                *
53468                * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
53469                * for details over the differences between `_.debounce` and `_.throttle`.
53470                *
53471                * @static
53472                * @memberOf _
53473                * @since 0.1.0
53474                * @category Function
53475                * @param {Function} func The function to debounce.
53476                * @param {number} [wait=0] The number of milliseconds to delay.
53477                * @param {Object} [options={}] The options object.
53478                * @param {boolean} [options.leading=false]
53479                *  Specify invoking on the leading edge of the timeout.
53480                * @param {number} [options.maxWait]
53481                *  The maximum time `func` is allowed to be delayed before it's invoked.
53482                * @param {boolean} [options.trailing=true]
53483                *  Specify invoking on the trailing edge of the timeout.
53484                * @returns {Function} Returns the new debounced function.
53485                * @example
53486                *
53487                * // Avoid costly calculations while the window size is in flux.
53488                * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
53489                *
53490                * // Invoke `sendMail` when clicked, debouncing subsequent calls.
53491                * jQuery(element).on('click', _.debounce(sendMail, 300, {
53492                *   'leading': true,
53493                *   'trailing': false
53494                * }));
53495                *
53496                * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
53497                * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
53498                * var source = new EventSource('/stream');
53499                * jQuery(source).on('message', debounced);
53500                *
53501                * // Cancel the trailing debounced invocation.
53502                * jQuery(window).on('popstate', debounced.cancel);
53503                */
53504
53505
53506               function debounce(func, wait, options) {
53507                 var lastArgs,
53508                     lastThis,
53509                     maxWait,
53510                     result,
53511                     timerId,
53512                     lastCallTime,
53513                     lastInvokeTime = 0,
53514                     leading = false,
53515                     maxing = false,
53516                     trailing = true;
53517
53518                 if (typeof func != 'function') {
53519                   throw new TypeError(FUNC_ERROR_TEXT);
53520                 }
53521
53522                 wait = toNumber(wait) || 0;
53523
53524                 if (isObject(options)) {
53525                   leading = !!options.leading;
53526                   maxing = 'maxWait' in options;
53527                   maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
53528                   trailing = 'trailing' in options ? !!options.trailing : trailing;
53529                 }
53530
53531                 function invokeFunc(time) {
53532                   var args = lastArgs,
53533                       thisArg = lastThis;
53534                   lastArgs = lastThis = undefined$1;
53535                   lastInvokeTime = time;
53536                   result = func.apply(thisArg, args);
53537                   return result;
53538                 }
53539
53540                 function leadingEdge(time) {
53541                   // Reset any `maxWait` timer.
53542                   lastInvokeTime = time; // Start the timer for the trailing edge.
53543
53544                   timerId = setTimeout(timerExpired, wait); // Invoke the leading edge.
53545
53546                   return leading ? invokeFunc(time) : result;
53547                 }
53548
53549                 function remainingWait(time) {
53550                   var timeSinceLastCall = time - lastCallTime,
53551                       timeSinceLastInvoke = time - lastInvokeTime,
53552                       timeWaiting = wait - timeSinceLastCall;
53553                   return maxing ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting;
53554                 }
53555
53556                 function shouldInvoke(time) {
53557                   var timeSinceLastCall = time - lastCallTime,
53558                       timeSinceLastInvoke = time - lastInvokeTime; // Either this is the first call, activity has stopped and we're at the
53559                   // trailing edge, the system time has gone backwards and we're treating
53560                   // it as the trailing edge, or we've hit the `maxWait` limit.
53561
53562                   return lastCallTime === undefined$1 || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait;
53563                 }
53564
53565                 function timerExpired() {
53566                   var time = now();
53567
53568                   if (shouldInvoke(time)) {
53569                     return trailingEdge(time);
53570                   } // Restart the timer.
53571
53572
53573                   timerId = setTimeout(timerExpired, remainingWait(time));
53574                 }
53575
53576                 function trailingEdge(time) {
53577                   timerId = undefined$1; // Only invoke if we have `lastArgs` which means `func` has been
53578                   // debounced at least once.
53579
53580                   if (trailing && lastArgs) {
53581                     return invokeFunc(time);
53582                   }
53583
53584                   lastArgs = lastThis = undefined$1;
53585                   return result;
53586                 }
53587
53588                 function cancel() {
53589                   if (timerId !== undefined$1) {
53590                     clearTimeout(timerId);
53591                   }
53592
53593                   lastInvokeTime = 0;
53594                   lastArgs = lastCallTime = lastThis = timerId = undefined$1;
53595                 }
53596
53597                 function flush() {
53598                   return timerId === undefined$1 ? result : trailingEdge(now());
53599                 }
53600
53601                 function debounced() {
53602                   var time = now(),
53603                       isInvoking = shouldInvoke(time);
53604                   lastArgs = arguments;
53605                   lastThis = this;
53606                   lastCallTime = time;
53607
53608                   if (isInvoking) {
53609                     if (timerId === undefined$1) {
53610                       return leadingEdge(lastCallTime);
53611                     }
53612
53613                     if (maxing) {
53614                       // Handle invocations in a tight loop.
53615                       clearTimeout(timerId);
53616                       timerId = setTimeout(timerExpired, wait);
53617                       return invokeFunc(lastCallTime);
53618                     }
53619                   }
53620
53621                   if (timerId === undefined$1) {
53622                     timerId = setTimeout(timerExpired, wait);
53623                   }
53624
53625                   return result;
53626                 }
53627
53628                 debounced.cancel = cancel;
53629                 debounced.flush = flush;
53630                 return debounced;
53631               }
53632               /**
53633                * Defers invoking the `func` until the current call stack has cleared. Any
53634                * additional arguments are provided to `func` when it's invoked.
53635                *
53636                * @static
53637                * @memberOf _
53638                * @since 0.1.0
53639                * @category Function
53640                * @param {Function} func The function to defer.
53641                * @param {...*} [args] The arguments to invoke `func` with.
53642                * @returns {number} Returns the timer id.
53643                * @example
53644                *
53645                * _.defer(function(text) {
53646                *   console.log(text);
53647                * }, 'deferred');
53648                * // => Logs 'deferred' after one millisecond.
53649                */
53650
53651
53652               var defer = baseRest(function (func, args) {
53653                 return baseDelay(func, 1, args);
53654               });
53655               /**
53656                * Invokes `func` after `wait` milliseconds. Any additional arguments are
53657                * provided to `func` when it's invoked.
53658                *
53659                * @static
53660                * @memberOf _
53661                * @since 0.1.0
53662                * @category Function
53663                * @param {Function} func The function to delay.
53664                * @param {number} wait The number of milliseconds to delay invocation.
53665                * @param {...*} [args] The arguments to invoke `func` with.
53666                * @returns {number} Returns the timer id.
53667                * @example
53668                *
53669                * _.delay(function(text) {
53670                *   console.log(text);
53671                * }, 1000, 'later');
53672                * // => Logs 'later' after one second.
53673                */
53674
53675               var delay = baseRest(function (func, wait, args) {
53676                 return baseDelay(func, toNumber(wait) || 0, args);
53677               });
53678               /**
53679                * Creates a function that invokes `func` with arguments reversed.
53680                *
53681                * @static
53682                * @memberOf _
53683                * @since 4.0.0
53684                * @category Function
53685                * @param {Function} func The function to flip arguments for.
53686                * @returns {Function} Returns the new flipped function.
53687                * @example
53688                *
53689                * var flipped = _.flip(function() {
53690                *   return _.toArray(arguments);
53691                * });
53692                *
53693                * flipped('a', 'b', 'c', 'd');
53694                * // => ['d', 'c', 'b', 'a']
53695                */
53696
53697               function flip(func) {
53698                 return createWrap(func, WRAP_FLIP_FLAG);
53699               }
53700               /**
53701                * Creates a function that memoizes the result of `func`. If `resolver` is
53702                * provided, it determines the cache key for storing the result based on the
53703                * arguments provided to the memoized function. By default, the first argument
53704                * provided to the memoized function is used as the map cache key. The `func`
53705                * is invoked with the `this` binding of the memoized function.
53706                *
53707                * **Note:** The cache is exposed as the `cache` property on the memoized
53708                * function. Its creation may be customized by replacing the `_.memoize.Cache`
53709                * constructor with one whose instances implement the
53710                * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
53711                * method interface of `clear`, `delete`, `get`, `has`, and `set`.
53712                *
53713                * @static
53714                * @memberOf _
53715                * @since 0.1.0
53716                * @category Function
53717                * @param {Function} func The function to have its output memoized.
53718                * @param {Function} [resolver] The function to resolve the cache key.
53719                * @returns {Function} Returns the new memoized function.
53720                * @example
53721                *
53722                * var object = { 'a': 1, 'b': 2 };
53723                * var other = { 'c': 3, 'd': 4 };
53724                *
53725                * var values = _.memoize(_.values);
53726                * values(object);
53727                * // => [1, 2]
53728                *
53729                * values(other);
53730                * // => [3, 4]
53731                *
53732                * object.a = 2;
53733                * values(object);
53734                * // => [1, 2]
53735                *
53736                * // Modify the result cache.
53737                * values.cache.set(object, ['a', 'b']);
53738                * values(object);
53739                * // => ['a', 'b']
53740                *
53741                * // Replace `_.memoize.Cache`.
53742                * _.memoize.Cache = WeakMap;
53743                */
53744
53745
53746               function memoize(func, resolver) {
53747                 if (typeof func != 'function' || resolver != null && typeof resolver != 'function') {
53748                   throw new TypeError(FUNC_ERROR_TEXT);
53749                 }
53750
53751                 var memoized = function memoized() {
53752                   var args = arguments,
53753                       key = resolver ? resolver.apply(this, args) : args[0],
53754                       cache = memoized.cache;
53755
53756                   if (cache.has(key)) {
53757                     return cache.get(key);
53758                   }
53759
53760                   var result = func.apply(this, args);
53761                   memoized.cache = cache.set(key, result) || cache;
53762                   return result;
53763                 };
53764
53765                 memoized.cache = new (memoize.Cache || MapCache)();
53766                 return memoized;
53767               } // Expose `MapCache`.
53768
53769
53770               memoize.Cache = MapCache;
53771               /**
53772                * Creates a function that negates the result of the predicate `func`. The
53773                * `func` predicate is invoked with the `this` binding and arguments of the
53774                * created function.
53775                *
53776                * @static
53777                * @memberOf _
53778                * @since 3.0.0
53779                * @category Function
53780                * @param {Function} predicate The predicate to negate.
53781                * @returns {Function} Returns the new negated function.
53782                * @example
53783                *
53784                * function isEven(n) {
53785                *   return n % 2 == 0;
53786                * }
53787                *
53788                * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
53789                * // => [1, 3, 5]
53790                */
53791
53792               function negate(predicate) {
53793                 if (typeof predicate != 'function') {
53794                   throw new TypeError(FUNC_ERROR_TEXT);
53795                 }
53796
53797                 return function () {
53798                   var args = arguments;
53799
53800                   switch (args.length) {
53801                     case 0:
53802                       return !predicate.call(this);
53803
53804                     case 1:
53805                       return !predicate.call(this, args[0]);
53806
53807                     case 2:
53808                       return !predicate.call(this, args[0], args[1]);
53809
53810                     case 3:
53811                       return !predicate.call(this, args[0], args[1], args[2]);
53812                   }
53813
53814                   return !predicate.apply(this, args);
53815                 };
53816               }
53817               /**
53818                * Creates a function that is restricted to invoking `func` once. Repeat calls
53819                * to the function return the value of the first invocation. The `func` is
53820                * invoked with the `this` binding and arguments of the created function.
53821                *
53822                * @static
53823                * @memberOf _
53824                * @since 0.1.0
53825                * @category Function
53826                * @param {Function} func The function to restrict.
53827                * @returns {Function} Returns the new restricted function.
53828                * @example
53829                *
53830                * var initialize = _.once(createApplication);
53831                * initialize();
53832                * initialize();
53833                * // => `createApplication` is invoked once
53834                */
53835
53836
53837               function once(func) {
53838                 return before(2, func);
53839               }
53840               /**
53841                * Creates a function that invokes `func` with its arguments transformed.
53842                *
53843                * @static
53844                * @since 4.0.0
53845                * @memberOf _
53846                * @category Function
53847                * @param {Function} func The function to wrap.
53848                * @param {...(Function|Function[])} [transforms=[_.identity]]
53849                *  The argument transforms.
53850                * @returns {Function} Returns the new function.
53851                * @example
53852                *
53853                * function doubled(n) {
53854                *   return n * 2;
53855                * }
53856                *
53857                * function square(n) {
53858                *   return n * n;
53859                * }
53860                *
53861                * var func = _.overArgs(function(x, y) {
53862                *   return [x, y];
53863                * }, [square, doubled]);
53864                *
53865                * func(9, 3);
53866                * // => [81, 6]
53867                *
53868                * func(10, 5);
53869                * // => [100, 10]
53870                */
53871
53872
53873               var overArgs = castRest(function (func, transforms) {
53874                 transforms = transforms.length == 1 && isArray(transforms[0]) ? arrayMap(transforms[0], baseUnary(getIteratee())) : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));
53875                 var funcsLength = transforms.length;
53876                 return baseRest(function (args) {
53877                   var index = -1,
53878                       length = nativeMin(args.length, funcsLength);
53879
53880                   while (++index < length) {
53881                     args[index] = transforms[index].call(this, args[index]);
53882                   }
53883
53884                   return apply(func, this, args);
53885                 });
53886               });
53887               /**
53888                * Creates a function that invokes `func` with `partials` prepended to the
53889                * arguments it receives. This method is like `_.bind` except it does **not**
53890                * alter the `this` binding.
53891                *
53892                * The `_.partial.placeholder` value, which defaults to `_` in monolithic
53893                * builds, may be used as a placeholder for partially applied arguments.
53894                *
53895                * **Note:** This method doesn't set the "length" property of partially
53896                * applied functions.
53897                *
53898                * @static
53899                * @memberOf _
53900                * @since 0.2.0
53901                * @category Function
53902                * @param {Function} func The function to partially apply arguments to.
53903                * @param {...*} [partials] The arguments to be partially applied.
53904                * @returns {Function} Returns the new partially applied function.
53905                * @example
53906                *
53907                * function greet(greeting, name) {
53908                *   return greeting + ' ' + name;
53909                * }
53910                *
53911                * var sayHelloTo = _.partial(greet, 'hello');
53912                * sayHelloTo('fred');
53913                * // => 'hello fred'
53914                *
53915                * // Partially applied with placeholders.
53916                * var greetFred = _.partial(greet, _, 'fred');
53917                * greetFred('hi');
53918                * // => 'hi fred'
53919                */
53920
53921               var partial = baseRest(function (func, partials) {
53922                 var holders = replaceHolders(partials, getHolder(partial));
53923                 return createWrap(func, WRAP_PARTIAL_FLAG, undefined$1, partials, holders);
53924               });
53925               /**
53926                * This method is like `_.partial` except that partially applied arguments
53927                * are appended to the arguments it receives.
53928                *
53929                * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
53930                * builds, may be used as a placeholder for partially applied arguments.
53931                *
53932                * **Note:** This method doesn't set the "length" property of partially
53933                * applied functions.
53934                *
53935                * @static
53936                * @memberOf _
53937                * @since 1.0.0
53938                * @category Function
53939                * @param {Function} func The function to partially apply arguments to.
53940                * @param {...*} [partials] The arguments to be partially applied.
53941                * @returns {Function} Returns the new partially applied function.
53942                * @example
53943                *
53944                * function greet(greeting, name) {
53945                *   return greeting + ' ' + name;
53946                * }
53947                *
53948                * var greetFred = _.partialRight(greet, 'fred');
53949                * greetFred('hi');
53950                * // => 'hi fred'
53951                *
53952                * // Partially applied with placeholders.
53953                * var sayHelloTo = _.partialRight(greet, 'hello', _);
53954                * sayHelloTo('fred');
53955                * // => 'hello fred'
53956                */
53957
53958               var partialRight = baseRest(function (func, partials) {
53959                 var holders = replaceHolders(partials, getHolder(partialRight));
53960                 return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined$1, partials, holders);
53961               });
53962               /**
53963                * Creates a function that invokes `func` with arguments arranged according
53964                * to the specified `indexes` where the argument value at the first index is
53965                * provided as the first argument, the argument value at the second index is
53966                * provided as the second argument, and so on.
53967                *
53968                * @static
53969                * @memberOf _
53970                * @since 3.0.0
53971                * @category Function
53972                * @param {Function} func The function to rearrange arguments for.
53973                * @param {...(number|number[])} indexes The arranged argument indexes.
53974                * @returns {Function} Returns the new function.
53975                * @example
53976                *
53977                * var rearged = _.rearg(function(a, b, c) {
53978                *   return [a, b, c];
53979                * }, [2, 0, 1]);
53980                *
53981                * rearged('b', 'c', 'a')
53982                * // => ['a', 'b', 'c']
53983                */
53984
53985               var rearg = flatRest(function (func, indexes) {
53986                 return createWrap(func, WRAP_REARG_FLAG, undefined$1, undefined$1, undefined$1, indexes);
53987               });
53988               /**
53989                * Creates a function that invokes `func` with the `this` binding of the
53990                * created function and arguments from `start` and beyond provided as
53991                * an array.
53992                *
53993                * **Note:** This method is based on the
53994                * [rest parameter](https://mdn.io/rest_parameters).
53995                *
53996                * @static
53997                * @memberOf _
53998                * @since 4.0.0
53999                * @category Function
54000                * @param {Function} func The function to apply a rest parameter to.
54001                * @param {number} [start=func.length-1] The start position of the rest parameter.
54002                * @returns {Function} Returns the new function.
54003                * @example
54004                *
54005                * var say = _.rest(function(what, names) {
54006                *   return what + ' ' + _.initial(names).join(', ') +
54007                *     (_.size(names) > 1 ? ', & ' : '') + _.last(names);
54008                * });
54009                *
54010                * say('hello', 'fred', 'barney', 'pebbles');
54011                * // => 'hello fred, barney, & pebbles'
54012                */
54013
54014               function rest(func, start) {
54015                 if (typeof func != 'function') {
54016                   throw new TypeError(FUNC_ERROR_TEXT);
54017                 }
54018
54019                 start = start === undefined$1 ? start : toInteger(start);
54020                 return baseRest(func, start);
54021               }
54022               /**
54023                * Creates a function that invokes `func` with the `this` binding of the
54024                * create function and an array of arguments much like
54025                * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply).
54026                *
54027                * **Note:** This method is based on the
54028                * [spread operator](https://mdn.io/spread_operator).
54029                *
54030                * @static
54031                * @memberOf _
54032                * @since 3.2.0
54033                * @category Function
54034                * @param {Function} func The function to spread arguments over.
54035                * @param {number} [start=0] The start position of the spread.
54036                * @returns {Function} Returns the new function.
54037                * @example
54038                *
54039                * var say = _.spread(function(who, what) {
54040                *   return who + ' says ' + what;
54041                * });
54042                *
54043                * say(['fred', 'hello']);
54044                * // => 'fred says hello'
54045                *
54046                * var numbers = Promise.all([
54047                *   Promise.resolve(40),
54048                *   Promise.resolve(36)
54049                * ]);
54050                *
54051                * numbers.then(_.spread(function(x, y) {
54052                *   return x + y;
54053                * }));
54054                * // => a Promise of 76
54055                */
54056
54057
54058               function spread(func, start) {
54059                 if (typeof func != 'function') {
54060                   throw new TypeError(FUNC_ERROR_TEXT);
54061                 }
54062
54063                 start = start == null ? 0 : nativeMax(toInteger(start), 0);
54064                 return baseRest(function (args) {
54065                   var array = args[start],
54066                       otherArgs = castSlice(args, 0, start);
54067
54068                   if (array) {
54069                     arrayPush(otherArgs, array);
54070                   }
54071
54072                   return apply(func, this, otherArgs);
54073                 });
54074               }
54075               /**
54076                * Creates a throttled function that only invokes `func` at most once per
54077                * every `wait` milliseconds. The throttled function comes with a `cancel`
54078                * method to cancel delayed `func` invocations and a `flush` method to
54079                * immediately invoke them. Provide `options` to indicate whether `func`
54080                * should be invoked on the leading and/or trailing edge of the `wait`
54081                * timeout. The `func` is invoked with the last arguments provided to the
54082                * throttled function. Subsequent calls to the throttled function return the
54083                * result of the last `func` invocation.
54084                *
54085                * **Note:** If `leading` and `trailing` options are `true`, `func` is
54086                * invoked on the trailing edge of the timeout only if the throttled function
54087                * is invoked more than once during the `wait` timeout.
54088                *
54089                * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
54090                * until to the next tick, similar to `setTimeout` with a timeout of `0`.
54091                *
54092                * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
54093                * for details over the differences between `_.throttle` and `_.debounce`.
54094                *
54095                * @static
54096                * @memberOf _
54097                * @since 0.1.0
54098                * @category Function
54099                * @param {Function} func The function to throttle.
54100                * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
54101                * @param {Object} [options={}] The options object.
54102                * @param {boolean} [options.leading=true]
54103                *  Specify invoking on the leading edge of the timeout.
54104                * @param {boolean} [options.trailing=true]
54105                *  Specify invoking on the trailing edge of the timeout.
54106                * @returns {Function} Returns the new throttled function.
54107                * @example
54108                *
54109                * // Avoid excessively updating the position while scrolling.
54110                * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
54111                *
54112                * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
54113                * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
54114                * jQuery(element).on('click', throttled);
54115                *
54116                * // Cancel the trailing throttled invocation.
54117                * jQuery(window).on('popstate', throttled.cancel);
54118                */
54119
54120
54121               function throttle(func, wait, options) {
54122                 var leading = true,
54123                     trailing = true;
54124
54125                 if (typeof func != 'function') {
54126                   throw new TypeError(FUNC_ERROR_TEXT);
54127                 }
54128
54129                 if (isObject(options)) {
54130                   leading = 'leading' in options ? !!options.leading : leading;
54131                   trailing = 'trailing' in options ? !!options.trailing : trailing;
54132                 }
54133
54134                 return debounce(func, wait, {
54135                   'leading': leading,
54136                   'maxWait': wait,
54137                   'trailing': trailing
54138                 });
54139               }
54140               /**
54141                * Creates a function that accepts up to one argument, ignoring any
54142                * additional arguments.
54143                *
54144                * @static
54145                * @memberOf _
54146                * @since 4.0.0
54147                * @category Function
54148                * @param {Function} func The function to cap arguments for.
54149                * @returns {Function} Returns the new capped function.
54150                * @example
54151                *
54152                * _.map(['6', '8', '10'], _.unary(parseInt));
54153                * // => [6, 8, 10]
54154                */
54155
54156
54157               function unary(func) {
54158                 return ary(func, 1);
54159               }
54160               /**
54161                * Creates a function that provides `value` to `wrapper` as its first
54162                * argument. Any additional arguments provided to the function are appended
54163                * to those provided to the `wrapper`. The wrapper is invoked with the `this`
54164                * binding of the created function.
54165                *
54166                * @static
54167                * @memberOf _
54168                * @since 0.1.0
54169                * @category Function
54170                * @param {*} value The value to wrap.
54171                * @param {Function} [wrapper=identity] The wrapper function.
54172                * @returns {Function} Returns the new function.
54173                * @example
54174                *
54175                * var p = _.wrap(_.escape, function(func, text) {
54176                *   return '<p>' + func(text) + '</p>';
54177                * });
54178                *
54179                * p('fred, barney, & pebbles');
54180                * // => '<p>fred, barney, &amp; pebbles</p>'
54181                */
54182
54183
54184               function wrap(value, wrapper) {
54185                 return partial(castFunction(wrapper), value);
54186               }
54187               /*------------------------------------------------------------------------*/
54188
54189               /**
54190                * Casts `value` as an array if it's not one.
54191                *
54192                * @static
54193                * @memberOf _
54194                * @since 4.4.0
54195                * @category Lang
54196                * @param {*} value The value to inspect.
54197                * @returns {Array} Returns the cast array.
54198                * @example
54199                *
54200                * _.castArray(1);
54201                * // => [1]
54202                *
54203                * _.castArray({ 'a': 1 });
54204                * // => [{ 'a': 1 }]
54205                *
54206                * _.castArray('abc');
54207                * // => ['abc']
54208                *
54209                * _.castArray(null);
54210                * // => [null]
54211                *
54212                * _.castArray(undefined);
54213                * // => [undefined]
54214                *
54215                * _.castArray();
54216                * // => []
54217                *
54218                * var array = [1, 2, 3];
54219                * console.log(_.castArray(array) === array);
54220                * // => true
54221                */
54222
54223
54224               function castArray() {
54225                 if (!arguments.length) {
54226                   return [];
54227                 }
54228
54229                 var value = arguments[0];
54230                 return isArray(value) ? value : [value];
54231               }
54232               /**
54233                * Creates a shallow clone of `value`.
54234                *
54235                * **Note:** This method is loosely based on the
54236                * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
54237                * and supports cloning arrays, array buffers, booleans, date objects, maps,
54238                * numbers, `Object` objects, regexes, sets, strings, symbols, and typed
54239                * arrays. The own enumerable properties of `arguments` objects are cloned
54240                * as plain objects. An empty object is returned for uncloneable values such
54241                * as error objects, functions, DOM nodes, and WeakMaps.
54242                *
54243                * @static
54244                * @memberOf _
54245                * @since 0.1.0
54246                * @category Lang
54247                * @param {*} value The value to clone.
54248                * @returns {*} Returns the cloned value.
54249                * @see _.cloneDeep
54250                * @example
54251                *
54252                * var objects = [{ 'a': 1 }, { 'b': 2 }];
54253                *
54254                * var shallow = _.clone(objects);
54255                * console.log(shallow[0] === objects[0]);
54256                * // => true
54257                */
54258
54259
54260               function clone(value) {
54261                 return baseClone(value, CLONE_SYMBOLS_FLAG);
54262               }
54263               /**
54264                * This method is like `_.clone` except that it accepts `customizer` which
54265                * is invoked to produce the cloned value. If `customizer` returns `undefined`,
54266                * cloning is handled by the method instead. The `customizer` is invoked with
54267                * up to four arguments; (value [, index|key, object, stack]).
54268                *
54269                * @static
54270                * @memberOf _
54271                * @since 4.0.0
54272                * @category Lang
54273                * @param {*} value The value to clone.
54274                * @param {Function} [customizer] The function to customize cloning.
54275                * @returns {*} Returns the cloned value.
54276                * @see _.cloneDeepWith
54277                * @example
54278                *
54279                * function customizer(value) {
54280                *   if (_.isElement(value)) {
54281                *     return value.cloneNode(false);
54282                *   }
54283                * }
54284                *
54285                * var el = _.cloneWith(document.body, customizer);
54286                *
54287                * console.log(el === document.body);
54288                * // => false
54289                * console.log(el.nodeName);
54290                * // => 'BODY'
54291                * console.log(el.childNodes.length);
54292                * // => 0
54293                */
54294
54295
54296               function cloneWith(value, customizer) {
54297                 customizer = typeof customizer == 'function' ? customizer : undefined$1;
54298                 return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);
54299               }
54300               /**
54301                * This method is like `_.clone` except that it recursively clones `value`.
54302                *
54303                * @static
54304                * @memberOf _
54305                * @since 1.0.0
54306                * @category Lang
54307                * @param {*} value The value to recursively clone.
54308                * @returns {*} Returns the deep cloned value.
54309                * @see _.clone
54310                * @example
54311                *
54312                * var objects = [{ 'a': 1 }, { 'b': 2 }];
54313                *
54314                * var deep = _.cloneDeep(objects);
54315                * console.log(deep[0] === objects[0]);
54316                * // => false
54317                */
54318
54319
54320               function cloneDeep(value) {
54321                 return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
54322               }
54323               /**
54324                * This method is like `_.cloneWith` except that it recursively clones `value`.
54325                *
54326                * @static
54327                * @memberOf _
54328                * @since 4.0.0
54329                * @category Lang
54330                * @param {*} value The value to recursively clone.
54331                * @param {Function} [customizer] The function to customize cloning.
54332                * @returns {*} Returns the deep cloned value.
54333                * @see _.cloneWith
54334                * @example
54335                *
54336                * function customizer(value) {
54337                *   if (_.isElement(value)) {
54338                *     return value.cloneNode(true);
54339                *   }
54340                * }
54341                *
54342                * var el = _.cloneDeepWith(document.body, customizer);
54343                *
54344                * console.log(el === document.body);
54345                * // => false
54346                * console.log(el.nodeName);
54347                * // => 'BODY'
54348                * console.log(el.childNodes.length);
54349                * // => 20
54350                */
54351
54352
54353               function cloneDeepWith(value, customizer) {
54354                 customizer = typeof customizer == 'function' ? customizer : undefined$1;
54355                 return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);
54356               }
54357               /**
54358                * Checks if `object` conforms to `source` by invoking the predicate
54359                * properties of `source` with the corresponding property values of `object`.
54360                *
54361                * **Note:** This method is equivalent to `_.conforms` when `source` is
54362                * partially applied.
54363                *
54364                * @static
54365                * @memberOf _
54366                * @since 4.14.0
54367                * @category Lang
54368                * @param {Object} object The object to inspect.
54369                * @param {Object} source The object of property predicates to conform to.
54370                * @returns {boolean} Returns `true` if `object` conforms, else `false`.
54371                * @example
54372                *
54373                * var object = { 'a': 1, 'b': 2 };
54374                *
54375                * _.conformsTo(object, { 'b': function(n) { return n > 1; } });
54376                * // => true
54377                *
54378                * _.conformsTo(object, { 'b': function(n) { return n > 2; } });
54379                * // => false
54380                */
54381
54382
54383               function conformsTo(object, source) {
54384                 return source == null || baseConformsTo(object, source, keys(source));
54385               }
54386               /**
54387                * Performs a
54388                * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
54389                * comparison between two values to determine if they are equivalent.
54390                *
54391                * @static
54392                * @memberOf _
54393                * @since 4.0.0
54394                * @category Lang
54395                * @param {*} value The value to compare.
54396                * @param {*} other The other value to compare.
54397                * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
54398                * @example
54399                *
54400                * var object = { 'a': 1 };
54401                * var other = { 'a': 1 };
54402                *
54403                * _.eq(object, object);
54404                * // => true
54405                *
54406                * _.eq(object, other);
54407                * // => false
54408                *
54409                * _.eq('a', 'a');
54410                * // => true
54411                *
54412                * _.eq('a', Object('a'));
54413                * // => false
54414                *
54415                * _.eq(NaN, NaN);
54416                * // => true
54417                */
54418
54419
54420               function eq(value, other) {
54421                 return value === other || value !== value && other !== other;
54422               }
54423               /**
54424                * Checks if `value` is greater than `other`.
54425                *
54426                * @static
54427                * @memberOf _
54428                * @since 3.9.0
54429                * @category Lang
54430                * @param {*} value The value to compare.
54431                * @param {*} other The other value to compare.
54432                * @returns {boolean} Returns `true` if `value` is greater than `other`,
54433                *  else `false`.
54434                * @see _.lt
54435                * @example
54436                *
54437                * _.gt(3, 1);
54438                * // => true
54439                *
54440                * _.gt(3, 3);
54441                * // => false
54442                *
54443                * _.gt(1, 3);
54444                * // => false
54445                */
54446
54447
54448               var gt = createRelationalOperation(baseGt);
54449               /**
54450                * Checks if `value` is greater than or equal to `other`.
54451                *
54452                * @static
54453                * @memberOf _
54454                * @since 3.9.0
54455                * @category Lang
54456                * @param {*} value The value to compare.
54457                * @param {*} other The other value to compare.
54458                * @returns {boolean} Returns `true` if `value` is greater than or equal to
54459                *  `other`, else `false`.
54460                * @see _.lte
54461                * @example
54462                *
54463                * _.gte(3, 1);
54464                * // => true
54465                *
54466                * _.gte(3, 3);
54467                * // => true
54468                *
54469                * _.gte(1, 3);
54470                * // => false
54471                */
54472
54473               var gte = createRelationalOperation(function (value, other) {
54474                 return value >= other;
54475               });
54476               /**
54477                * Checks if `value` is likely an `arguments` object.
54478                *
54479                * @static
54480                * @memberOf _
54481                * @since 0.1.0
54482                * @category Lang
54483                * @param {*} value The value to check.
54484                * @returns {boolean} Returns `true` if `value` is an `arguments` object,
54485                *  else `false`.
54486                * @example
54487                *
54488                * _.isArguments(function() { return arguments; }());
54489                * // => true
54490                *
54491                * _.isArguments([1, 2, 3]);
54492                * // => false
54493                */
54494
54495               var isArguments = baseIsArguments(function () {
54496                 return arguments;
54497               }()) ? baseIsArguments : function (value) {
54498                 return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee');
54499               };
54500               /**
54501                * Checks if `value` is classified as an `Array` object.
54502                *
54503                * @static
54504                * @memberOf _
54505                * @since 0.1.0
54506                * @category Lang
54507                * @param {*} value The value to check.
54508                * @returns {boolean} Returns `true` if `value` is an array, else `false`.
54509                * @example
54510                *
54511                * _.isArray([1, 2, 3]);
54512                * // => true
54513                *
54514                * _.isArray(document.body.children);
54515                * // => false
54516                *
54517                * _.isArray('abc');
54518                * // => false
54519                *
54520                * _.isArray(_.noop);
54521                * // => false
54522                */
54523
54524               var isArray = Array.isArray;
54525               /**
54526                * Checks if `value` is classified as an `ArrayBuffer` object.
54527                *
54528                * @static
54529                * @memberOf _
54530                * @since 4.3.0
54531                * @category Lang
54532                * @param {*} value The value to check.
54533                * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
54534                * @example
54535                *
54536                * _.isArrayBuffer(new ArrayBuffer(2));
54537                * // => true
54538                *
54539                * _.isArrayBuffer(new Array(2));
54540                * // => false
54541                */
54542
54543               var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;
54544               /**
54545                * Checks if `value` is array-like. A value is considered array-like if it's
54546                * not a function and has a `value.length` that's an integer greater than or
54547                * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
54548                *
54549                * @static
54550                * @memberOf _
54551                * @since 4.0.0
54552                * @category Lang
54553                * @param {*} value The value to check.
54554                * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
54555                * @example
54556                *
54557                * _.isArrayLike([1, 2, 3]);
54558                * // => true
54559                *
54560                * _.isArrayLike(document.body.children);
54561                * // => true
54562                *
54563                * _.isArrayLike('abc');
54564                * // => true
54565                *
54566                * _.isArrayLike(_.noop);
54567                * // => false
54568                */
54569
54570               function isArrayLike(value) {
54571                 return value != null && isLength(value.length) && !isFunction(value);
54572               }
54573               /**
54574                * This method is like `_.isArrayLike` except that it also checks if `value`
54575                * is an object.
54576                *
54577                * @static
54578                * @memberOf _
54579                * @since 4.0.0
54580                * @category Lang
54581                * @param {*} value The value to check.
54582                * @returns {boolean} Returns `true` if `value` is an array-like object,
54583                *  else `false`.
54584                * @example
54585                *
54586                * _.isArrayLikeObject([1, 2, 3]);
54587                * // => true
54588                *
54589                * _.isArrayLikeObject(document.body.children);
54590                * // => true
54591                *
54592                * _.isArrayLikeObject('abc');
54593                * // => false
54594                *
54595                * _.isArrayLikeObject(_.noop);
54596                * // => false
54597                */
54598
54599
54600               function isArrayLikeObject(value) {
54601                 return isObjectLike(value) && isArrayLike(value);
54602               }
54603               /**
54604                * Checks if `value` is classified as a boolean primitive or object.
54605                *
54606                * @static
54607                * @memberOf _
54608                * @since 0.1.0
54609                * @category Lang
54610                * @param {*} value The value to check.
54611                * @returns {boolean} Returns `true` if `value` is a boolean, else `false`.
54612                * @example
54613                *
54614                * _.isBoolean(false);
54615                * // => true
54616                *
54617                * _.isBoolean(null);
54618                * // => false
54619                */
54620
54621
54622               function isBoolean(value) {
54623                 return value === true || value === false || isObjectLike(value) && baseGetTag(value) == boolTag;
54624               }
54625               /**
54626                * Checks if `value` is a buffer.
54627                *
54628                * @static
54629                * @memberOf _
54630                * @since 4.3.0
54631                * @category Lang
54632                * @param {*} value The value to check.
54633                * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
54634                * @example
54635                *
54636                * _.isBuffer(new Buffer(2));
54637                * // => true
54638                *
54639                * _.isBuffer(new Uint8Array(2));
54640                * // => false
54641                */
54642
54643
54644               var isBuffer = nativeIsBuffer || stubFalse;
54645               /**
54646                * Checks if `value` is classified as a `Date` object.
54647                *
54648                * @static
54649                * @memberOf _
54650                * @since 0.1.0
54651                * @category Lang
54652                * @param {*} value The value to check.
54653                * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
54654                * @example
54655                *
54656                * _.isDate(new Date);
54657                * // => true
54658                *
54659                * _.isDate('Mon April 23 2012');
54660                * // => false
54661                */
54662
54663               var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
54664               /**
54665                * Checks if `value` is likely a DOM element.
54666                *
54667                * @static
54668                * @memberOf _
54669                * @since 0.1.0
54670                * @category Lang
54671                * @param {*} value The value to check.
54672                * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
54673                * @example
54674                *
54675                * _.isElement(document.body);
54676                * // => true
54677                *
54678                * _.isElement('<body>');
54679                * // => false
54680                */
54681
54682               function isElement(value) {
54683                 return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);
54684               }
54685               /**
54686                * Checks if `value` is an empty object, collection, map, or set.
54687                *
54688                * Objects are considered empty if they have no own enumerable string keyed
54689                * properties.
54690                *
54691                * Array-like values such as `arguments` objects, arrays, buffers, strings, or
54692                * jQuery-like collections are considered empty if they have a `length` of `0`.
54693                * Similarly, maps and sets are considered empty if they have a `size` of `0`.
54694                *
54695                * @static
54696                * @memberOf _
54697                * @since 0.1.0
54698                * @category Lang
54699                * @param {*} value The value to check.
54700                * @returns {boolean} Returns `true` if `value` is empty, else `false`.
54701                * @example
54702                *
54703                * _.isEmpty(null);
54704                * // => true
54705                *
54706                * _.isEmpty(true);
54707                * // => true
54708                *
54709                * _.isEmpty(1);
54710                * // => true
54711                *
54712                * _.isEmpty([1, 2, 3]);
54713                * // => false
54714                *
54715                * _.isEmpty({ 'a': 1 });
54716                * // => false
54717                */
54718
54719
54720               function isEmpty(value) {
54721                 if (value == null) {
54722                   return true;
54723                 }
54724
54725                 if (isArrayLike(value) && (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' || isBuffer(value) || isTypedArray(value) || isArguments(value))) {
54726                   return !value.length;
54727                 }
54728
54729                 var tag = getTag(value);
54730
54731                 if (tag == mapTag || tag == setTag) {
54732                   return !value.size;
54733                 }
54734
54735                 if (isPrototype(value)) {
54736                   return !baseKeys(value).length;
54737                 }
54738
54739                 for (var key in value) {
54740                   if (hasOwnProperty.call(value, key)) {
54741                     return false;
54742                   }
54743                 }
54744
54745                 return true;
54746               }
54747               /**
54748                * Performs a deep comparison between two values to determine if they are
54749                * equivalent.
54750                *
54751                * **Note:** This method supports comparing arrays, array buffers, booleans,
54752                * date objects, error objects, maps, numbers, `Object` objects, regexes,
54753                * sets, strings, symbols, and typed arrays. `Object` objects are compared
54754                * by their own, not inherited, enumerable properties. Functions and DOM
54755                * nodes are compared by strict equality, i.e. `===`.
54756                *
54757                * @static
54758                * @memberOf _
54759                * @since 0.1.0
54760                * @category Lang
54761                * @param {*} value The value to compare.
54762                * @param {*} other The other value to compare.
54763                * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
54764                * @example
54765                *
54766                * var object = { 'a': 1 };
54767                * var other = { 'a': 1 };
54768                *
54769                * _.isEqual(object, other);
54770                * // => true
54771                *
54772                * object === other;
54773                * // => false
54774                */
54775
54776
54777               function isEqual(value, other) {
54778                 return baseIsEqual(value, other);
54779               }
54780               /**
54781                * This method is like `_.isEqual` except that it accepts `customizer` which
54782                * is invoked to compare values. If `customizer` returns `undefined`, comparisons
54783                * are handled by the method instead. The `customizer` is invoked with up to
54784                * six arguments: (objValue, othValue [, index|key, object, other, stack]).
54785                *
54786                * @static
54787                * @memberOf _
54788                * @since 4.0.0
54789                * @category Lang
54790                * @param {*} value The value to compare.
54791                * @param {*} other The other value to compare.
54792                * @param {Function} [customizer] The function to customize comparisons.
54793                * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
54794                * @example
54795                *
54796                * function isGreeting(value) {
54797                *   return /^h(?:i|ello)$/.test(value);
54798                * }
54799                *
54800                * function customizer(objValue, othValue) {
54801                *   if (isGreeting(objValue) && isGreeting(othValue)) {
54802                *     return true;
54803                *   }
54804                * }
54805                *
54806                * var array = ['hello', 'goodbye'];
54807                * var other = ['hi', 'goodbye'];
54808                *
54809                * _.isEqualWith(array, other, customizer);
54810                * // => true
54811                */
54812
54813
54814               function isEqualWith(value, other, customizer) {
54815                 customizer = typeof customizer == 'function' ? customizer : undefined$1;
54816                 var result = customizer ? customizer(value, other) : undefined$1;
54817                 return result === undefined$1 ? baseIsEqual(value, other, undefined$1, customizer) : !!result;
54818               }
54819               /**
54820                * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
54821                * `SyntaxError`, `TypeError`, or `URIError` object.
54822                *
54823                * @static
54824                * @memberOf _
54825                * @since 3.0.0
54826                * @category Lang
54827                * @param {*} value The value to check.
54828                * @returns {boolean} Returns `true` if `value` is an error object, else `false`.
54829                * @example
54830                *
54831                * _.isError(new Error);
54832                * // => true
54833                *
54834                * _.isError(Error);
54835                * // => false
54836                */
54837
54838
54839               function isError(value) {
54840                 if (!isObjectLike(value)) {
54841                   return false;
54842                 }
54843
54844                 var tag = baseGetTag(value);
54845                 return tag == errorTag || tag == domExcTag || typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value);
54846               }
54847               /**
54848                * Checks if `value` is a finite primitive number.
54849                *
54850                * **Note:** This method is based on
54851                * [`Number.isFinite`](https://mdn.io/Number/isFinite).
54852                *
54853                * @static
54854                * @memberOf _
54855                * @since 0.1.0
54856                * @category Lang
54857                * @param {*} value The value to check.
54858                * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
54859                * @example
54860                *
54861                * _.isFinite(3);
54862                * // => true
54863                *
54864                * _.isFinite(Number.MIN_VALUE);
54865                * // => true
54866                *
54867                * _.isFinite(Infinity);
54868                * // => false
54869                *
54870                * _.isFinite('3');
54871                * // => false
54872                */
54873
54874
54875               function isFinite(value) {
54876                 return typeof value == 'number' && nativeIsFinite(value);
54877               }
54878               /**
54879                * Checks if `value` is classified as a `Function` object.
54880                *
54881                * @static
54882                * @memberOf _
54883                * @since 0.1.0
54884                * @category Lang
54885                * @param {*} value The value to check.
54886                * @returns {boolean} Returns `true` if `value` is a function, else `false`.
54887                * @example
54888                *
54889                * _.isFunction(_);
54890                * // => true
54891                *
54892                * _.isFunction(/abc/);
54893                * // => false
54894                */
54895
54896
54897               function isFunction(value) {
54898                 if (!isObject(value)) {
54899                   return false;
54900                 } // The use of `Object#toString` avoids issues with the `typeof` operator
54901                 // in Safari 9 which returns 'object' for typed arrays and other constructors.
54902
54903
54904                 var tag = baseGetTag(value);
54905                 return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
54906               }
54907               /**
54908                * Checks if `value` is an integer.
54909                *
54910                * **Note:** This method is based on
54911                * [`Number.isInteger`](https://mdn.io/Number/isInteger).
54912                *
54913                * @static
54914                * @memberOf _
54915                * @since 4.0.0
54916                * @category Lang
54917                * @param {*} value The value to check.
54918                * @returns {boolean} Returns `true` if `value` is an integer, else `false`.
54919                * @example
54920                *
54921                * _.isInteger(3);
54922                * // => true
54923                *
54924                * _.isInteger(Number.MIN_VALUE);
54925                * // => false
54926                *
54927                * _.isInteger(Infinity);
54928                * // => false
54929                *
54930                * _.isInteger('3');
54931                * // => false
54932                */
54933
54934
54935               function isInteger(value) {
54936                 return typeof value == 'number' && value == toInteger(value);
54937               }
54938               /**
54939                * Checks if `value` is a valid array-like length.
54940                *
54941                * **Note:** This method is loosely based on
54942                * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
54943                *
54944                * @static
54945                * @memberOf _
54946                * @since 4.0.0
54947                * @category Lang
54948                * @param {*} value The value to check.
54949                * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
54950                * @example
54951                *
54952                * _.isLength(3);
54953                * // => true
54954                *
54955                * _.isLength(Number.MIN_VALUE);
54956                * // => false
54957                *
54958                * _.isLength(Infinity);
54959                * // => false
54960                *
54961                * _.isLength('3');
54962                * // => false
54963                */
54964
54965
54966               function isLength(value) {
54967                 return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
54968               }
54969               /**
54970                * Checks if `value` is the
54971                * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
54972                * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
54973                *
54974                * @static
54975                * @memberOf _
54976                * @since 0.1.0
54977                * @category Lang
54978                * @param {*} value The value to check.
54979                * @returns {boolean} Returns `true` if `value` is an object, else `false`.
54980                * @example
54981                *
54982                * _.isObject({});
54983                * // => true
54984                *
54985                * _.isObject([1, 2, 3]);
54986                * // => true
54987                *
54988                * _.isObject(_.noop);
54989                * // => true
54990                *
54991                * _.isObject(null);
54992                * // => false
54993                */
54994
54995
54996               function isObject(value) {
54997                 var type = _typeof(value);
54998
54999                 return value != null && (type == 'object' || type == 'function');
55000               }
55001               /**
55002                * Checks if `value` is object-like. A value is object-like if it's not `null`
55003                * and has a `typeof` result of "object".
55004                *
55005                * @static
55006                * @memberOf _
55007                * @since 4.0.0
55008                * @category Lang
55009                * @param {*} value The value to check.
55010                * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
55011                * @example
55012                *
55013                * _.isObjectLike({});
55014                * // => true
55015                *
55016                * _.isObjectLike([1, 2, 3]);
55017                * // => true
55018                *
55019                * _.isObjectLike(_.noop);
55020                * // => false
55021                *
55022                * _.isObjectLike(null);
55023                * // => false
55024                */
55025
55026
55027               function isObjectLike(value) {
55028                 return value != null && _typeof(value) == 'object';
55029               }
55030               /**
55031                * Checks if `value` is classified as a `Map` object.
55032                *
55033                * @static
55034                * @memberOf _
55035                * @since 4.3.0
55036                * @category Lang
55037                * @param {*} value The value to check.
55038                * @returns {boolean} Returns `true` if `value` is a map, else `false`.
55039                * @example
55040                *
55041                * _.isMap(new Map);
55042                * // => true
55043                *
55044                * _.isMap(new WeakMap);
55045                * // => false
55046                */
55047
55048
55049               var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;
55050               /**
55051                * Performs a partial deep comparison between `object` and `source` to
55052                * determine if `object` contains equivalent property values.
55053                *
55054                * **Note:** This method is equivalent to `_.matches` when `source` is
55055                * partially applied.
55056                *
55057                * Partial comparisons will match empty array and empty object `source`
55058                * values against any array or object value, respectively. See `_.isEqual`
55059                * for a list of supported value comparisons.
55060                *
55061                * @static
55062                * @memberOf _
55063                * @since 3.0.0
55064                * @category Lang
55065                * @param {Object} object The object to inspect.
55066                * @param {Object} source The object of property values to match.
55067                * @returns {boolean} Returns `true` if `object` is a match, else `false`.
55068                * @example
55069                *
55070                * var object = { 'a': 1, 'b': 2 };
55071                *
55072                * _.isMatch(object, { 'b': 2 });
55073                * // => true
55074                *
55075                * _.isMatch(object, { 'b': 1 });
55076                * // => false
55077                */
55078
55079               function isMatch(object, source) {
55080                 return object === source || baseIsMatch(object, source, getMatchData(source));
55081               }
55082               /**
55083                * This method is like `_.isMatch` except that it accepts `customizer` which
55084                * is invoked to compare values. If `customizer` returns `undefined`, comparisons
55085                * are handled by the method instead. The `customizer` is invoked with five
55086                * arguments: (objValue, srcValue, index|key, object, source).
55087                *
55088                * @static
55089                * @memberOf _
55090                * @since 4.0.0
55091                * @category Lang
55092                * @param {Object} object The object to inspect.
55093                * @param {Object} source The object of property values to match.
55094                * @param {Function} [customizer] The function to customize comparisons.
55095                * @returns {boolean} Returns `true` if `object` is a match, else `false`.
55096                * @example
55097                *
55098                * function isGreeting(value) {
55099                *   return /^h(?:i|ello)$/.test(value);
55100                * }
55101                *
55102                * function customizer(objValue, srcValue) {
55103                *   if (isGreeting(objValue) && isGreeting(srcValue)) {
55104                *     return true;
55105                *   }
55106                * }
55107                *
55108                * var object = { 'greeting': 'hello' };
55109                * var source = { 'greeting': 'hi' };
55110                *
55111                * _.isMatchWith(object, source, customizer);
55112                * // => true
55113                */
55114
55115
55116               function isMatchWith(object, source, customizer) {
55117                 customizer = typeof customizer == 'function' ? customizer : undefined$1;
55118                 return baseIsMatch(object, source, getMatchData(source), customizer);
55119               }
55120               /**
55121                * Checks if `value` is `NaN`.
55122                *
55123                * **Note:** This method is based on
55124                * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as
55125                * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for
55126                * `undefined` and other non-number values.
55127                *
55128                * @static
55129                * @memberOf _
55130                * @since 0.1.0
55131                * @category Lang
55132                * @param {*} value The value to check.
55133                * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
55134                * @example
55135                *
55136                * _.isNaN(NaN);
55137                * // => true
55138                *
55139                * _.isNaN(new Number(NaN));
55140                * // => true
55141                *
55142                * isNaN(undefined);
55143                * // => true
55144                *
55145                * _.isNaN(undefined);
55146                * // => false
55147                */
55148
55149
55150               function isNaN(value) {
55151                 // An `NaN` primitive is the only value that is not equal to itself.
55152                 // Perform the `toStringTag` check first to avoid errors with some
55153                 // ActiveX objects in IE.
55154                 return isNumber(value) && value != +value;
55155               }
55156               /**
55157                * Checks if `value` is a pristine native function.
55158                *
55159                * **Note:** This method can't reliably detect native functions in the presence
55160                * of the core-js package because core-js circumvents this kind of detection.
55161                * Despite multiple requests, the core-js maintainer has made it clear: any
55162                * attempt to fix the detection will be obstructed. As a result, we're left
55163                * with little choice but to throw an error. Unfortunately, this also affects
55164                * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill),
55165                * which rely on core-js.
55166                *
55167                * @static
55168                * @memberOf _
55169                * @since 3.0.0
55170                * @category Lang
55171                * @param {*} value The value to check.
55172                * @returns {boolean} Returns `true` if `value` is a native function,
55173                *  else `false`.
55174                * @example
55175                *
55176                * _.isNative(Array.prototype.push);
55177                * // => true
55178                *
55179                * _.isNative(_);
55180                * // => false
55181                */
55182
55183
55184               function isNative(value) {
55185                 if (isMaskable(value)) {
55186                   throw new Error(CORE_ERROR_TEXT);
55187                 }
55188
55189                 return baseIsNative(value);
55190               }
55191               /**
55192                * Checks if `value` is `null`.
55193                *
55194                * @static
55195                * @memberOf _
55196                * @since 0.1.0
55197                * @category Lang
55198                * @param {*} value The value to check.
55199                * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
55200                * @example
55201                *
55202                * _.isNull(null);
55203                * // => true
55204                *
55205                * _.isNull(void 0);
55206                * // => false
55207                */
55208
55209
55210               function isNull(value) {
55211                 return value === null;
55212               }
55213               /**
55214                * Checks if `value` is `null` or `undefined`.
55215                *
55216                * @static
55217                * @memberOf _
55218                * @since 4.0.0
55219                * @category Lang
55220                * @param {*} value The value to check.
55221                * @returns {boolean} Returns `true` if `value` is nullish, else `false`.
55222                * @example
55223                *
55224                * _.isNil(null);
55225                * // => true
55226                *
55227                * _.isNil(void 0);
55228                * // => true
55229                *
55230                * _.isNil(NaN);
55231                * // => false
55232                */
55233
55234
55235               function isNil(value) {
55236                 return value == null;
55237               }
55238               /**
55239                * Checks if `value` is classified as a `Number` primitive or object.
55240                *
55241                * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are
55242                * classified as numbers, use the `_.isFinite` method.
55243                *
55244                * @static
55245                * @memberOf _
55246                * @since 0.1.0
55247                * @category Lang
55248                * @param {*} value The value to check.
55249                * @returns {boolean} Returns `true` if `value` is a number, else `false`.
55250                * @example
55251                *
55252                * _.isNumber(3);
55253                * // => true
55254                *
55255                * _.isNumber(Number.MIN_VALUE);
55256                * // => true
55257                *
55258                * _.isNumber(Infinity);
55259                * // => true
55260                *
55261                * _.isNumber('3');
55262                * // => false
55263                */
55264
55265
55266               function isNumber(value) {
55267                 return typeof value == 'number' || isObjectLike(value) && baseGetTag(value) == numberTag;
55268               }
55269               /**
55270                * Checks if `value` is a plain object, that is, an object created by the
55271                * `Object` constructor or one with a `[[Prototype]]` of `null`.
55272                *
55273                * @static
55274                * @memberOf _
55275                * @since 0.8.0
55276                * @category Lang
55277                * @param {*} value The value to check.
55278                * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
55279                * @example
55280                *
55281                * function Foo() {
55282                *   this.a = 1;
55283                * }
55284                *
55285                * _.isPlainObject(new Foo);
55286                * // => false
55287                *
55288                * _.isPlainObject([1, 2, 3]);
55289                * // => false
55290                *
55291                * _.isPlainObject({ 'x': 0, 'y': 0 });
55292                * // => true
55293                *
55294                * _.isPlainObject(Object.create(null));
55295                * // => true
55296                */
55297
55298
55299               function isPlainObject(value) {
55300                 if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
55301                   return false;
55302                 }
55303
55304                 var proto = getPrototype(value);
55305
55306                 if (proto === null) {
55307                   return true;
55308                 }
55309
55310                 var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
55311                 return typeof Ctor == 'function' && Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString;
55312               }
55313               /**
55314                * Checks if `value` is classified as a `RegExp` object.
55315                *
55316                * @static
55317                * @memberOf _
55318                * @since 0.1.0
55319                * @category Lang
55320                * @param {*} value The value to check.
55321                * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
55322                * @example
55323                *
55324                * _.isRegExp(/abc/);
55325                * // => true
55326                *
55327                * _.isRegExp('/abc/');
55328                * // => false
55329                */
55330
55331
55332               var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;
55333               /**
55334                * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754
55335                * double precision number which isn't the result of a rounded unsafe integer.
55336                *
55337                * **Note:** This method is based on
55338                * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).
55339                *
55340                * @static
55341                * @memberOf _
55342                * @since 4.0.0
55343                * @category Lang
55344                * @param {*} value The value to check.
55345                * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`.
55346                * @example
55347                *
55348                * _.isSafeInteger(3);
55349                * // => true
55350                *
55351                * _.isSafeInteger(Number.MIN_VALUE);
55352                * // => false
55353                *
55354                * _.isSafeInteger(Infinity);
55355                * // => false
55356                *
55357                * _.isSafeInteger('3');
55358                * // => false
55359                */
55360
55361               function isSafeInteger(value) {
55362                 return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
55363               }
55364               /**
55365                * Checks if `value` is classified as a `Set` object.
55366                *
55367                * @static
55368                * @memberOf _
55369                * @since 4.3.0
55370                * @category Lang
55371                * @param {*} value The value to check.
55372                * @returns {boolean} Returns `true` if `value` is a set, else `false`.
55373                * @example
55374                *
55375                * _.isSet(new Set);
55376                * // => true
55377                *
55378                * _.isSet(new WeakSet);
55379                * // => false
55380                */
55381
55382
55383               var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
55384               /**
55385                * Checks if `value` is classified as a `String` primitive or object.
55386                *
55387                * @static
55388                * @since 0.1.0
55389                * @memberOf _
55390                * @category Lang
55391                * @param {*} value The value to check.
55392                * @returns {boolean} Returns `true` if `value` is a string, else `false`.
55393                * @example
55394                *
55395                * _.isString('abc');
55396                * // => true
55397                *
55398                * _.isString(1);
55399                * // => false
55400                */
55401
55402               function isString(value) {
55403                 return typeof value == 'string' || !isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag;
55404               }
55405               /**
55406                * Checks if `value` is classified as a `Symbol` primitive or object.
55407                *
55408                * @static
55409                * @memberOf _
55410                * @since 4.0.0
55411                * @category Lang
55412                * @param {*} value The value to check.
55413                * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
55414                * @example
55415                *
55416                * _.isSymbol(Symbol.iterator);
55417                * // => true
55418                *
55419                * _.isSymbol('abc');
55420                * // => false
55421                */
55422
55423
55424               function isSymbol(value) {
55425                 return _typeof(value) == 'symbol' || isObjectLike(value) && baseGetTag(value) == symbolTag;
55426               }
55427               /**
55428                * Checks if `value` is classified as a typed array.
55429                *
55430                * @static
55431                * @memberOf _
55432                * @since 3.0.0
55433                * @category Lang
55434                * @param {*} value The value to check.
55435                * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
55436                * @example
55437                *
55438                * _.isTypedArray(new Uint8Array);
55439                * // => true
55440                *
55441                * _.isTypedArray([]);
55442                * // => false
55443                */
55444
55445
55446               var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
55447               /**
55448                * Checks if `value` is `undefined`.
55449                *
55450                * @static
55451                * @since 0.1.0
55452                * @memberOf _
55453                * @category Lang
55454                * @param {*} value The value to check.
55455                * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
55456                * @example
55457                *
55458                * _.isUndefined(void 0);
55459                * // => true
55460                *
55461                * _.isUndefined(null);
55462                * // => false
55463                */
55464
55465               function isUndefined(value) {
55466                 return value === undefined$1;
55467               }
55468               /**
55469                * Checks if `value` is classified as a `WeakMap` object.
55470                *
55471                * @static
55472                * @memberOf _
55473                * @since 4.3.0
55474                * @category Lang
55475                * @param {*} value The value to check.
55476                * @returns {boolean} Returns `true` if `value` is a weak map, else `false`.
55477                * @example
55478                *
55479                * _.isWeakMap(new WeakMap);
55480                * // => true
55481                *
55482                * _.isWeakMap(new Map);
55483                * // => false
55484                */
55485
55486
55487               function isWeakMap(value) {
55488                 return isObjectLike(value) && getTag(value) == weakMapTag;
55489               }
55490               /**
55491                * Checks if `value` is classified as a `WeakSet` object.
55492                *
55493                * @static
55494                * @memberOf _
55495                * @since 4.3.0
55496                * @category Lang
55497                * @param {*} value The value to check.
55498                * @returns {boolean} Returns `true` if `value` is a weak set, else `false`.
55499                * @example
55500                *
55501                * _.isWeakSet(new WeakSet);
55502                * // => true
55503                *
55504                * _.isWeakSet(new Set);
55505                * // => false
55506                */
55507
55508
55509               function isWeakSet(value) {
55510                 return isObjectLike(value) && baseGetTag(value) == weakSetTag;
55511               }
55512               /**
55513                * Checks if `value` is less than `other`.
55514                *
55515                * @static
55516                * @memberOf _
55517                * @since 3.9.0
55518                * @category Lang
55519                * @param {*} value The value to compare.
55520                * @param {*} other The other value to compare.
55521                * @returns {boolean} Returns `true` if `value` is less than `other`,
55522                *  else `false`.
55523                * @see _.gt
55524                * @example
55525                *
55526                * _.lt(1, 3);
55527                * // => true
55528                *
55529                * _.lt(3, 3);
55530                * // => false
55531                *
55532                * _.lt(3, 1);
55533                * // => false
55534                */
55535
55536
55537               var lt = createRelationalOperation(baseLt);
55538               /**
55539                * Checks if `value` is less than or equal to `other`.
55540                *
55541                * @static
55542                * @memberOf _
55543                * @since 3.9.0
55544                * @category Lang
55545                * @param {*} value The value to compare.
55546                * @param {*} other The other value to compare.
55547                * @returns {boolean} Returns `true` if `value` is less than or equal to
55548                *  `other`, else `false`.
55549                * @see _.gte
55550                * @example
55551                *
55552                * _.lte(1, 3);
55553                * // => true
55554                *
55555                * _.lte(3, 3);
55556                * // => true
55557                *
55558                * _.lte(3, 1);
55559                * // => false
55560                */
55561
55562               var lte = createRelationalOperation(function (value, other) {
55563                 return value <= other;
55564               });
55565               /**
55566                * Converts `value` to an array.
55567                *
55568                * @static
55569                * @since 0.1.0
55570                * @memberOf _
55571                * @category Lang
55572                * @param {*} value The value to convert.
55573                * @returns {Array} Returns the converted array.
55574                * @example
55575                *
55576                * _.toArray({ 'a': 1, 'b': 2 });
55577                * // => [1, 2]
55578                *
55579                * _.toArray('abc');
55580                * // => ['a', 'b', 'c']
55581                *
55582                * _.toArray(1);
55583                * // => []
55584                *
55585                * _.toArray(null);
55586                * // => []
55587                */
55588
55589               function toArray(value) {
55590                 if (!value) {
55591                   return [];
55592                 }
55593
55594                 if (isArrayLike(value)) {
55595                   return isString(value) ? stringToArray(value) : copyArray(value);
55596                 }
55597
55598                 if (symIterator && value[symIterator]) {
55599                   return iteratorToArray(value[symIterator]());
55600                 }
55601
55602                 var tag = getTag(value),
55603                     func = tag == mapTag ? mapToArray : tag == setTag ? setToArray : values;
55604                 return func(value);
55605               }
55606               /**
55607                * Converts `value` to a finite number.
55608                *
55609                * @static
55610                * @memberOf _
55611                * @since 4.12.0
55612                * @category Lang
55613                * @param {*} value The value to convert.
55614                * @returns {number} Returns the converted number.
55615                * @example
55616                *
55617                * _.toFinite(3.2);
55618                * // => 3.2
55619                *
55620                * _.toFinite(Number.MIN_VALUE);
55621                * // => 5e-324
55622                *
55623                * _.toFinite(Infinity);
55624                * // => 1.7976931348623157e+308
55625                *
55626                * _.toFinite('3.2');
55627                * // => 3.2
55628                */
55629
55630
55631               function toFinite(value) {
55632                 if (!value) {
55633                   return value === 0 ? value : 0;
55634                 }
55635
55636                 value = toNumber(value);
55637
55638                 if (value === INFINITY || value === -INFINITY) {
55639                   var sign = value < 0 ? -1 : 1;
55640                   return sign * MAX_INTEGER;
55641                 }
55642
55643                 return value === value ? value : 0;
55644               }
55645               /**
55646                * Converts `value` to an integer.
55647                *
55648                * **Note:** This method is loosely based on
55649                * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
55650                *
55651                * @static
55652                * @memberOf _
55653                * @since 4.0.0
55654                * @category Lang
55655                * @param {*} value The value to convert.
55656                * @returns {number} Returns the converted integer.
55657                * @example
55658                *
55659                * _.toInteger(3.2);
55660                * // => 3
55661                *
55662                * _.toInteger(Number.MIN_VALUE);
55663                * // => 0
55664                *
55665                * _.toInteger(Infinity);
55666                * // => 1.7976931348623157e+308
55667                *
55668                * _.toInteger('3.2');
55669                * // => 3
55670                */
55671
55672
55673               function toInteger(value) {
55674                 var result = toFinite(value),
55675                     remainder = result % 1;
55676                 return result === result ? remainder ? result - remainder : result : 0;
55677               }
55678               /**
55679                * Converts `value` to an integer suitable for use as the length of an
55680                * array-like object.
55681                *
55682                * **Note:** This method is based on
55683                * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
55684                *
55685                * @static
55686                * @memberOf _
55687                * @since 4.0.0
55688                * @category Lang
55689                * @param {*} value The value to convert.
55690                * @returns {number} Returns the converted integer.
55691                * @example
55692                *
55693                * _.toLength(3.2);
55694                * // => 3
55695                *
55696                * _.toLength(Number.MIN_VALUE);
55697                * // => 0
55698                *
55699                * _.toLength(Infinity);
55700                * // => 4294967295
55701                *
55702                * _.toLength('3.2');
55703                * // => 3
55704                */
55705
55706
55707               function toLength(value) {
55708                 return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
55709               }
55710               /**
55711                * Converts `value` to a number.
55712                *
55713                * @static
55714                * @memberOf _
55715                * @since 4.0.0
55716                * @category Lang
55717                * @param {*} value The value to process.
55718                * @returns {number} Returns the number.
55719                * @example
55720                *
55721                * _.toNumber(3.2);
55722                * // => 3.2
55723                *
55724                * _.toNumber(Number.MIN_VALUE);
55725                * // => 5e-324
55726                *
55727                * _.toNumber(Infinity);
55728                * // => Infinity
55729                *
55730                * _.toNumber('3.2');
55731                * // => 3.2
55732                */
55733
55734
55735               function toNumber(value) {
55736                 if (typeof value == 'number') {
55737                   return value;
55738                 }
55739
55740                 if (isSymbol(value)) {
55741                   return NAN;
55742                 }
55743
55744                 if (isObject(value)) {
55745                   var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
55746                   value = isObject(other) ? other + '' : other;
55747                 }
55748
55749                 if (typeof value != 'string') {
55750                   return value === 0 ? value : +value;
55751                 }
55752
55753                 value = baseTrim(value);
55754                 var isBinary = reIsBinary.test(value);
55755                 return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value;
55756               }
55757               /**
55758                * Converts `value` to a plain object flattening inherited enumerable string
55759                * keyed properties of `value` to own properties of the plain object.
55760                *
55761                * @static
55762                * @memberOf _
55763                * @since 3.0.0
55764                * @category Lang
55765                * @param {*} value The value to convert.
55766                * @returns {Object} Returns the converted plain object.
55767                * @example
55768                *
55769                * function Foo() {
55770                *   this.b = 2;
55771                * }
55772                *
55773                * Foo.prototype.c = 3;
55774                *
55775                * _.assign({ 'a': 1 }, new Foo);
55776                * // => { 'a': 1, 'b': 2 }
55777                *
55778                * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
55779                * // => { 'a': 1, 'b': 2, 'c': 3 }
55780                */
55781
55782
55783               function toPlainObject(value) {
55784                 return copyObject(value, keysIn(value));
55785               }
55786               /**
55787                * Converts `value` to a safe integer. A safe integer can be compared and
55788                * represented correctly.
55789                *
55790                * @static
55791                * @memberOf _
55792                * @since 4.0.0
55793                * @category Lang
55794                * @param {*} value The value to convert.
55795                * @returns {number} Returns the converted integer.
55796                * @example
55797                *
55798                * _.toSafeInteger(3.2);
55799                * // => 3
55800                *
55801                * _.toSafeInteger(Number.MIN_VALUE);
55802                * // => 0
55803                *
55804                * _.toSafeInteger(Infinity);
55805                * // => 9007199254740991
55806                *
55807                * _.toSafeInteger('3.2');
55808                * // => 3
55809                */
55810
55811
55812               function toSafeInteger(value) {
55813                 return value ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER) : value === 0 ? value : 0;
55814               }
55815               /**
55816                * Converts `value` to a string. An empty string is returned for `null`
55817                * and `undefined` values. The sign of `-0` is preserved.
55818                *
55819                * @static
55820                * @memberOf _
55821                * @since 4.0.0
55822                * @category Lang
55823                * @param {*} value The value to convert.
55824                * @returns {string} Returns the converted string.
55825                * @example
55826                *
55827                * _.toString(null);
55828                * // => ''
55829                *
55830                * _.toString(-0);
55831                * // => '-0'
55832                *
55833                * _.toString([1, 2, 3]);
55834                * // => '1,2,3'
55835                */
55836
55837
55838               function toString(value) {
55839                 return value == null ? '' : baseToString(value);
55840               }
55841               /*------------------------------------------------------------------------*/
55842
55843               /**
55844                * Assigns own enumerable string keyed properties of source objects to the
55845                * destination object. Source objects are applied from left to right.
55846                * Subsequent sources overwrite property assignments of previous sources.
55847                *
55848                * **Note:** This method mutates `object` and is loosely based on
55849                * [`Object.assign`](https://mdn.io/Object/assign).
55850                *
55851                * @static
55852                * @memberOf _
55853                * @since 0.10.0
55854                * @category Object
55855                * @param {Object} object The destination object.
55856                * @param {...Object} [sources] The source objects.
55857                * @returns {Object} Returns `object`.
55858                * @see _.assignIn
55859                * @example
55860                *
55861                * function Foo() {
55862                *   this.a = 1;
55863                * }
55864                *
55865                * function Bar() {
55866                *   this.c = 3;
55867                * }
55868                *
55869                * Foo.prototype.b = 2;
55870                * Bar.prototype.d = 4;
55871                *
55872                * _.assign({ 'a': 0 }, new Foo, new Bar);
55873                * // => { 'a': 1, 'c': 3 }
55874                */
55875
55876
55877               var assign = createAssigner(function (object, source) {
55878                 if (isPrototype(source) || isArrayLike(source)) {
55879                   copyObject(source, keys(source), object);
55880                   return;
55881                 }
55882
55883                 for (var key in source) {
55884                   if (hasOwnProperty.call(source, key)) {
55885                     assignValue(object, key, source[key]);
55886                   }
55887                 }
55888               });
55889               /**
55890                * This method is like `_.assign` except that it iterates over own and
55891                * inherited source properties.
55892                *
55893                * **Note:** This method mutates `object`.
55894                *
55895                * @static
55896                * @memberOf _
55897                * @since 4.0.0
55898                * @alias extend
55899                * @category Object
55900                * @param {Object} object The destination object.
55901                * @param {...Object} [sources] The source objects.
55902                * @returns {Object} Returns `object`.
55903                * @see _.assign
55904                * @example
55905                *
55906                * function Foo() {
55907                *   this.a = 1;
55908                * }
55909                *
55910                * function Bar() {
55911                *   this.c = 3;
55912                * }
55913                *
55914                * Foo.prototype.b = 2;
55915                * Bar.prototype.d = 4;
55916                *
55917                * _.assignIn({ 'a': 0 }, new Foo, new Bar);
55918                * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }
55919                */
55920
55921               var assignIn = createAssigner(function (object, source) {
55922                 copyObject(source, keysIn(source), object);
55923               });
55924               /**
55925                * This method is like `_.assignIn` except that it accepts `customizer`
55926                * which is invoked to produce the assigned values. If `customizer` returns
55927                * `undefined`, assignment is handled by the method instead. The `customizer`
55928                * is invoked with five arguments: (objValue, srcValue, key, object, source).
55929                *
55930                * **Note:** This method mutates `object`.
55931                *
55932                * @static
55933                * @memberOf _
55934                * @since 4.0.0
55935                * @alias extendWith
55936                * @category Object
55937                * @param {Object} object The destination object.
55938                * @param {...Object} sources The source objects.
55939                * @param {Function} [customizer] The function to customize assigned values.
55940                * @returns {Object} Returns `object`.
55941                * @see _.assignWith
55942                * @example
55943                *
55944                * function customizer(objValue, srcValue) {
55945                *   return _.isUndefined(objValue) ? srcValue : objValue;
55946                * }
55947                *
55948                * var defaults = _.partialRight(_.assignInWith, customizer);
55949                *
55950                * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
55951                * // => { 'a': 1, 'b': 2 }
55952                */
55953
55954               var assignInWith = createAssigner(function (object, source, srcIndex, customizer) {
55955                 copyObject(source, keysIn(source), object, customizer);
55956               });
55957               /**
55958                * This method is like `_.assign` except that it accepts `customizer`
55959                * which is invoked to produce the assigned values. If `customizer` returns
55960                * `undefined`, assignment is handled by the method instead. The `customizer`
55961                * is invoked with five arguments: (objValue, srcValue, key, object, source).
55962                *
55963                * **Note:** This method mutates `object`.
55964                *
55965                * @static
55966                * @memberOf _
55967                * @since 4.0.0
55968                * @category Object
55969                * @param {Object} object The destination object.
55970                * @param {...Object} sources The source objects.
55971                * @param {Function} [customizer] The function to customize assigned values.
55972                * @returns {Object} Returns `object`.
55973                * @see _.assignInWith
55974                * @example
55975                *
55976                * function customizer(objValue, srcValue) {
55977                *   return _.isUndefined(objValue) ? srcValue : objValue;
55978                * }
55979                *
55980                * var defaults = _.partialRight(_.assignWith, customizer);
55981                *
55982                * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
55983                * // => { 'a': 1, 'b': 2 }
55984                */
55985
55986               var assignWith = createAssigner(function (object, source, srcIndex, customizer) {
55987                 copyObject(source, keys(source), object, customizer);
55988               });
55989               /**
55990                * Creates an array of values corresponding to `paths` of `object`.
55991                *
55992                * @static
55993                * @memberOf _
55994                * @since 1.0.0
55995                * @category Object
55996                * @param {Object} object The object to iterate over.
55997                * @param {...(string|string[])} [paths] The property paths to pick.
55998                * @returns {Array} Returns the picked values.
55999                * @example
56000                *
56001                * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
56002                *
56003                * _.at(object, ['a[0].b.c', 'a[1]']);
56004                * // => [3, 4]
56005                */
56006
56007               var at = flatRest(baseAt);
56008               /**
56009                * Creates an object that inherits from the `prototype` object. If a
56010                * `properties` object is given, its own enumerable string keyed properties
56011                * are assigned to the created object.
56012                *
56013                * @static
56014                * @memberOf _
56015                * @since 2.3.0
56016                * @category Object
56017                * @param {Object} prototype The object to inherit from.
56018                * @param {Object} [properties] The properties to assign to the object.
56019                * @returns {Object} Returns the new object.
56020                * @example
56021                *
56022                * function Shape() {
56023                *   this.x = 0;
56024                *   this.y = 0;
56025                * }
56026                *
56027                * function Circle() {
56028                *   Shape.call(this);
56029                * }
56030                *
56031                * Circle.prototype = _.create(Shape.prototype, {
56032                *   'constructor': Circle
56033                * });
56034                *
56035                * var circle = new Circle;
56036                * circle instanceof Circle;
56037                * // => true
56038                *
56039                * circle instanceof Shape;
56040                * // => true
56041                */
56042
56043               function create(prototype, properties) {
56044                 var result = baseCreate(prototype);
56045                 return properties == null ? result : baseAssign(result, properties);
56046               }
56047               /**
56048                * Assigns own and inherited enumerable string keyed properties of source
56049                * objects to the destination object for all destination properties that
56050                * resolve to `undefined`. Source objects are applied from left to right.
56051                * Once a property is set, additional values of the same property are ignored.
56052                *
56053                * **Note:** This method mutates `object`.
56054                *
56055                * @static
56056                * @since 0.1.0
56057                * @memberOf _
56058                * @category Object
56059                * @param {Object} object The destination object.
56060                * @param {...Object} [sources] The source objects.
56061                * @returns {Object} Returns `object`.
56062                * @see _.defaultsDeep
56063                * @example
56064                *
56065                * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
56066                * // => { 'a': 1, 'b': 2 }
56067                */
56068
56069
56070               var defaults = baseRest(function (object, sources) {
56071                 object = Object(object);
56072                 var index = -1;
56073                 var length = sources.length;
56074                 var guard = length > 2 ? sources[2] : undefined$1;
56075
56076                 if (guard && isIterateeCall(sources[0], sources[1], guard)) {
56077                   length = 1;
56078                 }
56079
56080                 while (++index < length) {
56081                   var source = sources[index];
56082                   var props = keysIn(source);
56083                   var propsIndex = -1;
56084                   var propsLength = props.length;
56085
56086                   while (++propsIndex < propsLength) {
56087                     var key = props[propsIndex];
56088                     var value = object[key];
56089
56090                     if (value === undefined$1 || eq(value, objectProto[key]) && !hasOwnProperty.call(object, key)) {
56091                       object[key] = source[key];
56092                     }
56093                   }
56094                 }
56095
56096                 return object;
56097               });
56098               /**
56099                * This method is like `_.defaults` except that it recursively assigns
56100                * default properties.
56101                *
56102                * **Note:** This method mutates `object`.
56103                *
56104                * @static
56105                * @memberOf _
56106                * @since 3.10.0
56107                * @category Object
56108                * @param {Object} object The destination object.
56109                * @param {...Object} [sources] The source objects.
56110                * @returns {Object} Returns `object`.
56111                * @see _.defaults
56112                * @example
56113                *
56114                * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });
56115                * // => { 'a': { 'b': 2, 'c': 3 } }
56116                */
56117
56118               var defaultsDeep = baseRest(function (args) {
56119                 args.push(undefined$1, customDefaultsMerge);
56120                 return apply(mergeWith, undefined$1, args);
56121               });
56122               /**
56123                * This method is like `_.find` except that it returns the key of the first
56124                * element `predicate` returns truthy for instead of the element itself.
56125                *
56126                * @static
56127                * @memberOf _
56128                * @since 1.1.0
56129                * @category Object
56130                * @param {Object} object The object to inspect.
56131                * @param {Function} [predicate=_.identity] The function invoked per iteration.
56132                * @returns {string|undefined} Returns the key of the matched element,
56133                *  else `undefined`.
56134                * @example
56135                *
56136                * var users = {
56137                *   'barney':  { 'age': 36, 'active': true },
56138                *   'fred':    { 'age': 40, 'active': false },
56139                *   'pebbles': { 'age': 1,  'active': true }
56140                * };
56141                *
56142                * _.findKey(users, function(o) { return o.age < 40; });
56143                * // => 'barney' (iteration order is not guaranteed)
56144                *
56145                * // The `_.matches` iteratee shorthand.
56146                * _.findKey(users, { 'age': 1, 'active': true });
56147                * // => 'pebbles'
56148                *
56149                * // The `_.matchesProperty` iteratee shorthand.
56150                * _.findKey(users, ['active', false]);
56151                * // => 'fred'
56152                *
56153                * // The `_.property` iteratee shorthand.
56154                * _.findKey(users, 'active');
56155                * // => 'barney'
56156                */
56157
56158               function findKey(object, predicate) {
56159                 return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);
56160               }
56161               /**
56162                * This method is like `_.findKey` except that it iterates over elements of
56163                * a collection in the opposite order.
56164                *
56165                * @static
56166                * @memberOf _
56167                * @since 2.0.0
56168                * @category Object
56169                * @param {Object} object The object to inspect.
56170                * @param {Function} [predicate=_.identity] The function invoked per iteration.
56171                * @returns {string|undefined} Returns the key of the matched element,
56172                *  else `undefined`.
56173                * @example
56174                *
56175                * var users = {
56176                *   'barney':  { 'age': 36, 'active': true },
56177                *   'fred':    { 'age': 40, 'active': false },
56178                *   'pebbles': { 'age': 1,  'active': true }
56179                * };
56180                *
56181                * _.findLastKey(users, function(o) { return o.age < 40; });
56182                * // => returns 'pebbles' assuming `_.findKey` returns 'barney'
56183                *
56184                * // The `_.matches` iteratee shorthand.
56185                * _.findLastKey(users, { 'age': 36, 'active': true });
56186                * // => 'barney'
56187                *
56188                * // The `_.matchesProperty` iteratee shorthand.
56189                * _.findLastKey(users, ['active', false]);
56190                * // => 'fred'
56191                *
56192                * // The `_.property` iteratee shorthand.
56193                * _.findLastKey(users, 'active');
56194                * // => 'pebbles'
56195                */
56196
56197
56198               function findLastKey(object, predicate) {
56199                 return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);
56200               }
56201               /**
56202                * Iterates over own and inherited enumerable string keyed properties of an
56203                * object and invokes `iteratee` for each property. The iteratee is invoked
56204                * with three arguments: (value, key, object). Iteratee functions may exit
56205                * iteration early by explicitly returning `false`.
56206                *
56207                * @static
56208                * @memberOf _
56209                * @since 0.3.0
56210                * @category Object
56211                * @param {Object} object The object to iterate over.
56212                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
56213                * @returns {Object} Returns `object`.
56214                * @see _.forInRight
56215                * @example
56216                *
56217                * function Foo() {
56218                *   this.a = 1;
56219                *   this.b = 2;
56220                * }
56221                *
56222                * Foo.prototype.c = 3;
56223                *
56224                * _.forIn(new Foo, function(value, key) {
56225                *   console.log(key);
56226                * });
56227                * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed).
56228                */
56229
56230
56231               function forIn(object, iteratee) {
56232                 return object == null ? object : baseFor(object, getIteratee(iteratee, 3), keysIn);
56233               }
56234               /**
56235                * This method is like `_.forIn` except that it iterates over properties of
56236                * `object` in the opposite order.
56237                *
56238                * @static
56239                * @memberOf _
56240                * @since 2.0.0
56241                * @category Object
56242                * @param {Object} object The object to iterate over.
56243                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
56244                * @returns {Object} Returns `object`.
56245                * @see _.forIn
56246                * @example
56247                *
56248                * function Foo() {
56249                *   this.a = 1;
56250                *   this.b = 2;
56251                * }
56252                *
56253                * Foo.prototype.c = 3;
56254                *
56255                * _.forInRight(new Foo, function(value, key) {
56256                *   console.log(key);
56257                * });
56258                * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'.
56259                */
56260
56261
56262               function forInRight(object, iteratee) {
56263                 return object == null ? object : baseForRight(object, getIteratee(iteratee, 3), keysIn);
56264               }
56265               /**
56266                * Iterates over own enumerable string keyed properties of an object and
56267                * invokes `iteratee` for each property. The iteratee is invoked with three
56268                * arguments: (value, key, object). Iteratee functions may exit iteration
56269                * early by explicitly returning `false`.
56270                *
56271                * @static
56272                * @memberOf _
56273                * @since 0.3.0
56274                * @category Object
56275                * @param {Object} object The object to iterate over.
56276                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
56277                * @returns {Object} Returns `object`.
56278                * @see _.forOwnRight
56279                * @example
56280                *
56281                * function Foo() {
56282                *   this.a = 1;
56283                *   this.b = 2;
56284                * }
56285                *
56286                * Foo.prototype.c = 3;
56287                *
56288                * _.forOwn(new Foo, function(value, key) {
56289                *   console.log(key);
56290                * });
56291                * // => Logs 'a' then 'b' (iteration order is not guaranteed).
56292                */
56293
56294
56295               function forOwn(object, iteratee) {
56296                 return object && baseForOwn(object, getIteratee(iteratee, 3));
56297               }
56298               /**
56299                * This method is like `_.forOwn` except that it iterates over properties of
56300                * `object` in the opposite order.
56301                *
56302                * @static
56303                * @memberOf _
56304                * @since 2.0.0
56305                * @category Object
56306                * @param {Object} object The object to iterate over.
56307                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
56308                * @returns {Object} Returns `object`.
56309                * @see _.forOwn
56310                * @example
56311                *
56312                * function Foo() {
56313                *   this.a = 1;
56314                *   this.b = 2;
56315                * }
56316                *
56317                * Foo.prototype.c = 3;
56318                *
56319                * _.forOwnRight(new Foo, function(value, key) {
56320                *   console.log(key);
56321                * });
56322                * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'.
56323                */
56324
56325
56326               function forOwnRight(object, iteratee) {
56327                 return object && baseForOwnRight(object, getIteratee(iteratee, 3));
56328               }
56329               /**
56330                * Creates an array of function property names from own enumerable properties
56331                * of `object`.
56332                *
56333                * @static
56334                * @since 0.1.0
56335                * @memberOf _
56336                * @category Object
56337                * @param {Object} object The object to inspect.
56338                * @returns {Array} Returns the function names.
56339                * @see _.functionsIn
56340                * @example
56341                *
56342                * function Foo() {
56343                *   this.a = _.constant('a');
56344                *   this.b = _.constant('b');
56345                * }
56346                *
56347                * Foo.prototype.c = _.constant('c');
56348                *
56349                * _.functions(new Foo);
56350                * // => ['a', 'b']
56351                */
56352
56353
56354               function functions(object) {
56355                 return object == null ? [] : baseFunctions(object, keys(object));
56356               }
56357               /**
56358                * Creates an array of function property names from own and inherited
56359                * enumerable properties of `object`.
56360                *
56361                * @static
56362                * @memberOf _
56363                * @since 4.0.0
56364                * @category Object
56365                * @param {Object} object The object to inspect.
56366                * @returns {Array} Returns the function names.
56367                * @see _.functions
56368                * @example
56369                *
56370                * function Foo() {
56371                *   this.a = _.constant('a');
56372                *   this.b = _.constant('b');
56373                * }
56374                *
56375                * Foo.prototype.c = _.constant('c');
56376                *
56377                * _.functionsIn(new Foo);
56378                * // => ['a', 'b', 'c']
56379                */
56380
56381
56382               function functionsIn(object) {
56383                 return object == null ? [] : baseFunctions(object, keysIn(object));
56384               }
56385               /**
56386                * Gets the value at `path` of `object`. If the resolved value is
56387                * `undefined`, the `defaultValue` is returned in its place.
56388                *
56389                * @static
56390                * @memberOf _
56391                * @since 3.7.0
56392                * @category Object
56393                * @param {Object} object The object to query.
56394                * @param {Array|string} path The path of the property to get.
56395                * @param {*} [defaultValue] The value returned for `undefined` resolved values.
56396                * @returns {*} Returns the resolved value.
56397                * @example
56398                *
56399                * var object = { 'a': [{ 'b': { 'c': 3 } }] };
56400                *
56401                * _.get(object, 'a[0].b.c');
56402                * // => 3
56403                *
56404                * _.get(object, ['a', '0', 'b', 'c']);
56405                * // => 3
56406                *
56407                * _.get(object, 'a.b.c', 'default');
56408                * // => 'default'
56409                */
56410
56411
56412               function get(object, path, defaultValue) {
56413                 var result = object == null ? undefined$1 : baseGet(object, path);
56414                 return result === undefined$1 ? defaultValue : result;
56415               }
56416               /**
56417                * Checks if `path` is a direct property of `object`.
56418                *
56419                * @static
56420                * @since 0.1.0
56421                * @memberOf _
56422                * @category Object
56423                * @param {Object} object The object to query.
56424                * @param {Array|string} path The path to check.
56425                * @returns {boolean} Returns `true` if `path` exists, else `false`.
56426                * @example
56427                *
56428                * var object = { 'a': { 'b': 2 } };
56429                * var other = _.create({ 'a': _.create({ 'b': 2 }) });
56430                *
56431                * _.has(object, 'a');
56432                * // => true
56433                *
56434                * _.has(object, 'a.b');
56435                * // => true
56436                *
56437                * _.has(object, ['a', 'b']);
56438                * // => true
56439                *
56440                * _.has(other, 'a');
56441                * // => false
56442                */
56443
56444
56445               function has(object, path) {
56446                 return object != null && hasPath(object, path, baseHas);
56447               }
56448               /**
56449                * Checks if `path` is a direct or inherited property of `object`.
56450                *
56451                * @static
56452                * @memberOf _
56453                * @since 4.0.0
56454                * @category Object
56455                * @param {Object} object The object to query.
56456                * @param {Array|string} path The path to check.
56457                * @returns {boolean} Returns `true` if `path` exists, else `false`.
56458                * @example
56459                *
56460                * var object = _.create({ 'a': _.create({ 'b': 2 }) });
56461                *
56462                * _.hasIn(object, 'a');
56463                * // => true
56464                *
56465                * _.hasIn(object, 'a.b');
56466                * // => true
56467                *
56468                * _.hasIn(object, ['a', 'b']);
56469                * // => true
56470                *
56471                * _.hasIn(object, 'b');
56472                * // => false
56473                */
56474
56475
56476               function hasIn(object, path) {
56477                 return object != null && hasPath(object, path, baseHasIn);
56478               }
56479               /**
56480                * Creates an object composed of the inverted keys and values of `object`.
56481                * If `object` contains duplicate values, subsequent values overwrite
56482                * property assignments of previous values.
56483                *
56484                * @static
56485                * @memberOf _
56486                * @since 0.7.0
56487                * @category Object
56488                * @param {Object} object The object to invert.
56489                * @returns {Object} Returns the new inverted object.
56490                * @example
56491                *
56492                * var object = { 'a': 1, 'b': 2, 'c': 1 };
56493                *
56494                * _.invert(object);
56495                * // => { '1': 'c', '2': 'b' }
56496                */
56497
56498
56499               var invert = createInverter(function (result, value, key) {
56500                 if (value != null && typeof value.toString != 'function') {
56501                   value = nativeObjectToString.call(value);
56502                 }
56503
56504                 result[value] = key;
56505               }, constant(identity));
56506               /**
56507                * This method is like `_.invert` except that the inverted object is generated
56508                * from the results of running each element of `object` thru `iteratee`. The
56509                * corresponding inverted value of each inverted key is an array of keys
56510                * responsible for generating the inverted value. The iteratee is invoked
56511                * with one argument: (value).
56512                *
56513                * @static
56514                * @memberOf _
56515                * @since 4.1.0
56516                * @category Object
56517                * @param {Object} object The object to invert.
56518                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
56519                * @returns {Object} Returns the new inverted object.
56520                * @example
56521                *
56522                * var object = { 'a': 1, 'b': 2, 'c': 1 };
56523                *
56524                * _.invertBy(object);
56525                * // => { '1': ['a', 'c'], '2': ['b'] }
56526                *
56527                * _.invertBy(object, function(value) {
56528                *   return 'group' + value;
56529                * });
56530                * // => { 'group1': ['a', 'c'], 'group2': ['b'] }
56531                */
56532
56533               var invertBy = createInverter(function (result, value, key) {
56534                 if (value != null && typeof value.toString != 'function') {
56535                   value = nativeObjectToString.call(value);
56536                 }
56537
56538                 if (hasOwnProperty.call(result, value)) {
56539                   result[value].push(key);
56540                 } else {
56541                   result[value] = [key];
56542                 }
56543               }, getIteratee);
56544               /**
56545                * Invokes the method at `path` of `object`.
56546                *
56547                * @static
56548                * @memberOf _
56549                * @since 4.0.0
56550                * @category Object
56551                * @param {Object} object The object to query.
56552                * @param {Array|string} path The path of the method to invoke.
56553                * @param {...*} [args] The arguments to invoke the method with.
56554                * @returns {*} Returns the result of the invoked method.
56555                * @example
56556                *
56557                * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };
56558                *
56559                * _.invoke(object, 'a[0].b.c.slice', 1, 3);
56560                * // => [2, 3]
56561                */
56562
56563               var invoke = baseRest(baseInvoke);
56564               /**
56565                * Creates an array of the own enumerable property names of `object`.
56566                *
56567                * **Note:** Non-object values are coerced to objects. See the
56568                * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
56569                * for more details.
56570                *
56571                * @static
56572                * @since 0.1.0
56573                * @memberOf _
56574                * @category Object
56575                * @param {Object} object The object to query.
56576                * @returns {Array} Returns the array of property names.
56577                * @example
56578                *
56579                * function Foo() {
56580                *   this.a = 1;
56581                *   this.b = 2;
56582                * }
56583                *
56584                * Foo.prototype.c = 3;
56585                *
56586                * _.keys(new Foo);
56587                * // => ['a', 'b'] (iteration order is not guaranteed)
56588                *
56589                * _.keys('hi');
56590                * // => ['0', '1']
56591                */
56592
56593               function keys(object) {
56594                 return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
56595               }
56596               /**
56597                * Creates an array of the own and inherited enumerable property names of `object`.
56598                *
56599                * **Note:** Non-object values are coerced to objects.
56600                *
56601                * @static
56602                * @memberOf _
56603                * @since 3.0.0
56604                * @category Object
56605                * @param {Object} object The object to query.
56606                * @returns {Array} Returns the array of property names.
56607                * @example
56608                *
56609                * function Foo() {
56610                *   this.a = 1;
56611                *   this.b = 2;
56612                * }
56613                *
56614                * Foo.prototype.c = 3;
56615                *
56616                * _.keysIn(new Foo);
56617                * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
56618                */
56619
56620
56621               function keysIn(object) {
56622                 return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
56623               }
56624               /**
56625                * The opposite of `_.mapValues`; this method creates an object with the
56626                * same values as `object` and keys generated by running each own enumerable
56627                * string keyed property of `object` thru `iteratee`. The iteratee is invoked
56628                * with three arguments: (value, key, object).
56629                *
56630                * @static
56631                * @memberOf _
56632                * @since 3.8.0
56633                * @category Object
56634                * @param {Object} object The object to iterate over.
56635                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
56636                * @returns {Object} Returns the new mapped object.
56637                * @see _.mapValues
56638                * @example
56639                *
56640                * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
56641                *   return key + value;
56642                * });
56643                * // => { 'a1': 1, 'b2': 2 }
56644                */
56645
56646
56647               function mapKeys(object, iteratee) {
56648                 var result = {};
56649                 iteratee = getIteratee(iteratee, 3);
56650                 baseForOwn(object, function (value, key, object) {
56651                   baseAssignValue(result, iteratee(value, key, object), value);
56652                 });
56653                 return result;
56654               }
56655               /**
56656                * Creates an object with the same keys as `object` and values generated
56657                * by running each own enumerable string keyed property of `object` thru
56658                * `iteratee`. The iteratee is invoked with three arguments:
56659                * (value, key, object).
56660                *
56661                * @static
56662                * @memberOf _
56663                * @since 2.4.0
56664                * @category Object
56665                * @param {Object} object The object to iterate over.
56666                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
56667                * @returns {Object} Returns the new mapped object.
56668                * @see _.mapKeys
56669                * @example
56670                *
56671                * var users = {
56672                *   'fred':    { 'user': 'fred',    'age': 40 },
56673                *   'pebbles': { 'user': 'pebbles', 'age': 1 }
56674                * };
56675                *
56676                * _.mapValues(users, function(o) { return o.age; });
56677                * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
56678                *
56679                * // The `_.property` iteratee shorthand.
56680                * _.mapValues(users, 'age');
56681                * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
56682                */
56683
56684
56685               function mapValues(object, iteratee) {
56686                 var result = {};
56687                 iteratee = getIteratee(iteratee, 3);
56688                 baseForOwn(object, function (value, key, object) {
56689                   baseAssignValue(result, key, iteratee(value, key, object));
56690                 });
56691                 return result;
56692               }
56693               /**
56694                * This method is like `_.assign` except that it recursively merges own and
56695                * inherited enumerable string keyed properties of source objects into the
56696                * destination object. Source properties that resolve to `undefined` are
56697                * skipped if a destination value exists. Array and plain object properties
56698                * are merged recursively. Other objects and value types are overridden by
56699                * assignment. Source objects are applied from left to right. Subsequent
56700                * sources overwrite property assignments of previous sources.
56701                *
56702                * **Note:** This method mutates `object`.
56703                *
56704                * @static
56705                * @memberOf _
56706                * @since 0.5.0
56707                * @category Object
56708                * @param {Object} object The destination object.
56709                * @param {...Object} [sources] The source objects.
56710                * @returns {Object} Returns `object`.
56711                * @example
56712                *
56713                * var object = {
56714                *   'a': [{ 'b': 2 }, { 'd': 4 }]
56715                * };
56716                *
56717                * var other = {
56718                *   'a': [{ 'c': 3 }, { 'e': 5 }]
56719                * };
56720                *
56721                * _.merge(object, other);
56722                * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
56723                */
56724
56725
56726               var merge = createAssigner(function (object, source, srcIndex) {
56727                 baseMerge(object, source, srcIndex);
56728               });
56729               /**
56730                * This method is like `_.merge` except that it accepts `customizer` which
56731                * is invoked to produce the merged values of the destination and source
56732                * properties. If `customizer` returns `undefined`, merging is handled by the
56733                * method instead. The `customizer` is invoked with six arguments:
56734                * (objValue, srcValue, key, object, source, stack).
56735                *
56736                * **Note:** This method mutates `object`.
56737                *
56738                * @static
56739                * @memberOf _
56740                * @since 4.0.0
56741                * @category Object
56742                * @param {Object} object The destination object.
56743                * @param {...Object} sources The source objects.
56744                * @param {Function} customizer The function to customize assigned values.
56745                * @returns {Object} Returns `object`.
56746                * @example
56747                *
56748                * function customizer(objValue, srcValue) {
56749                *   if (_.isArray(objValue)) {
56750                *     return objValue.concat(srcValue);
56751                *   }
56752                * }
56753                *
56754                * var object = { 'a': [1], 'b': [2] };
56755                * var other = { 'a': [3], 'b': [4] };
56756                *
56757                * _.mergeWith(object, other, customizer);
56758                * // => { 'a': [1, 3], 'b': [2, 4] }
56759                */
56760
56761               var mergeWith = createAssigner(function (object, source, srcIndex, customizer) {
56762                 baseMerge(object, source, srcIndex, customizer);
56763               });
56764               /**
56765                * The opposite of `_.pick`; this method creates an object composed of the
56766                * own and inherited enumerable property paths of `object` that are not omitted.
56767                *
56768                * **Note:** This method is considerably slower than `_.pick`.
56769                *
56770                * @static
56771                * @since 0.1.0
56772                * @memberOf _
56773                * @category Object
56774                * @param {Object} object The source object.
56775                * @param {...(string|string[])} [paths] The property paths to omit.
56776                * @returns {Object} Returns the new object.
56777                * @example
56778                *
56779                * var object = { 'a': 1, 'b': '2', 'c': 3 };
56780                *
56781                * _.omit(object, ['a', 'c']);
56782                * // => { 'b': '2' }
56783                */
56784
56785               var omit = flatRest(function (object, paths) {
56786                 var result = {};
56787
56788                 if (object == null) {
56789                   return result;
56790                 }
56791
56792                 var isDeep = false;
56793                 paths = arrayMap(paths, function (path) {
56794                   path = castPath(path, object);
56795                   isDeep || (isDeep = path.length > 1);
56796                   return path;
56797                 });
56798                 copyObject(object, getAllKeysIn(object), result);
56799
56800                 if (isDeep) {
56801                   result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone);
56802                 }
56803
56804                 var length = paths.length;
56805
56806                 while (length--) {
56807                   baseUnset(result, paths[length]);
56808                 }
56809
56810                 return result;
56811               });
56812               /**
56813                * The opposite of `_.pickBy`; this method creates an object composed of
56814                * the own and inherited enumerable string keyed properties of `object` that
56815                * `predicate` doesn't return truthy for. The predicate is invoked with two
56816                * arguments: (value, key).
56817                *
56818                * @static
56819                * @memberOf _
56820                * @since 4.0.0
56821                * @category Object
56822                * @param {Object} object The source object.
56823                * @param {Function} [predicate=_.identity] The function invoked per property.
56824                * @returns {Object} Returns the new object.
56825                * @example
56826                *
56827                * var object = { 'a': 1, 'b': '2', 'c': 3 };
56828                *
56829                * _.omitBy(object, _.isNumber);
56830                * // => { 'b': '2' }
56831                */
56832
56833               function omitBy(object, predicate) {
56834                 return pickBy(object, negate(getIteratee(predicate)));
56835               }
56836               /**
56837                * Creates an object composed of the picked `object` properties.
56838                *
56839                * @static
56840                * @since 0.1.0
56841                * @memberOf _
56842                * @category Object
56843                * @param {Object} object The source object.
56844                * @param {...(string|string[])} [paths] The property paths to pick.
56845                * @returns {Object} Returns the new object.
56846                * @example
56847                *
56848                * var object = { 'a': 1, 'b': '2', 'c': 3 };
56849                *
56850                * _.pick(object, ['a', 'c']);
56851                * // => { 'a': 1, 'c': 3 }
56852                */
56853
56854
56855               var pick = flatRest(function (object, paths) {
56856                 return object == null ? {} : basePick(object, paths);
56857               });
56858               /**
56859                * Creates an object composed of the `object` properties `predicate` returns
56860                * truthy for. The predicate is invoked with two arguments: (value, key).
56861                *
56862                * @static
56863                * @memberOf _
56864                * @since 4.0.0
56865                * @category Object
56866                * @param {Object} object The source object.
56867                * @param {Function} [predicate=_.identity] The function invoked per property.
56868                * @returns {Object} Returns the new object.
56869                * @example
56870                *
56871                * var object = { 'a': 1, 'b': '2', 'c': 3 };
56872                *
56873                * _.pickBy(object, _.isNumber);
56874                * // => { 'a': 1, 'c': 3 }
56875                */
56876
56877               function pickBy(object, predicate) {
56878                 if (object == null) {
56879                   return {};
56880                 }
56881
56882                 var props = arrayMap(getAllKeysIn(object), function (prop) {
56883                   return [prop];
56884                 });
56885                 predicate = getIteratee(predicate);
56886                 return basePickBy(object, props, function (value, path) {
56887                   return predicate(value, path[0]);
56888                 });
56889               }
56890               /**
56891                * This method is like `_.get` except that if the resolved value is a
56892                * function it's invoked with the `this` binding of its parent object and
56893                * its result is returned.
56894                *
56895                * @static
56896                * @since 0.1.0
56897                * @memberOf _
56898                * @category Object
56899                * @param {Object} object The object to query.
56900                * @param {Array|string} path The path of the property to resolve.
56901                * @param {*} [defaultValue] The value returned for `undefined` resolved values.
56902                * @returns {*} Returns the resolved value.
56903                * @example
56904                *
56905                * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
56906                *
56907                * _.result(object, 'a[0].b.c1');
56908                * // => 3
56909                *
56910                * _.result(object, 'a[0].b.c2');
56911                * // => 4
56912                *
56913                * _.result(object, 'a[0].b.c3', 'default');
56914                * // => 'default'
56915                *
56916                * _.result(object, 'a[0].b.c3', _.constant('default'));
56917                * // => 'default'
56918                */
56919
56920
56921               function result(object, path, defaultValue) {
56922                 path = castPath(path, object);
56923                 var index = -1,
56924                     length = path.length; // Ensure the loop is entered when path is empty.
56925
56926                 if (!length) {
56927                   length = 1;
56928                   object = undefined$1;
56929                 }
56930
56931                 while (++index < length) {
56932                   var value = object == null ? undefined$1 : object[toKey(path[index])];
56933
56934                   if (value === undefined$1) {
56935                     index = length;
56936                     value = defaultValue;
56937                   }
56938
56939                   object = isFunction(value) ? value.call(object) : value;
56940                 }
56941
56942                 return object;
56943               }
56944               /**
56945                * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,
56946                * it's created. Arrays are created for missing index properties while objects
56947                * are created for all other missing properties. Use `_.setWith` to customize
56948                * `path` creation.
56949                *
56950                * **Note:** This method mutates `object`.
56951                *
56952                * @static
56953                * @memberOf _
56954                * @since 3.7.0
56955                * @category Object
56956                * @param {Object} object The object to modify.
56957                * @param {Array|string} path The path of the property to set.
56958                * @param {*} value The value to set.
56959                * @returns {Object} Returns `object`.
56960                * @example
56961                *
56962                * var object = { 'a': [{ 'b': { 'c': 3 } }] };
56963                *
56964                * _.set(object, 'a[0].b.c', 4);
56965                * console.log(object.a[0].b.c);
56966                * // => 4
56967                *
56968                * _.set(object, ['x', '0', 'y', 'z'], 5);
56969                * console.log(object.x[0].y.z);
56970                * // => 5
56971                */
56972
56973
56974               function set(object, path, value) {
56975                 return object == null ? object : baseSet(object, path, value);
56976               }
56977               /**
56978                * This method is like `_.set` except that it accepts `customizer` which is
56979                * invoked to produce the objects of `path`.  If `customizer` returns `undefined`
56980                * path creation is handled by the method instead. The `customizer` is invoked
56981                * with three arguments: (nsValue, key, nsObject).
56982                *
56983                * **Note:** This method mutates `object`.
56984                *
56985                * @static
56986                * @memberOf _
56987                * @since 4.0.0
56988                * @category Object
56989                * @param {Object} object The object to modify.
56990                * @param {Array|string} path The path of the property to set.
56991                * @param {*} value The value to set.
56992                * @param {Function} [customizer] The function to customize assigned values.
56993                * @returns {Object} Returns `object`.
56994                * @example
56995                *
56996                * var object = {};
56997                *
56998                * _.setWith(object, '[0][1]', 'a', Object);
56999                * // => { '0': { '1': 'a' } }
57000                */
57001
57002
57003               function setWith(object, path, value, customizer) {
57004                 customizer = typeof customizer == 'function' ? customizer : undefined$1;
57005                 return object == null ? object : baseSet(object, path, value, customizer);
57006               }
57007               /**
57008                * Creates an array of own enumerable string keyed-value pairs for `object`
57009                * which can be consumed by `_.fromPairs`. If `object` is a map or set, its
57010                * entries are returned.
57011                *
57012                * @static
57013                * @memberOf _
57014                * @since 4.0.0
57015                * @alias entries
57016                * @category Object
57017                * @param {Object} object The object to query.
57018                * @returns {Array} Returns the key-value pairs.
57019                * @example
57020                *
57021                * function Foo() {
57022                *   this.a = 1;
57023                *   this.b = 2;
57024                * }
57025                *
57026                * Foo.prototype.c = 3;
57027                *
57028                * _.toPairs(new Foo);
57029                * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
57030                */
57031
57032
57033               var toPairs = createToPairs(keys);
57034               /**
57035                * Creates an array of own and inherited enumerable string keyed-value pairs
57036                * for `object` which can be consumed by `_.fromPairs`. If `object` is a map
57037                * or set, its entries are returned.
57038                *
57039                * @static
57040                * @memberOf _
57041                * @since 4.0.0
57042                * @alias entriesIn
57043                * @category Object
57044                * @param {Object} object The object to query.
57045                * @returns {Array} Returns the key-value pairs.
57046                * @example
57047                *
57048                * function Foo() {
57049                *   this.a = 1;
57050                *   this.b = 2;
57051                * }
57052                *
57053                * Foo.prototype.c = 3;
57054                *
57055                * _.toPairsIn(new Foo);
57056                * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed)
57057                */
57058
57059               var toPairsIn = createToPairs(keysIn);
57060               /**
57061                * An alternative to `_.reduce`; this method transforms `object` to a new
57062                * `accumulator` object which is the result of running each of its own
57063                * enumerable string keyed properties thru `iteratee`, with each invocation
57064                * potentially mutating the `accumulator` object. If `accumulator` is not
57065                * provided, a new object with the same `[[Prototype]]` will be used. The
57066                * iteratee is invoked with four arguments: (accumulator, value, key, object).
57067                * Iteratee functions may exit iteration early by explicitly returning `false`.
57068                *
57069                * @static
57070                * @memberOf _
57071                * @since 1.3.0
57072                * @category Object
57073                * @param {Object} object The object to iterate over.
57074                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
57075                * @param {*} [accumulator] The custom accumulator value.
57076                * @returns {*} Returns the accumulated value.
57077                * @example
57078                *
57079                * _.transform([2, 3, 4], function(result, n) {
57080                *   result.push(n *= n);
57081                *   return n % 2 == 0;
57082                * }, []);
57083                * // => [4, 9]
57084                *
57085                * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
57086                *   (result[value] || (result[value] = [])).push(key);
57087                * }, {});
57088                * // => { '1': ['a', 'c'], '2': ['b'] }
57089                */
57090
57091               function transform(object, iteratee, accumulator) {
57092                 var isArr = isArray(object),
57093                     isArrLike = isArr || isBuffer(object) || isTypedArray(object);
57094                 iteratee = getIteratee(iteratee, 4);
57095
57096                 if (accumulator == null) {
57097                   var Ctor = object && object.constructor;
57098
57099                   if (isArrLike) {
57100                     accumulator = isArr ? new Ctor() : [];
57101                   } else if (isObject(object)) {
57102                     accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
57103                   } else {
57104                     accumulator = {};
57105                   }
57106                 }
57107
57108                 (isArrLike ? arrayEach : baseForOwn)(object, function (value, index, object) {
57109                   return iteratee(accumulator, value, index, object);
57110                 });
57111                 return accumulator;
57112               }
57113               /**
57114                * Removes the property at `path` of `object`.
57115                *
57116                * **Note:** This method mutates `object`.
57117                *
57118                * @static
57119                * @memberOf _
57120                * @since 4.0.0
57121                * @category Object
57122                * @param {Object} object The object to modify.
57123                * @param {Array|string} path The path of the property to unset.
57124                * @returns {boolean} Returns `true` if the property is deleted, else `false`.
57125                * @example
57126                *
57127                * var object = { 'a': [{ 'b': { 'c': 7 } }] };
57128                * _.unset(object, 'a[0].b.c');
57129                * // => true
57130                *
57131                * console.log(object);
57132                * // => { 'a': [{ 'b': {} }] };
57133                *
57134                * _.unset(object, ['a', '0', 'b', 'c']);
57135                * // => true
57136                *
57137                * console.log(object);
57138                * // => { 'a': [{ 'b': {} }] };
57139                */
57140
57141
57142               function unset(object, path) {
57143                 return object == null ? true : baseUnset(object, path);
57144               }
57145               /**
57146                * This method is like `_.set` except that accepts `updater` to produce the
57147                * value to set. Use `_.updateWith` to customize `path` creation. The `updater`
57148                * is invoked with one argument: (value).
57149                *
57150                * **Note:** This method mutates `object`.
57151                *
57152                * @static
57153                * @memberOf _
57154                * @since 4.6.0
57155                * @category Object
57156                * @param {Object} object The object to modify.
57157                * @param {Array|string} path The path of the property to set.
57158                * @param {Function} updater The function to produce the updated value.
57159                * @returns {Object} Returns `object`.
57160                * @example
57161                *
57162                * var object = { 'a': [{ 'b': { 'c': 3 } }] };
57163                *
57164                * _.update(object, 'a[0].b.c', function(n) { return n * n; });
57165                * console.log(object.a[0].b.c);
57166                * // => 9
57167                *
57168                * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; });
57169                * console.log(object.x[0].y.z);
57170                * // => 0
57171                */
57172
57173
57174               function update(object, path, updater) {
57175                 return object == null ? object : baseUpdate(object, path, castFunction(updater));
57176               }
57177               /**
57178                * This method is like `_.update` except that it accepts `customizer` which is
57179                * invoked to produce the objects of `path`.  If `customizer` returns `undefined`
57180                * path creation is handled by the method instead. The `customizer` is invoked
57181                * with three arguments: (nsValue, key, nsObject).
57182                *
57183                * **Note:** This method mutates `object`.
57184                *
57185                * @static
57186                * @memberOf _
57187                * @since 4.6.0
57188                * @category Object
57189                * @param {Object} object The object to modify.
57190                * @param {Array|string} path The path of the property to set.
57191                * @param {Function} updater The function to produce the updated value.
57192                * @param {Function} [customizer] The function to customize assigned values.
57193                * @returns {Object} Returns `object`.
57194                * @example
57195                *
57196                * var object = {};
57197                *
57198                * _.updateWith(object, '[0][1]', _.constant('a'), Object);
57199                * // => { '0': { '1': 'a' } }
57200                */
57201
57202
57203               function updateWith(object, path, updater, customizer) {
57204                 customizer = typeof customizer == 'function' ? customizer : undefined$1;
57205                 return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);
57206               }
57207               /**
57208                * Creates an array of the own enumerable string keyed property values of `object`.
57209                *
57210                * **Note:** Non-object values are coerced to objects.
57211                *
57212                * @static
57213                * @since 0.1.0
57214                * @memberOf _
57215                * @category Object
57216                * @param {Object} object The object to query.
57217                * @returns {Array} Returns the array of property values.
57218                * @example
57219                *
57220                * function Foo() {
57221                *   this.a = 1;
57222                *   this.b = 2;
57223                * }
57224                *
57225                * Foo.prototype.c = 3;
57226                *
57227                * _.values(new Foo);
57228                * // => [1, 2] (iteration order is not guaranteed)
57229                *
57230                * _.values('hi');
57231                * // => ['h', 'i']
57232                */
57233
57234
57235               function values(object) {
57236                 return object == null ? [] : baseValues(object, keys(object));
57237               }
57238               /**
57239                * Creates an array of the own and inherited enumerable string keyed property
57240                * values of `object`.
57241                *
57242                * **Note:** Non-object values are coerced to objects.
57243                *
57244                * @static
57245                * @memberOf _
57246                * @since 3.0.0
57247                * @category Object
57248                * @param {Object} object The object to query.
57249                * @returns {Array} Returns the array of property values.
57250                * @example
57251                *
57252                * function Foo() {
57253                *   this.a = 1;
57254                *   this.b = 2;
57255                * }
57256                *
57257                * Foo.prototype.c = 3;
57258                *
57259                * _.valuesIn(new Foo);
57260                * // => [1, 2, 3] (iteration order is not guaranteed)
57261                */
57262
57263
57264               function valuesIn(object) {
57265                 return object == null ? [] : baseValues(object, keysIn(object));
57266               }
57267               /*------------------------------------------------------------------------*/
57268
57269               /**
57270                * Clamps `number` within the inclusive `lower` and `upper` bounds.
57271                *
57272                * @static
57273                * @memberOf _
57274                * @since 4.0.0
57275                * @category Number
57276                * @param {number} number The number to clamp.
57277                * @param {number} [lower] The lower bound.
57278                * @param {number} upper The upper bound.
57279                * @returns {number} Returns the clamped number.
57280                * @example
57281                *
57282                * _.clamp(-10, -5, 5);
57283                * // => -5
57284                *
57285                * _.clamp(10, -5, 5);
57286                * // => 5
57287                */
57288
57289
57290               function clamp(number, lower, upper) {
57291                 if (upper === undefined$1) {
57292                   upper = lower;
57293                   lower = undefined$1;
57294                 }
57295
57296                 if (upper !== undefined$1) {
57297                   upper = toNumber(upper);
57298                   upper = upper === upper ? upper : 0;
57299                 }
57300
57301                 if (lower !== undefined$1) {
57302                   lower = toNumber(lower);
57303                   lower = lower === lower ? lower : 0;
57304                 }
57305
57306                 return baseClamp(toNumber(number), lower, upper);
57307               }
57308               /**
57309                * Checks if `n` is between `start` and up to, but not including, `end`. If
57310                * `end` is not specified, it's set to `start` with `start` then set to `0`.
57311                * If `start` is greater than `end` the params are swapped to support
57312                * negative ranges.
57313                *
57314                * @static
57315                * @memberOf _
57316                * @since 3.3.0
57317                * @category Number
57318                * @param {number} number The number to check.
57319                * @param {number} [start=0] The start of the range.
57320                * @param {number} end The end of the range.
57321                * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
57322                * @see _.range, _.rangeRight
57323                * @example
57324                *
57325                * _.inRange(3, 2, 4);
57326                * // => true
57327                *
57328                * _.inRange(4, 8);
57329                * // => true
57330                *
57331                * _.inRange(4, 2);
57332                * // => false
57333                *
57334                * _.inRange(2, 2);
57335                * // => false
57336                *
57337                * _.inRange(1.2, 2);
57338                * // => true
57339                *
57340                * _.inRange(5.2, 4);
57341                * // => false
57342                *
57343                * _.inRange(-3, -2, -6);
57344                * // => true
57345                */
57346
57347
57348               function inRange(number, start, end) {
57349                 start = toFinite(start);
57350
57351                 if (end === undefined$1) {
57352                   end = start;
57353                   start = 0;
57354                 } else {
57355                   end = toFinite(end);
57356                 }
57357
57358                 number = toNumber(number);
57359                 return baseInRange(number, start, end);
57360               }
57361               /**
57362                * Produces a random number between the inclusive `lower` and `upper` bounds.
57363                * If only one argument is provided a number between `0` and the given number
57364                * is returned. If `floating` is `true`, or either `lower` or `upper` are
57365                * floats, a floating-point number is returned instead of an integer.
57366                *
57367                * **Note:** JavaScript follows the IEEE-754 standard for resolving
57368                * floating-point values which can produce unexpected results.
57369                *
57370                * @static
57371                * @memberOf _
57372                * @since 0.7.0
57373                * @category Number
57374                * @param {number} [lower=0] The lower bound.
57375                * @param {number} [upper=1] The upper bound.
57376                * @param {boolean} [floating] Specify returning a floating-point number.
57377                * @returns {number} Returns the random number.
57378                * @example
57379                *
57380                * _.random(0, 5);
57381                * // => an integer between 0 and 5
57382                *
57383                * _.random(5);
57384                * // => also an integer between 0 and 5
57385                *
57386                * _.random(5, true);
57387                * // => a floating-point number between 0 and 5
57388                *
57389                * _.random(1.2, 5.2);
57390                * // => a floating-point number between 1.2 and 5.2
57391                */
57392
57393
57394               function random(lower, upper, floating) {
57395                 if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {
57396                   upper = floating = undefined$1;
57397                 }
57398
57399                 if (floating === undefined$1) {
57400                   if (typeof upper == 'boolean') {
57401                     floating = upper;
57402                     upper = undefined$1;
57403                   } else if (typeof lower == 'boolean') {
57404                     floating = lower;
57405                     lower = undefined$1;
57406                   }
57407                 }
57408
57409                 if (lower === undefined$1 && upper === undefined$1) {
57410                   lower = 0;
57411                   upper = 1;
57412                 } else {
57413                   lower = toFinite(lower);
57414
57415                   if (upper === undefined$1) {
57416                     upper = lower;
57417                     lower = 0;
57418                   } else {
57419                     upper = toFinite(upper);
57420                   }
57421                 }
57422
57423                 if (lower > upper) {
57424                   var temp = lower;
57425                   lower = upper;
57426                   upper = temp;
57427                 }
57428
57429                 if (floating || lower % 1 || upper % 1) {
57430                   var rand = nativeRandom();
57431                   return nativeMin(lower + rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1))), upper);
57432                 }
57433
57434                 return baseRandom(lower, upper);
57435               }
57436               /*------------------------------------------------------------------------*/
57437
57438               /**
57439                * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).
57440                *
57441                * @static
57442                * @memberOf _
57443                * @since 3.0.0
57444                * @category String
57445                * @param {string} [string=''] The string to convert.
57446                * @returns {string} Returns the camel cased string.
57447                * @example
57448                *
57449                * _.camelCase('Foo Bar');
57450                * // => 'fooBar'
57451                *
57452                * _.camelCase('--foo-bar--');
57453                * // => 'fooBar'
57454                *
57455                * _.camelCase('__FOO_BAR__');
57456                * // => 'fooBar'
57457                */
57458
57459
57460               var camelCase = createCompounder(function (result, word, index) {
57461                 word = word.toLowerCase();
57462                 return result + (index ? capitalize(word) : word);
57463               });
57464               /**
57465                * Converts the first character of `string` to upper case and the remaining
57466                * to lower case.
57467                *
57468                * @static
57469                * @memberOf _
57470                * @since 3.0.0
57471                * @category String
57472                * @param {string} [string=''] The string to capitalize.
57473                * @returns {string} Returns the capitalized string.
57474                * @example
57475                *
57476                * _.capitalize('FRED');
57477                * // => 'Fred'
57478                */
57479
57480               function capitalize(string) {
57481                 return upperFirst(toString(string).toLowerCase());
57482               }
57483               /**
57484                * Deburrs `string` by converting
57485                * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
57486                * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)
57487                * letters to basic Latin letters and removing
57488                * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
57489                *
57490                * @static
57491                * @memberOf _
57492                * @since 3.0.0
57493                * @category String
57494                * @param {string} [string=''] The string to deburr.
57495                * @returns {string} Returns the deburred string.
57496                * @example
57497                *
57498                * _.deburr('déjà vu');
57499                * // => 'deja vu'
57500                */
57501
57502
57503               function deburr(string) {
57504                 string = toString(string);
57505                 return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');
57506               }
57507               /**
57508                * Checks if `string` ends with the given target string.
57509                *
57510                * @static
57511                * @memberOf _
57512                * @since 3.0.0
57513                * @category String
57514                * @param {string} [string=''] The string to inspect.
57515                * @param {string} [target] The string to search for.
57516                * @param {number} [position=string.length] The position to search up to.
57517                * @returns {boolean} Returns `true` if `string` ends with `target`,
57518                *  else `false`.
57519                * @example
57520                *
57521                * _.endsWith('abc', 'c');
57522                * // => true
57523                *
57524                * _.endsWith('abc', 'b');
57525                * // => false
57526                *
57527                * _.endsWith('abc', 'b', 2);
57528                * // => true
57529                */
57530
57531
57532               function endsWith(string, target, position) {
57533                 string = toString(string);
57534                 target = baseToString(target);
57535                 var length = string.length;
57536                 position = position === undefined$1 ? length : baseClamp(toInteger(position), 0, length);
57537                 var end = position;
57538                 position -= target.length;
57539                 return position >= 0 && string.slice(position, end) == target;
57540               }
57541               /**
57542                * Converts the characters "&", "<", ">", '"', and "'" in `string` to their
57543                * corresponding HTML entities.
57544                *
57545                * **Note:** No other characters are escaped. To escape additional
57546                * characters use a third-party library like [_he_](https://mths.be/he).
57547                *
57548                * Though the ">" character is escaped for symmetry, characters like
57549                * ">" and "/" don't need escaping in HTML and have no special meaning
57550                * unless they're part of a tag or unquoted attribute value. See
57551                * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
57552                * (under "semi-related fun fact") for more details.
57553                *
57554                * When working with HTML you should always
57555                * [quote attribute values](http://wonko.com/post/html-escaping) to reduce
57556                * XSS vectors.
57557                *
57558                * @static
57559                * @since 0.1.0
57560                * @memberOf _
57561                * @category String
57562                * @param {string} [string=''] The string to escape.
57563                * @returns {string} Returns the escaped string.
57564                * @example
57565                *
57566                * _.escape('fred, barney, & pebbles');
57567                * // => 'fred, barney, &amp; pebbles'
57568                */
57569
57570
57571               function escape(string) {
57572                 string = toString(string);
57573                 return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string;
57574               }
57575               /**
57576                * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+",
57577                * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`.
57578                *
57579                * @static
57580                * @memberOf _
57581                * @since 3.0.0
57582                * @category String
57583                * @param {string} [string=''] The string to escape.
57584                * @returns {string} Returns the escaped string.
57585                * @example
57586                *
57587                * _.escapeRegExp('[lodash](https://lodash.com/)');
57588                * // => '\[lodash\]\(https://lodash\.com/\)'
57589                */
57590
57591
57592               function escapeRegExp(string) {
57593                 string = toString(string);
57594                 return string && reHasRegExpChar.test(string) ? string.replace(reRegExpChar, '\\$&') : string;
57595               }
57596               /**
57597                * Converts `string` to
57598                * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
57599                *
57600                * @static
57601                * @memberOf _
57602                * @since 3.0.0
57603                * @category String
57604                * @param {string} [string=''] The string to convert.
57605                * @returns {string} Returns the kebab cased string.
57606                * @example
57607                *
57608                * _.kebabCase('Foo Bar');
57609                * // => 'foo-bar'
57610                *
57611                * _.kebabCase('fooBar');
57612                * // => 'foo-bar'
57613                *
57614                * _.kebabCase('__FOO_BAR__');
57615                * // => 'foo-bar'
57616                */
57617
57618
57619               var kebabCase = createCompounder(function (result, word, index) {
57620                 return result + (index ? '-' : '') + word.toLowerCase();
57621               });
57622               /**
57623                * Converts `string`, as space separated words, to lower case.
57624                *
57625                * @static
57626                * @memberOf _
57627                * @since 4.0.0
57628                * @category String
57629                * @param {string} [string=''] The string to convert.
57630                * @returns {string} Returns the lower cased string.
57631                * @example
57632                *
57633                * _.lowerCase('--Foo-Bar--');
57634                * // => 'foo bar'
57635                *
57636                * _.lowerCase('fooBar');
57637                * // => 'foo bar'
57638                *
57639                * _.lowerCase('__FOO_BAR__');
57640                * // => 'foo bar'
57641                */
57642
57643               var lowerCase = createCompounder(function (result, word, index) {
57644                 return result + (index ? ' ' : '') + word.toLowerCase();
57645               });
57646               /**
57647                * Converts the first character of `string` to lower case.
57648                *
57649                * @static
57650                * @memberOf _
57651                * @since 4.0.0
57652                * @category String
57653                * @param {string} [string=''] The string to convert.
57654                * @returns {string} Returns the converted string.
57655                * @example
57656                *
57657                * _.lowerFirst('Fred');
57658                * // => 'fred'
57659                *
57660                * _.lowerFirst('FRED');
57661                * // => 'fRED'
57662                */
57663
57664               var lowerFirst = createCaseFirst('toLowerCase');
57665               /**
57666                * Pads `string` on the left and right sides if it's shorter than `length`.
57667                * Padding characters are truncated if they can't be evenly divided by `length`.
57668                *
57669                * @static
57670                * @memberOf _
57671                * @since 3.0.0
57672                * @category String
57673                * @param {string} [string=''] The string to pad.
57674                * @param {number} [length=0] The padding length.
57675                * @param {string} [chars=' '] The string used as padding.
57676                * @returns {string} Returns the padded string.
57677                * @example
57678                *
57679                * _.pad('abc', 8);
57680                * // => '  abc   '
57681                *
57682                * _.pad('abc', 8, '_-');
57683                * // => '_-abc_-_'
57684                *
57685                * _.pad('abc', 3);
57686                * // => 'abc'
57687                */
57688
57689               function pad(string, length, chars) {
57690                 string = toString(string);
57691                 length = toInteger(length);
57692                 var strLength = length ? stringSize(string) : 0;
57693
57694                 if (!length || strLength >= length) {
57695                   return string;
57696                 }
57697
57698                 var mid = (length - strLength) / 2;
57699                 return createPadding(nativeFloor(mid), chars) + string + createPadding(nativeCeil(mid), chars);
57700               }
57701               /**
57702                * Pads `string` on the right side if it's shorter than `length`. Padding
57703                * characters are truncated if they exceed `length`.
57704                *
57705                * @static
57706                * @memberOf _
57707                * @since 4.0.0
57708                * @category String
57709                * @param {string} [string=''] The string to pad.
57710                * @param {number} [length=0] The padding length.
57711                * @param {string} [chars=' '] The string used as padding.
57712                * @returns {string} Returns the padded string.
57713                * @example
57714                *
57715                * _.padEnd('abc', 6);
57716                * // => 'abc   '
57717                *
57718                * _.padEnd('abc', 6, '_-');
57719                * // => 'abc_-_'
57720                *
57721                * _.padEnd('abc', 3);
57722                * // => 'abc'
57723                */
57724
57725
57726               function padEnd(string, length, chars) {
57727                 string = toString(string);
57728                 length = toInteger(length);
57729                 var strLength = length ? stringSize(string) : 0;
57730                 return length && strLength < length ? string + createPadding(length - strLength, chars) : string;
57731               }
57732               /**
57733                * Pads `string` on the left side if it's shorter than `length`. Padding
57734                * characters are truncated if they exceed `length`.
57735                *
57736                * @static
57737                * @memberOf _
57738                * @since 4.0.0
57739                * @category String
57740                * @param {string} [string=''] The string to pad.
57741                * @param {number} [length=0] The padding length.
57742                * @param {string} [chars=' '] The string used as padding.
57743                * @returns {string} Returns the padded string.
57744                * @example
57745                *
57746                * _.padStart('abc', 6);
57747                * // => '   abc'
57748                *
57749                * _.padStart('abc', 6, '_-');
57750                * // => '_-_abc'
57751                *
57752                * _.padStart('abc', 3);
57753                * // => 'abc'
57754                */
57755
57756
57757               function padStart(string, length, chars) {
57758                 string = toString(string);
57759                 length = toInteger(length);
57760                 var strLength = length ? stringSize(string) : 0;
57761                 return length && strLength < length ? createPadding(length - strLength, chars) + string : string;
57762               }
57763               /**
57764                * Converts `string` to an integer of the specified radix. If `radix` is
57765                * `undefined` or `0`, a `radix` of `10` is used unless `value` is a
57766                * hexadecimal, in which case a `radix` of `16` is used.
57767                *
57768                * **Note:** This method aligns with the
57769                * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`.
57770                *
57771                * @static
57772                * @memberOf _
57773                * @since 1.1.0
57774                * @category String
57775                * @param {string} string The string to convert.
57776                * @param {number} [radix=10] The radix to interpret `value` by.
57777                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
57778                * @returns {number} Returns the converted integer.
57779                * @example
57780                *
57781                * _.parseInt('08');
57782                * // => 8
57783                *
57784                * _.map(['6', '08', '10'], _.parseInt);
57785                * // => [6, 8, 10]
57786                */
57787
57788
57789               function parseInt(string, radix, guard) {
57790                 if (guard || radix == null) {
57791                   radix = 0;
57792                 } else if (radix) {
57793                   radix = +radix;
57794                 }
57795
57796                 return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0);
57797               }
57798               /**
57799                * Repeats the given string `n` times.
57800                *
57801                * @static
57802                * @memberOf _
57803                * @since 3.0.0
57804                * @category String
57805                * @param {string} [string=''] The string to repeat.
57806                * @param {number} [n=1] The number of times to repeat the string.
57807                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
57808                * @returns {string} Returns the repeated string.
57809                * @example
57810                *
57811                * _.repeat('*', 3);
57812                * // => '***'
57813                *
57814                * _.repeat('abc', 2);
57815                * // => 'abcabc'
57816                *
57817                * _.repeat('abc', 0);
57818                * // => ''
57819                */
57820
57821
57822               function repeat(string, n, guard) {
57823                 if (guard ? isIterateeCall(string, n, guard) : n === undefined$1) {
57824                   n = 1;
57825                 } else {
57826                   n = toInteger(n);
57827                 }
57828
57829                 return baseRepeat(toString(string), n);
57830               }
57831               /**
57832                * Replaces matches for `pattern` in `string` with `replacement`.
57833                *
57834                * **Note:** This method is based on
57835                * [`String#replace`](https://mdn.io/String/replace).
57836                *
57837                * @static
57838                * @memberOf _
57839                * @since 4.0.0
57840                * @category String
57841                * @param {string} [string=''] The string to modify.
57842                * @param {RegExp|string} pattern The pattern to replace.
57843                * @param {Function|string} replacement The match replacement.
57844                * @returns {string} Returns the modified string.
57845                * @example
57846                *
57847                * _.replace('Hi Fred', 'Fred', 'Barney');
57848                * // => 'Hi Barney'
57849                */
57850
57851
57852               function replace() {
57853                 var args = arguments,
57854                     string = toString(args[0]);
57855                 return args.length < 3 ? string : string.replace(args[1], args[2]);
57856               }
57857               /**
57858                * Converts `string` to
57859                * [snake case](https://en.wikipedia.org/wiki/Snake_case).
57860                *
57861                * @static
57862                * @memberOf _
57863                * @since 3.0.0
57864                * @category String
57865                * @param {string} [string=''] The string to convert.
57866                * @returns {string} Returns the snake cased string.
57867                * @example
57868                *
57869                * _.snakeCase('Foo Bar');
57870                * // => 'foo_bar'
57871                *
57872                * _.snakeCase('fooBar');
57873                * // => 'foo_bar'
57874                *
57875                * _.snakeCase('--FOO-BAR--');
57876                * // => 'foo_bar'
57877                */
57878
57879
57880               var snakeCase = createCompounder(function (result, word, index) {
57881                 return result + (index ? '_' : '') + word.toLowerCase();
57882               });
57883               /**
57884                * Splits `string` by `separator`.
57885                *
57886                * **Note:** This method is based on
57887                * [`String#split`](https://mdn.io/String/split).
57888                *
57889                * @static
57890                * @memberOf _
57891                * @since 4.0.0
57892                * @category String
57893                * @param {string} [string=''] The string to split.
57894                * @param {RegExp|string} separator The separator pattern to split by.
57895                * @param {number} [limit] The length to truncate results to.
57896                * @returns {Array} Returns the string segments.
57897                * @example
57898                *
57899                * _.split('a-b-c', '-', 2);
57900                * // => ['a', 'b']
57901                */
57902
57903               function split(string, separator, limit) {
57904                 if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) {
57905                   separator = limit = undefined$1;
57906                 }
57907
57908                 limit = limit === undefined$1 ? MAX_ARRAY_LENGTH : limit >>> 0;
57909
57910                 if (!limit) {
57911                   return [];
57912                 }
57913
57914                 string = toString(string);
57915
57916                 if (string && (typeof separator == 'string' || separator != null && !isRegExp(separator))) {
57917                   separator = baseToString(separator);
57918
57919                   if (!separator && hasUnicode(string)) {
57920                     return castSlice(stringToArray(string), 0, limit);
57921                   }
57922                 }
57923
57924                 return string.split(separator, limit);
57925               }
57926               /**
57927                * Converts `string` to
57928                * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
57929                *
57930                * @static
57931                * @memberOf _
57932                * @since 3.1.0
57933                * @category String
57934                * @param {string} [string=''] The string to convert.
57935                * @returns {string} Returns the start cased string.
57936                * @example
57937                *
57938                * _.startCase('--foo-bar--');
57939                * // => 'Foo Bar'
57940                *
57941                * _.startCase('fooBar');
57942                * // => 'Foo Bar'
57943                *
57944                * _.startCase('__FOO_BAR__');
57945                * // => 'FOO BAR'
57946                */
57947
57948
57949               var startCase = createCompounder(function (result, word, index) {
57950                 return result + (index ? ' ' : '') + upperFirst(word);
57951               });
57952               /**
57953                * Checks if `string` starts with the given target string.
57954                *
57955                * @static
57956                * @memberOf _
57957                * @since 3.0.0
57958                * @category String
57959                * @param {string} [string=''] The string to inspect.
57960                * @param {string} [target] The string to search for.
57961                * @param {number} [position=0] The position to search from.
57962                * @returns {boolean} Returns `true` if `string` starts with `target`,
57963                *  else `false`.
57964                * @example
57965                *
57966                * _.startsWith('abc', 'a');
57967                * // => true
57968                *
57969                * _.startsWith('abc', 'b');
57970                * // => false
57971                *
57972                * _.startsWith('abc', 'b', 1);
57973                * // => true
57974                */
57975
57976               function startsWith(string, target, position) {
57977                 string = toString(string);
57978                 position = position == null ? 0 : baseClamp(toInteger(position), 0, string.length);
57979                 target = baseToString(target);
57980                 return string.slice(position, position + target.length) == target;
57981               }
57982               /**
57983                * Creates a compiled template function that can interpolate data properties
57984                * in "interpolate" delimiters, HTML-escape interpolated data properties in
57985                * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
57986                * properties may be accessed as free variables in the template. If a setting
57987                * object is given, it takes precedence over `_.templateSettings` values.
57988                *
57989                * **Note:** In the development build `_.template` utilizes
57990                * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
57991                * for easier debugging.
57992                *
57993                * For more information on precompiling templates see
57994                * [lodash's custom builds documentation](https://lodash.com/custom-builds).
57995                *
57996                * For more information on Chrome extension sandboxes see
57997                * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
57998                *
57999                * @static
58000                * @since 0.1.0
58001                * @memberOf _
58002                * @category String
58003                * @param {string} [string=''] The template string.
58004                * @param {Object} [options={}] The options object.
58005                * @param {RegExp} [options.escape=_.templateSettings.escape]
58006                *  The HTML "escape" delimiter.
58007                * @param {RegExp} [options.evaluate=_.templateSettings.evaluate]
58008                *  The "evaluate" delimiter.
58009                * @param {Object} [options.imports=_.templateSettings.imports]
58010                *  An object to import into the template as free variables.
58011                * @param {RegExp} [options.interpolate=_.templateSettings.interpolate]
58012                *  The "interpolate" delimiter.
58013                * @param {string} [options.sourceURL='lodash.templateSources[n]']
58014                *  The sourceURL of the compiled template.
58015                * @param {string} [options.variable='obj']
58016                *  The data object variable name.
58017                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
58018                * @returns {Function} Returns the compiled template function.
58019                * @example
58020                *
58021                * // Use the "interpolate" delimiter to create a compiled template.
58022                * var compiled = _.template('hello <%= user %>!');
58023                * compiled({ 'user': 'fred' });
58024                * // => 'hello fred!'
58025                *
58026                * // Use the HTML "escape" delimiter to escape data property values.
58027                * var compiled = _.template('<b><%- value %></b>');
58028                * compiled({ 'value': '<script>' });
58029                * // => '<b>&lt;script&gt;</b>'
58030                *
58031                * // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
58032                * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
58033                * compiled({ 'users': ['fred', 'barney'] });
58034                * // => '<li>fred</li><li>barney</li>'
58035                *
58036                * // Use the internal `print` function in "evaluate" delimiters.
58037                * var compiled = _.template('<% print("hello " + user); %>!');
58038                * compiled({ 'user': 'barney' });
58039                * // => 'hello barney!'
58040                *
58041                * // Use the ES template literal delimiter as an "interpolate" delimiter.
58042                * // Disable support by replacing the "interpolate" delimiter.
58043                * var compiled = _.template('hello ${ user }!');
58044                * compiled({ 'user': 'pebbles' });
58045                * // => 'hello pebbles!'
58046                *
58047                * // Use backslashes to treat delimiters as plain text.
58048                * var compiled = _.template('<%= "\\<%- value %\\>" %>');
58049                * compiled({ 'value': 'ignored' });
58050                * // => '<%- value %>'
58051                *
58052                * // Use the `imports` option to import `jQuery` as `jq`.
58053                * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
58054                * var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
58055                * compiled({ 'users': ['fred', 'barney'] });
58056                * // => '<li>fred</li><li>barney</li>'
58057                *
58058                * // Use the `sourceURL` option to specify a custom sourceURL for the template.
58059                * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
58060                * compiled(data);
58061                * // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector.
58062                *
58063                * // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
58064                * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
58065                * compiled.source;
58066                * // => function(data) {
58067                * //   var __t, __p = '';
58068                * //   __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
58069                * //   return __p;
58070                * // }
58071                *
58072                * // Use custom template delimiters.
58073                * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
58074                * var compiled = _.template('hello {{ user }}!');
58075                * compiled({ 'user': 'mustache' });
58076                * // => 'hello mustache!'
58077                *
58078                * // Use the `source` property to inline compiled templates for meaningful
58079                * // line numbers in error messages and stack traces.
58080                * fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\
58081                *   var JST = {\
58082                *     "main": ' + _.template(mainText).source + '\
58083                *   };\
58084                * ');
58085                */
58086
58087
58088               function template(string, options, guard) {
58089                 // Based on John Resig's `tmpl` implementation
58090                 // (http://ejohn.org/blog/javascript-micro-templating/)
58091                 // and Laura Doktorova's doT.js (https://github.com/olado/doT).
58092                 var settings = lodash.templateSettings;
58093
58094                 if (guard && isIterateeCall(string, options, guard)) {
58095                   options = undefined$1;
58096                 }
58097
58098                 string = toString(string);
58099                 options = assignInWith({}, options, settings, customDefaultsAssignIn);
58100                 var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn),
58101                     importsKeys = keys(imports),
58102                     importsValues = baseValues(imports, importsKeys);
58103                 var isEscaping,
58104                     isEvaluating,
58105                     index = 0,
58106                     interpolate = options.interpolate || reNoMatch,
58107                     source = "__p += '"; // Compile the regexp to match each delimiter.
58108
58109                 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.
58110                 // The sourceURL gets injected into the source that's eval-ed, so be careful
58111                 // to normalize all kinds of whitespace, so e.g. newlines (and unicode versions of it) can't sneak in
58112                 // and escape the comment, thus injecting code that gets evaled.
58113
58114                 var sourceURL = '//# sourceURL=' + (hasOwnProperty.call(options, 'sourceURL') ? (options.sourceURL + '').replace(/\s/g, ' ') : 'lodash.templateSources[' + ++templateCounter + ']') + '\n';
58115                 string.replace(reDelimiters, function (match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
58116                   interpolateValue || (interpolateValue = esTemplateValue); // Escape characters that can't be included in string literals.
58117
58118                   source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); // Replace delimiters with snippets.
58119
58120                   if (escapeValue) {
58121                     isEscaping = true;
58122                     source += "' +\n__e(" + escapeValue + ") +\n'";
58123                   }
58124
58125                   if (evaluateValue) {
58126                     isEvaluating = true;
58127                     source += "';\n" + evaluateValue + ";\n__p += '";
58128                   }
58129
58130                   if (interpolateValue) {
58131                     source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
58132                   }
58133
58134                   index = offset + match.length; // The JS engine embedded in Adobe products needs `match` returned in
58135                   // order to produce the correct `offset` value.
58136
58137                   return match;
58138                 });
58139                 source += "';\n"; // If `variable` is not specified wrap a with-statement around the generated
58140                 // code to add the data object to the top of the scope chain.
58141
58142                 var variable = hasOwnProperty.call(options, 'variable') && options.variable;
58143
58144                 if (!variable) {
58145                   source = 'with (obj) {\n' + source + '\n}\n';
58146                 } // Throw an error if a forbidden character was found in `variable`, to prevent
58147                 // potential command injection attacks.
58148                 else if (reForbiddenIdentifierChars.test(variable)) {
58149                   throw new Error(INVALID_TEMPL_VAR_ERROR_TEXT);
58150                 } // Cleanup code by stripping empty strings.
58151
58152
58153                 source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source).replace(reEmptyStringMiddle, '$1').replace(reEmptyStringTrailing, '$1;'); // Frame code as the function body.
58154
58155                 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}';
58156                 var result = attempt(function () {
58157                   return Function(importsKeys, sourceURL + 'return ' + source).apply(undefined$1, importsValues);
58158                 }); // Provide the compiled function's source by its `toString` method or
58159                 // the `source` property as a convenience for inlining compiled templates.
58160
58161                 result.source = source;
58162
58163                 if (isError(result)) {
58164                   throw result;
58165                 }
58166
58167                 return result;
58168               }
58169               /**
58170                * Converts `string`, as a whole, to lower case just like
58171                * [String#toLowerCase](https://mdn.io/toLowerCase).
58172                *
58173                * @static
58174                * @memberOf _
58175                * @since 4.0.0
58176                * @category String
58177                * @param {string} [string=''] The string to convert.
58178                * @returns {string} Returns the lower cased string.
58179                * @example
58180                *
58181                * _.toLower('--Foo-Bar--');
58182                * // => '--foo-bar--'
58183                *
58184                * _.toLower('fooBar');
58185                * // => 'foobar'
58186                *
58187                * _.toLower('__FOO_BAR__');
58188                * // => '__foo_bar__'
58189                */
58190
58191
58192               function toLower(value) {
58193                 return toString(value).toLowerCase();
58194               }
58195               /**
58196                * Converts `string`, as a whole, to upper case just like
58197                * [String#toUpperCase](https://mdn.io/toUpperCase).
58198                *
58199                * @static
58200                * @memberOf _
58201                * @since 4.0.0
58202                * @category String
58203                * @param {string} [string=''] The string to convert.
58204                * @returns {string} Returns the upper cased string.
58205                * @example
58206                *
58207                * _.toUpper('--foo-bar--');
58208                * // => '--FOO-BAR--'
58209                *
58210                * _.toUpper('fooBar');
58211                * // => 'FOOBAR'
58212                *
58213                * _.toUpper('__foo_bar__');
58214                * // => '__FOO_BAR__'
58215                */
58216
58217
58218               function toUpper(value) {
58219                 return toString(value).toUpperCase();
58220               }
58221               /**
58222                * Removes leading and trailing whitespace or specified characters from `string`.
58223                *
58224                * @static
58225                * @memberOf _
58226                * @since 3.0.0
58227                * @category String
58228                * @param {string} [string=''] The string to trim.
58229                * @param {string} [chars=whitespace] The characters to trim.
58230                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
58231                * @returns {string} Returns the trimmed string.
58232                * @example
58233                *
58234                * _.trim('  abc  ');
58235                * // => 'abc'
58236                *
58237                * _.trim('-_-abc-_-', '_-');
58238                * // => 'abc'
58239                *
58240                * _.map(['  foo  ', '  bar  '], _.trim);
58241                * // => ['foo', 'bar']
58242                */
58243
58244
58245               function trim(string, chars, guard) {
58246                 string = toString(string);
58247
58248                 if (string && (guard || chars === undefined$1)) {
58249                   return baseTrim(string);
58250                 }
58251
58252                 if (!string || !(chars = baseToString(chars))) {
58253                   return string;
58254                 }
58255
58256                 var strSymbols = stringToArray(string),
58257                     chrSymbols = stringToArray(chars),
58258                     start = charsStartIndex(strSymbols, chrSymbols),
58259                     end = charsEndIndex(strSymbols, chrSymbols) + 1;
58260                 return castSlice(strSymbols, start, end).join('');
58261               }
58262               /**
58263                * Removes trailing whitespace or specified characters from `string`.
58264                *
58265                * @static
58266                * @memberOf _
58267                * @since 4.0.0
58268                * @category String
58269                * @param {string} [string=''] The string to trim.
58270                * @param {string} [chars=whitespace] The characters to trim.
58271                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
58272                * @returns {string} Returns the trimmed string.
58273                * @example
58274                *
58275                * _.trimEnd('  abc  ');
58276                * // => '  abc'
58277                *
58278                * _.trimEnd('-_-abc-_-', '_-');
58279                * // => '-_-abc'
58280                */
58281
58282
58283               function trimEnd(string, chars, guard) {
58284                 string = toString(string);
58285
58286                 if (string && (guard || chars === undefined$1)) {
58287                   return string.slice(0, trimmedEndIndex(string) + 1);
58288                 }
58289
58290                 if (!string || !(chars = baseToString(chars))) {
58291                   return string;
58292                 }
58293
58294                 var strSymbols = stringToArray(string),
58295                     end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;
58296                 return castSlice(strSymbols, 0, end).join('');
58297               }
58298               /**
58299                * Removes leading whitespace or specified characters from `string`.
58300                *
58301                * @static
58302                * @memberOf _
58303                * @since 4.0.0
58304                * @category String
58305                * @param {string} [string=''] The string to trim.
58306                * @param {string} [chars=whitespace] The characters to trim.
58307                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
58308                * @returns {string} Returns the trimmed string.
58309                * @example
58310                *
58311                * _.trimStart('  abc  ');
58312                * // => 'abc  '
58313                *
58314                * _.trimStart('-_-abc-_-', '_-');
58315                * // => 'abc-_-'
58316                */
58317
58318
58319               function trimStart(string, chars, guard) {
58320                 string = toString(string);
58321
58322                 if (string && (guard || chars === undefined$1)) {
58323                   return string.replace(reTrimStart, '');
58324                 }
58325
58326                 if (!string || !(chars = baseToString(chars))) {
58327                   return string;
58328                 }
58329
58330                 var strSymbols = stringToArray(string),
58331                     start = charsStartIndex(strSymbols, stringToArray(chars));
58332                 return castSlice(strSymbols, start).join('');
58333               }
58334               /**
58335                * Truncates `string` if it's longer than the given maximum string length.
58336                * The last characters of the truncated string are replaced with the omission
58337                * string which defaults to "...".
58338                *
58339                * @static
58340                * @memberOf _
58341                * @since 4.0.0
58342                * @category String
58343                * @param {string} [string=''] The string to truncate.
58344                * @param {Object} [options={}] The options object.
58345                * @param {number} [options.length=30] The maximum string length.
58346                * @param {string} [options.omission='...'] The string to indicate text is omitted.
58347                * @param {RegExp|string} [options.separator] The separator pattern to truncate to.
58348                * @returns {string} Returns the truncated string.
58349                * @example
58350                *
58351                * _.truncate('hi-diddly-ho there, neighborino');
58352                * // => 'hi-diddly-ho there, neighbo...'
58353                *
58354                * _.truncate('hi-diddly-ho there, neighborino', {
58355                *   'length': 24,
58356                *   'separator': ' '
58357                * });
58358                * // => 'hi-diddly-ho there,...'
58359                *
58360                * _.truncate('hi-diddly-ho there, neighborino', {
58361                *   'length': 24,
58362                *   'separator': /,? +/
58363                * });
58364                * // => 'hi-diddly-ho there...'
58365                *
58366                * _.truncate('hi-diddly-ho there, neighborino', {
58367                *   'omission': ' [...]'
58368                * });
58369                * // => 'hi-diddly-ho there, neig [...]'
58370                */
58371
58372
58373               function truncate(string, options) {
58374                 var length = DEFAULT_TRUNC_LENGTH,
58375                     omission = DEFAULT_TRUNC_OMISSION;
58376
58377                 if (isObject(options)) {
58378                   var separator = 'separator' in options ? options.separator : separator;
58379                   length = 'length' in options ? toInteger(options.length) : length;
58380                   omission = 'omission' in options ? baseToString(options.omission) : omission;
58381                 }
58382
58383                 string = toString(string);
58384                 var strLength = string.length;
58385
58386                 if (hasUnicode(string)) {
58387                   var strSymbols = stringToArray(string);
58388                   strLength = strSymbols.length;
58389                 }
58390
58391                 if (length >= strLength) {
58392                   return string;
58393                 }
58394
58395                 var end = length - stringSize(omission);
58396
58397                 if (end < 1) {
58398                   return omission;
58399                 }
58400
58401                 var result = strSymbols ? castSlice(strSymbols, 0, end).join('') : string.slice(0, end);
58402
58403                 if (separator === undefined$1) {
58404                   return result + omission;
58405                 }
58406
58407                 if (strSymbols) {
58408                   end += result.length - end;
58409                 }
58410
58411                 if (isRegExp(separator)) {
58412                   if (string.slice(end).search(separator)) {
58413                     var match,
58414                         substring = result;
58415
58416                     if (!separator.global) {
58417                       separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');
58418                     }
58419
58420                     separator.lastIndex = 0;
58421
58422                     while (match = separator.exec(substring)) {
58423                       var newEnd = match.index;
58424                     }
58425
58426                     result = result.slice(0, newEnd === undefined$1 ? end : newEnd);
58427                   }
58428                 } else if (string.indexOf(baseToString(separator), end) != end) {
58429                   var index = result.lastIndexOf(separator);
58430
58431                   if (index > -1) {
58432                     result = result.slice(0, index);
58433                   }
58434                 }
58435
58436                 return result + omission;
58437               }
58438               /**
58439                * The inverse of `_.escape`; this method converts the HTML entities
58440                * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to
58441                * their corresponding characters.
58442                *
58443                * **Note:** No other HTML entities are unescaped. To unescape additional
58444                * HTML entities use a third-party library like [_he_](https://mths.be/he).
58445                *
58446                * @static
58447                * @memberOf _
58448                * @since 0.6.0
58449                * @category String
58450                * @param {string} [string=''] The string to unescape.
58451                * @returns {string} Returns the unescaped string.
58452                * @example
58453                *
58454                * _.unescape('fred, barney, &amp; pebbles');
58455                * // => 'fred, barney, & pebbles'
58456                */
58457
58458
58459               function unescape(string) {
58460                 string = toString(string);
58461                 return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string;
58462               }
58463               /**
58464                * Converts `string`, as space separated words, to upper case.
58465                *
58466                * @static
58467                * @memberOf _
58468                * @since 4.0.0
58469                * @category String
58470                * @param {string} [string=''] The string to convert.
58471                * @returns {string} Returns the upper cased string.
58472                * @example
58473                *
58474                * _.upperCase('--foo-bar');
58475                * // => 'FOO BAR'
58476                *
58477                * _.upperCase('fooBar');
58478                * // => 'FOO BAR'
58479                *
58480                * _.upperCase('__foo_bar__');
58481                * // => 'FOO BAR'
58482                */
58483
58484
58485               var upperCase = createCompounder(function (result, word, index) {
58486                 return result + (index ? ' ' : '') + word.toUpperCase();
58487               });
58488               /**
58489                * Converts the first character of `string` to upper case.
58490                *
58491                * @static
58492                * @memberOf _
58493                * @since 4.0.0
58494                * @category String
58495                * @param {string} [string=''] The string to convert.
58496                * @returns {string} Returns the converted string.
58497                * @example
58498                *
58499                * _.upperFirst('fred');
58500                * // => 'Fred'
58501                *
58502                * _.upperFirst('FRED');
58503                * // => 'FRED'
58504                */
58505
58506               var upperFirst = createCaseFirst('toUpperCase');
58507               /**
58508                * Splits `string` into an array of its words.
58509                *
58510                * @static
58511                * @memberOf _
58512                * @since 3.0.0
58513                * @category String
58514                * @param {string} [string=''] The string to inspect.
58515                * @param {RegExp|string} [pattern] The pattern to match words.
58516                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
58517                * @returns {Array} Returns the words of `string`.
58518                * @example
58519                *
58520                * _.words('fred, barney, & pebbles');
58521                * // => ['fred', 'barney', 'pebbles']
58522                *
58523                * _.words('fred, barney, & pebbles', /[^, ]+/g);
58524                * // => ['fred', 'barney', '&', 'pebbles']
58525                */
58526
58527               function words(string, pattern, guard) {
58528                 string = toString(string);
58529                 pattern = guard ? undefined$1 : pattern;
58530
58531                 if (pattern === undefined$1) {
58532                   return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
58533                 }
58534
58535                 return string.match(pattern) || [];
58536               }
58537               /*------------------------------------------------------------------------*/
58538
58539               /**
58540                * Attempts to invoke `func`, returning either the result or the caught error
58541                * object. Any additional arguments are provided to `func` when it's invoked.
58542                *
58543                * @static
58544                * @memberOf _
58545                * @since 3.0.0
58546                * @category Util
58547                * @param {Function} func The function to attempt.
58548                * @param {...*} [args] The arguments to invoke `func` with.
58549                * @returns {*} Returns the `func` result or error object.
58550                * @example
58551                *
58552                * // Avoid throwing errors for invalid selectors.
58553                * var elements = _.attempt(function(selector) {
58554                *   return document.querySelectorAll(selector);
58555                * }, '>_>');
58556                *
58557                * if (_.isError(elements)) {
58558                *   elements = [];
58559                * }
58560                */
58561
58562
58563               var attempt = baseRest(function (func, args) {
58564                 try {
58565                   return apply(func, undefined$1, args);
58566                 } catch (e) {
58567                   return isError(e) ? e : new Error(e);
58568                 }
58569               });
58570               /**
58571                * Binds methods of an object to the object itself, overwriting the existing
58572                * method.
58573                *
58574                * **Note:** This method doesn't set the "length" property of bound functions.
58575                *
58576                * @static
58577                * @since 0.1.0
58578                * @memberOf _
58579                * @category Util
58580                * @param {Object} object The object to bind and assign the bound methods to.
58581                * @param {...(string|string[])} methodNames The object method names to bind.
58582                * @returns {Object} Returns `object`.
58583                * @example
58584                *
58585                * var view = {
58586                *   'label': 'docs',
58587                *   'click': function() {
58588                *     console.log('clicked ' + this.label);
58589                *   }
58590                * };
58591                *
58592                * _.bindAll(view, ['click']);
58593                * jQuery(element).on('click', view.click);
58594                * // => Logs 'clicked docs' when clicked.
58595                */
58596
58597               var bindAll = flatRest(function (object, methodNames) {
58598                 arrayEach(methodNames, function (key) {
58599                   key = toKey(key);
58600                   baseAssignValue(object, key, bind(object[key], object));
58601                 });
58602                 return object;
58603               });
58604               /**
58605                * Creates a function that iterates over `pairs` and invokes the corresponding
58606                * function of the first predicate to return truthy. The predicate-function
58607                * pairs are invoked with the `this` binding and arguments of the created
58608                * function.
58609                *
58610                * @static
58611                * @memberOf _
58612                * @since 4.0.0
58613                * @category Util
58614                * @param {Array} pairs The predicate-function pairs.
58615                * @returns {Function} Returns the new composite function.
58616                * @example
58617                *
58618                * var func = _.cond([
58619                *   [_.matches({ 'a': 1 }),           _.constant('matches A')],
58620                *   [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],
58621                *   [_.stubTrue,                      _.constant('no match')]
58622                * ]);
58623                *
58624                * func({ 'a': 1, 'b': 2 });
58625                * // => 'matches A'
58626                *
58627                * func({ 'a': 0, 'b': 1 });
58628                * // => 'matches B'
58629                *
58630                * func({ 'a': '1', 'b': '2' });
58631                * // => 'no match'
58632                */
58633
58634               function cond(pairs) {
58635                 var length = pairs == null ? 0 : pairs.length,
58636                     toIteratee = getIteratee();
58637                 pairs = !length ? [] : arrayMap(pairs, function (pair) {
58638                   if (typeof pair[1] != 'function') {
58639                     throw new TypeError(FUNC_ERROR_TEXT);
58640                   }
58641
58642                   return [toIteratee(pair[0]), pair[1]];
58643                 });
58644                 return baseRest(function (args) {
58645                   var index = -1;
58646
58647                   while (++index < length) {
58648                     var pair = pairs[index];
58649
58650                     if (apply(pair[0], this, args)) {
58651                       return apply(pair[1], this, args);
58652                     }
58653                   }
58654                 });
58655               }
58656               /**
58657                * Creates a function that invokes the predicate properties of `source` with
58658                * the corresponding property values of a given object, returning `true` if
58659                * all predicates return truthy, else `false`.
58660                *
58661                * **Note:** The created function is equivalent to `_.conformsTo` with
58662                * `source` partially applied.
58663                *
58664                * @static
58665                * @memberOf _
58666                * @since 4.0.0
58667                * @category Util
58668                * @param {Object} source The object of property predicates to conform to.
58669                * @returns {Function} Returns the new spec function.
58670                * @example
58671                *
58672                * var objects = [
58673                *   { 'a': 2, 'b': 1 },
58674                *   { 'a': 1, 'b': 2 }
58675                * ];
58676                *
58677                * _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } }));
58678                * // => [{ 'a': 1, 'b': 2 }]
58679                */
58680
58681
58682               function conforms(source) {
58683                 return baseConforms(baseClone(source, CLONE_DEEP_FLAG));
58684               }
58685               /**
58686                * Creates a function that returns `value`.
58687                *
58688                * @static
58689                * @memberOf _
58690                * @since 2.4.0
58691                * @category Util
58692                * @param {*} value The value to return from the new function.
58693                * @returns {Function} Returns the new constant function.
58694                * @example
58695                *
58696                * var objects = _.times(2, _.constant({ 'a': 1 }));
58697                *
58698                * console.log(objects);
58699                * // => [{ 'a': 1 }, { 'a': 1 }]
58700                *
58701                * console.log(objects[0] === objects[1]);
58702                * // => true
58703                */
58704
58705
58706               function constant(value) {
58707                 return function () {
58708                   return value;
58709                 };
58710               }
58711               /**
58712                * Checks `value` to determine whether a default value should be returned in
58713                * its place. The `defaultValue` is returned if `value` is `NaN`, `null`,
58714                * or `undefined`.
58715                *
58716                * @static
58717                * @memberOf _
58718                * @since 4.14.0
58719                * @category Util
58720                * @param {*} value The value to check.
58721                * @param {*} defaultValue The default value.
58722                * @returns {*} Returns the resolved value.
58723                * @example
58724                *
58725                * _.defaultTo(1, 10);
58726                * // => 1
58727                *
58728                * _.defaultTo(undefined, 10);
58729                * // => 10
58730                */
58731
58732
58733               function defaultTo(value, defaultValue) {
58734                 return value == null || value !== value ? defaultValue : value;
58735               }
58736               /**
58737                * Creates a function that returns the result of invoking the given functions
58738                * with the `this` binding of the created function, where each successive
58739                * invocation is supplied the return value of the previous.
58740                *
58741                * @static
58742                * @memberOf _
58743                * @since 3.0.0
58744                * @category Util
58745                * @param {...(Function|Function[])} [funcs] The functions to invoke.
58746                * @returns {Function} Returns the new composite function.
58747                * @see _.flowRight
58748                * @example
58749                *
58750                * function square(n) {
58751                *   return n * n;
58752                * }
58753                *
58754                * var addSquare = _.flow([_.add, square]);
58755                * addSquare(1, 2);
58756                * // => 9
58757                */
58758
58759
58760               var flow = createFlow();
58761               /**
58762                * This method is like `_.flow` except that it creates a function that
58763                * invokes the given functions from right to left.
58764                *
58765                * @static
58766                * @since 3.0.0
58767                * @memberOf _
58768                * @category Util
58769                * @param {...(Function|Function[])} [funcs] The functions to invoke.
58770                * @returns {Function} Returns the new composite function.
58771                * @see _.flow
58772                * @example
58773                *
58774                * function square(n) {
58775                *   return n * n;
58776                * }
58777                *
58778                * var addSquare = _.flowRight([square, _.add]);
58779                * addSquare(1, 2);
58780                * // => 9
58781                */
58782
58783               var flowRight = createFlow(true);
58784               /**
58785                * This method returns the first argument it receives.
58786                *
58787                * @static
58788                * @since 0.1.0
58789                * @memberOf _
58790                * @category Util
58791                * @param {*} value Any value.
58792                * @returns {*} Returns `value`.
58793                * @example
58794                *
58795                * var object = { 'a': 1 };
58796                *
58797                * console.log(_.identity(object) === object);
58798                * // => true
58799                */
58800
58801               function identity(value) {
58802                 return value;
58803               }
58804               /**
58805                * Creates a function that invokes `func` with the arguments of the created
58806                * function. If `func` is a property name, the created function returns the
58807                * property value for a given element. If `func` is an array or object, the
58808                * created function returns `true` for elements that contain the equivalent
58809                * source properties, otherwise it returns `false`.
58810                *
58811                * @static
58812                * @since 4.0.0
58813                * @memberOf _
58814                * @category Util
58815                * @param {*} [func=_.identity] The value to convert to a callback.
58816                * @returns {Function} Returns the callback.
58817                * @example
58818                *
58819                * var users = [
58820                *   { 'user': 'barney', 'age': 36, 'active': true },
58821                *   { 'user': 'fred',   'age': 40, 'active': false }
58822                * ];
58823                *
58824                * // The `_.matches` iteratee shorthand.
58825                * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));
58826                * // => [{ 'user': 'barney', 'age': 36, 'active': true }]
58827                *
58828                * // The `_.matchesProperty` iteratee shorthand.
58829                * _.filter(users, _.iteratee(['user', 'fred']));
58830                * // => [{ 'user': 'fred', 'age': 40 }]
58831                *
58832                * // The `_.property` iteratee shorthand.
58833                * _.map(users, _.iteratee('user'));
58834                * // => ['barney', 'fred']
58835                *
58836                * // Create custom iteratee shorthands.
58837                * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {
58838                *   return !_.isRegExp(func) ? iteratee(func) : function(string) {
58839                *     return func.test(string);
58840                *   };
58841                * });
58842                *
58843                * _.filter(['abc', 'def'], /ef/);
58844                * // => ['def']
58845                */
58846
58847
58848               function iteratee(func) {
58849                 return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG));
58850               }
58851               /**
58852                * Creates a function that performs a partial deep comparison between a given
58853                * object and `source`, returning `true` if the given object has equivalent
58854                * property values, else `false`.
58855                *
58856                * **Note:** The created function is equivalent to `_.isMatch` with `source`
58857                * partially applied.
58858                *
58859                * Partial comparisons will match empty array and empty object `source`
58860                * values against any array or object value, respectively. See `_.isEqual`
58861                * for a list of supported value comparisons.
58862                *
58863                * **Note:** Multiple values can be checked by combining several matchers
58864                * using `_.overSome`
58865                *
58866                * @static
58867                * @memberOf _
58868                * @since 3.0.0
58869                * @category Util
58870                * @param {Object} source The object of property values to match.
58871                * @returns {Function} Returns the new spec function.
58872                * @example
58873                *
58874                * var objects = [
58875                *   { 'a': 1, 'b': 2, 'c': 3 },
58876                *   { 'a': 4, 'b': 5, 'c': 6 }
58877                * ];
58878                *
58879                * _.filter(objects, _.matches({ 'a': 4, 'c': 6 }));
58880                * // => [{ 'a': 4, 'b': 5, 'c': 6 }]
58881                *
58882                * // Checking for several possible values
58883                * _.filter(objects, _.overSome([_.matches({ 'a': 1 }), _.matches({ 'a': 4 })]));
58884                * // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }]
58885                */
58886
58887
58888               function matches(source) {
58889                 return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
58890               }
58891               /**
58892                * Creates a function that performs a partial deep comparison between the
58893                * value at `path` of a given object to `srcValue`, returning `true` if the
58894                * object value is equivalent, else `false`.
58895                *
58896                * **Note:** Partial comparisons will match empty array and empty object
58897                * `srcValue` values against any array or object value, respectively. See
58898                * `_.isEqual` for a list of supported value comparisons.
58899                *
58900                * **Note:** Multiple values can be checked by combining several matchers
58901                * using `_.overSome`
58902                *
58903                * @static
58904                * @memberOf _
58905                * @since 3.2.0
58906                * @category Util
58907                * @param {Array|string} path The path of the property to get.
58908                * @param {*} srcValue The value to match.
58909                * @returns {Function} Returns the new spec function.
58910                * @example
58911                *
58912                * var objects = [
58913                *   { 'a': 1, 'b': 2, 'c': 3 },
58914                *   { 'a': 4, 'b': 5, 'c': 6 }
58915                * ];
58916                *
58917                * _.find(objects, _.matchesProperty('a', 4));
58918                * // => { 'a': 4, 'b': 5, 'c': 6 }
58919                *
58920                * // Checking for several possible values
58921                * _.filter(objects, _.overSome([_.matchesProperty('a', 1), _.matchesProperty('a', 4)]));
58922                * // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }]
58923                */
58924
58925
58926               function matchesProperty(path, srcValue) {
58927                 return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));
58928               }
58929               /**
58930                * Creates a function that invokes the method at `path` of a given object.
58931                * Any additional arguments are provided to the invoked method.
58932                *
58933                * @static
58934                * @memberOf _
58935                * @since 3.7.0
58936                * @category Util
58937                * @param {Array|string} path The path of the method to invoke.
58938                * @param {...*} [args] The arguments to invoke the method with.
58939                * @returns {Function} Returns the new invoker function.
58940                * @example
58941                *
58942                * var objects = [
58943                *   { 'a': { 'b': _.constant(2) } },
58944                *   { 'a': { 'b': _.constant(1) } }
58945                * ];
58946                *
58947                * _.map(objects, _.method('a.b'));
58948                * // => [2, 1]
58949                *
58950                * _.map(objects, _.method(['a', 'b']));
58951                * // => [2, 1]
58952                */
58953
58954
58955               var method = baseRest(function (path, args) {
58956                 return function (object) {
58957                   return baseInvoke(object, path, args);
58958                 };
58959               });
58960               /**
58961                * The opposite of `_.method`; this method creates a function that invokes
58962                * the method at a given path of `object`. Any additional arguments are
58963                * provided to the invoked method.
58964                *
58965                * @static
58966                * @memberOf _
58967                * @since 3.7.0
58968                * @category Util
58969                * @param {Object} object The object to query.
58970                * @param {...*} [args] The arguments to invoke the method with.
58971                * @returns {Function} Returns the new invoker function.
58972                * @example
58973                *
58974                * var array = _.times(3, _.constant),
58975                *     object = { 'a': array, 'b': array, 'c': array };
58976                *
58977                * _.map(['a[2]', 'c[0]'], _.methodOf(object));
58978                * // => [2, 0]
58979                *
58980                * _.map([['a', '2'], ['c', '0']], _.methodOf(object));
58981                * // => [2, 0]
58982                */
58983
58984               var methodOf = baseRest(function (object, args) {
58985                 return function (path) {
58986                   return baseInvoke(object, path, args);
58987                 };
58988               });
58989               /**
58990                * Adds all own enumerable string keyed function properties of a source
58991                * object to the destination object. If `object` is a function, then methods
58992                * are added to its prototype as well.
58993                *
58994                * **Note:** Use `_.runInContext` to create a pristine `lodash` function to
58995                * avoid conflicts caused by modifying the original.
58996                *
58997                * @static
58998                * @since 0.1.0
58999                * @memberOf _
59000                * @category Util
59001                * @param {Function|Object} [object=lodash] The destination object.
59002                * @param {Object} source The object of functions to add.
59003                * @param {Object} [options={}] The options object.
59004                * @param {boolean} [options.chain=true] Specify whether mixins are chainable.
59005                * @returns {Function|Object} Returns `object`.
59006                * @example
59007                *
59008                * function vowels(string) {
59009                *   return _.filter(string, function(v) {
59010                *     return /[aeiou]/i.test(v);
59011                *   });
59012                * }
59013                *
59014                * _.mixin({ 'vowels': vowels });
59015                * _.vowels('fred');
59016                * // => ['e']
59017                *
59018                * _('fred').vowels().value();
59019                * // => ['e']
59020                *
59021                * _.mixin({ 'vowels': vowels }, { 'chain': false });
59022                * _('fred').vowels();
59023                * // => ['e']
59024                */
59025
59026               function mixin(object, source, options) {
59027                 var props = keys(source),
59028                     methodNames = baseFunctions(source, props);
59029
59030                 if (options == null && !(isObject(source) && (methodNames.length || !props.length))) {
59031                   options = source;
59032                   source = object;
59033                   object = this;
59034                   methodNames = baseFunctions(source, keys(source));
59035                 }
59036
59037                 var chain = !(isObject(options) && 'chain' in options) || !!options.chain,
59038                     isFunc = isFunction(object);
59039                 arrayEach(methodNames, function (methodName) {
59040                   var func = source[methodName];
59041                   object[methodName] = func;
59042
59043                   if (isFunc) {
59044                     object.prototype[methodName] = function () {
59045                       var chainAll = this.__chain__;
59046
59047                       if (chain || chainAll) {
59048                         var result = object(this.__wrapped__),
59049                             actions = result.__actions__ = copyArray(this.__actions__);
59050                         actions.push({
59051                           'func': func,
59052                           'args': arguments,
59053                           'thisArg': object
59054                         });
59055                         result.__chain__ = chainAll;
59056                         return result;
59057                       }
59058
59059                       return func.apply(object, arrayPush([this.value()], arguments));
59060                     };
59061                   }
59062                 });
59063                 return object;
59064               }
59065               /**
59066                * Reverts the `_` variable to its previous value and returns a reference to
59067                * the `lodash` function.
59068                *
59069                * @static
59070                * @since 0.1.0
59071                * @memberOf _
59072                * @category Util
59073                * @returns {Function} Returns the `lodash` function.
59074                * @example
59075                *
59076                * var lodash = _.noConflict();
59077                */
59078
59079
59080               function noConflict() {
59081                 if (root._ === this) {
59082                   root._ = oldDash;
59083                 }
59084
59085                 return this;
59086               }
59087               /**
59088                * This method returns `undefined`.
59089                *
59090                * @static
59091                * @memberOf _
59092                * @since 2.3.0
59093                * @category Util
59094                * @example
59095                *
59096                * _.times(2, _.noop);
59097                * // => [undefined, undefined]
59098                */
59099
59100
59101               function noop() {// No operation performed.
59102               }
59103               /**
59104                * Creates a function that gets the argument at index `n`. If `n` is negative,
59105                * the nth argument from the end is returned.
59106                *
59107                * @static
59108                * @memberOf _
59109                * @since 4.0.0
59110                * @category Util
59111                * @param {number} [n=0] The index of the argument to return.
59112                * @returns {Function} Returns the new pass-thru function.
59113                * @example
59114                *
59115                * var func = _.nthArg(1);
59116                * func('a', 'b', 'c', 'd');
59117                * // => 'b'
59118                *
59119                * var func = _.nthArg(-2);
59120                * func('a', 'b', 'c', 'd');
59121                * // => 'c'
59122                */
59123
59124
59125               function nthArg(n) {
59126                 n = toInteger(n);
59127                 return baseRest(function (args) {
59128                   return baseNth(args, n);
59129                 });
59130               }
59131               /**
59132                * Creates a function that invokes `iteratees` with the arguments it receives
59133                * and returns their results.
59134                *
59135                * @static
59136                * @memberOf _
59137                * @since 4.0.0
59138                * @category Util
59139                * @param {...(Function|Function[])} [iteratees=[_.identity]]
59140                *  The iteratees to invoke.
59141                * @returns {Function} Returns the new function.
59142                * @example
59143                *
59144                * var func = _.over([Math.max, Math.min]);
59145                *
59146                * func(1, 2, 3, 4);
59147                * // => [4, 1]
59148                */
59149
59150
59151               var over = createOver(arrayMap);
59152               /**
59153                * Creates a function that checks if **all** of the `predicates` return
59154                * truthy when invoked with the arguments it receives.
59155                *
59156                * Following shorthands are possible for providing predicates.
59157                * Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate.
59158                * Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them.
59159                *
59160                * @static
59161                * @memberOf _
59162                * @since 4.0.0
59163                * @category Util
59164                * @param {...(Function|Function[])} [predicates=[_.identity]]
59165                *  The predicates to check.
59166                * @returns {Function} Returns the new function.
59167                * @example
59168                *
59169                * var func = _.overEvery([Boolean, isFinite]);
59170                *
59171                * func('1');
59172                * // => true
59173                *
59174                * func(null);
59175                * // => false
59176                *
59177                * func(NaN);
59178                * // => false
59179                */
59180
59181               var overEvery = createOver(arrayEvery);
59182               /**
59183                * Creates a function that checks if **any** of the `predicates` return
59184                * truthy when invoked with the arguments it receives.
59185                *
59186                * Following shorthands are possible for providing predicates.
59187                * Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate.
59188                * Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them.
59189                *
59190                * @static
59191                * @memberOf _
59192                * @since 4.0.0
59193                * @category Util
59194                * @param {...(Function|Function[])} [predicates=[_.identity]]
59195                *  The predicates to check.
59196                * @returns {Function} Returns the new function.
59197                * @example
59198                *
59199                * var func = _.overSome([Boolean, isFinite]);
59200                *
59201                * func('1');
59202                * // => true
59203                *
59204                * func(null);
59205                * // => true
59206                *
59207                * func(NaN);
59208                * // => false
59209                *
59210                * var matchesFunc = _.overSome([{ 'a': 1 }, { 'a': 2 }])
59211                * var matchesPropertyFunc = _.overSome([['a', 1], ['a', 2]])
59212                */
59213
59214               var overSome = createOver(arraySome);
59215               /**
59216                * Creates a function that returns the value at `path` of a given object.
59217                *
59218                * @static
59219                * @memberOf _
59220                * @since 2.4.0
59221                * @category Util
59222                * @param {Array|string} path The path of the property to get.
59223                * @returns {Function} Returns the new accessor function.
59224                * @example
59225                *
59226                * var objects = [
59227                *   { 'a': { 'b': 2 } },
59228                *   { 'a': { 'b': 1 } }
59229                * ];
59230                *
59231                * _.map(objects, _.property('a.b'));
59232                * // => [2, 1]
59233                *
59234                * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
59235                * // => [1, 2]
59236                */
59237
59238               function property(path) {
59239                 return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
59240               }
59241               /**
59242                * The opposite of `_.property`; this method creates a function that returns
59243                * the value at a given path of `object`.
59244                *
59245                * @static
59246                * @memberOf _
59247                * @since 3.0.0
59248                * @category Util
59249                * @param {Object} object The object to query.
59250                * @returns {Function} Returns the new accessor function.
59251                * @example
59252                *
59253                * var array = [0, 1, 2],
59254                *     object = { 'a': array, 'b': array, 'c': array };
59255                *
59256                * _.map(['a[2]', 'c[0]'], _.propertyOf(object));
59257                * // => [2, 0]
59258                *
59259                * _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
59260                * // => [2, 0]
59261                */
59262
59263
59264               function propertyOf(object) {
59265                 return function (path) {
59266                   return object == null ? undefined$1 : baseGet(object, path);
59267                 };
59268               }
59269               /**
59270                * Creates an array of numbers (positive and/or negative) progressing from
59271                * `start` up to, but not including, `end`. A step of `-1` is used if a negative
59272                * `start` is specified without an `end` or `step`. If `end` is not specified,
59273                * it's set to `start` with `start` then set to `0`.
59274                *
59275                * **Note:** JavaScript follows the IEEE-754 standard for resolving
59276                * floating-point values which can produce unexpected results.
59277                *
59278                * @static
59279                * @since 0.1.0
59280                * @memberOf _
59281                * @category Util
59282                * @param {number} [start=0] The start of the range.
59283                * @param {number} end The end of the range.
59284                * @param {number} [step=1] The value to increment or decrement by.
59285                * @returns {Array} Returns the range of numbers.
59286                * @see _.inRange, _.rangeRight
59287                * @example
59288                *
59289                * _.range(4);
59290                * // => [0, 1, 2, 3]
59291                *
59292                * _.range(-4);
59293                * // => [0, -1, -2, -3]
59294                *
59295                * _.range(1, 5);
59296                * // => [1, 2, 3, 4]
59297                *
59298                * _.range(0, 20, 5);
59299                * // => [0, 5, 10, 15]
59300                *
59301                * _.range(0, -4, -1);
59302                * // => [0, -1, -2, -3]
59303                *
59304                * _.range(1, 4, 0);
59305                * // => [1, 1, 1]
59306                *
59307                * _.range(0);
59308                * // => []
59309                */
59310
59311
59312               var range = createRange();
59313               /**
59314                * This method is like `_.range` except that it populates values in
59315                * descending order.
59316                *
59317                * @static
59318                * @memberOf _
59319                * @since 4.0.0
59320                * @category Util
59321                * @param {number} [start=0] The start of the range.
59322                * @param {number} end The end of the range.
59323                * @param {number} [step=1] The value to increment or decrement by.
59324                * @returns {Array} Returns the range of numbers.
59325                * @see _.inRange, _.range
59326                * @example
59327                *
59328                * _.rangeRight(4);
59329                * // => [3, 2, 1, 0]
59330                *
59331                * _.rangeRight(-4);
59332                * // => [-3, -2, -1, 0]
59333                *
59334                * _.rangeRight(1, 5);
59335                * // => [4, 3, 2, 1]
59336                *
59337                * _.rangeRight(0, 20, 5);
59338                * // => [15, 10, 5, 0]
59339                *
59340                * _.rangeRight(0, -4, -1);
59341                * // => [-3, -2, -1, 0]
59342                *
59343                * _.rangeRight(1, 4, 0);
59344                * // => [1, 1, 1]
59345                *
59346                * _.rangeRight(0);
59347                * // => []
59348                */
59349
59350               var rangeRight = createRange(true);
59351               /**
59352                * This method returns a new empty array.
59353                *
59354                * @static
59355                * @memberOf _
59356                * @since 4.13.0
59357                * @category Util
59358                * @returns {Array} Returns the new empty array.
59359                * @example
59360                *
59361                * var arrays = _.times(2, _.stubArray);
59362                *
59363                * console.log(arrays);
59364                * // => [[], []]
59365                *
59366                * console.log(arrays[0] === arrays[1]);
59367                * // => false
59368                */
59369
59370               function stubArray() {
59371                 return [];
59372               }
59373               /**
59374                * This method returns `false`.
59375                *
59376                * @static
59377                * @memberOf _
59378                * @since 4.13.0
59379                * @category Util
59380                * @returns {boolean} Returns `false`.
59381                * @example
59382                *
59383                * _.times(2, _.stubFalse);
59384                * // => [false, false]
59385                */
59386
59387
59388               function stubFalse() {
59389                 return false;
59390               }
59391               /**
59392                * This method returns a new empty object.
59393                *
59394                * @static
59395                * @memberOf _
59396                * @since 4.13.0
59397                * @category Util
59398                * @returns {Object} Returns the new empty object.
59399                * @example
59400                *
59401                * var objects = _.times(2, _.stubObject);
59402                *
59403                * console.log(objects);
59404                * // => [{}, {}]
59405                *
59406                * console.log(objects[0] === objects[1]);
59407                * // => false
59408                */
59409
59410
59411               function stubObject() {
59412                 return {};
59413               }
59414               /**
59415                * This method returns an empty string.
59416                *
59417                * @static
59418                * @memberOf _
59419                * @since 4.13.0
59420                * @category Util
59421                * @returns {string} Returns the empty string.
59422                * @example
59423                *
59424                * _.times(2, _.stubString);
59425                * // => ['', '']
59426                */
59427
59428
59429               function stubString() {
59430                 return '';
59431               }
59432               /**
59433                * This method returns `true`.
59434                *
59435                * @static
59436                * @memberOf _
59437                * @since 4.13.0
59438                * @category Util
59439                * @returns {boolean} Returns `true`.
59440                * @example
59441                *
59442                * _.times(2, _.stubTrue);
59443                * // => [true, true]
59444                */
59445
59446
59447               function stubTrue() {
59448                 return true;
59449               }
59450               /**
59451                * Invokes the iteratee `n` times, returning an array of the results of
59452                * each invocation. The iteratee is invoked with one argument; (index).
59453                *
59454                * @static
59455                * @since 0.1.0
59456                * @memberOf _
59457                * @category Util
59458                * @param {number} n The number of times to invoke `iteratee`.
59459                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
59460                * @returns {Array} Returns the array of results.
59461                * @example
59462                *
59463                * _.times(3, String);
59464                * // => ['0', '1', '2']
59465                *
59466                *  _.times(4, _.constant(0));
59467                * // => [0, 0, 0, 0]
59468                */
59469
59470
59471               function times(n, iteratee) {
59472                 n = toInteger(n);
59473
59474                 if (n < 1 || n > MAX_SAFE_INTEGER) {
59475                   return [];
59476                 }
59477
59478                 var index = MAX_ARRAY_LENGTH,
59479                     length = nativeMin(n, MAX_ARRAY_LENGTH);
59480                 iteratee = getIteratee(iteratee);
59481                 n -= MAX_ARRAY_LENGTH;
59482                 var result = baseTimes(length, iteratee);
59483
59484                 while (++index < n) {
59485                   iteratee(index);
59486                 }
59487
59488                 return result;
59489               }
59490               /**
59491                * Converts `value` to a property path array.
59492                *
59493                * @static
59494                * @memberOf _
59495                * @since 4.0.0
59496                * @category Util
59497                * @param {*} value The value to convert.
59498                * @returns {Array} Returns the new property path array.
59499                * @example
59500                *
59501                * _.toPath('a.b.c');
59502                * // => ['a', 'b', 'c']
59503                *
59504                * _.toPath('a[0].b.c');
59505                * // => ['a', '0', 'b', 'c']
59506                */
59507
59508
59509               function toPath(value) {
59510                 if (isArray(value)) {
59511                   return arrayMap(value, toKey);
59512                 }
59513
59514                 return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value)));
59515               }
59516               /**
59517                * Generates a unique ID. If `prefix` is given, the ID is appended to it.
59518                *
59519                * @static
59520                * @since 0.1.0
59521                * @memberOf _
59522                * @category Util
59523                * @param {string} [prefix=''] The value to prefix the ID with.
59524                * @returns {string} Returns the unique ID.
59525                * @example
59526                *
59527                * _.uniqueId('contact_');
59528                * // => 'contact_104'
59529                *
59530                * _.uniqueId();
59531                * // => '105'
59532                */
59533
59534
59535               function uniqueId(prefix) {
59536                 var id = ++idCounter;
59537                 return toString(prefix) + id;
59538               }
59539               /*------------------------------------------------------------------------*/
59540
59541               /**
59542                * Adds two numbers.
59543                *
59544                * @static
59545                * @memberOf _
59546                * @since 3.4.0
59547                * @category Math
59548                * @param {number} augend The first number in an addition.
59549                * @param {number} addend The second number in an addition.
59550                * @returns {number} Returns the total.
59551                * @example
59552                *
59553                * _.add(6, 4);
59554                * // => 10
59555                */
59556
59557
59558               var add = createMathOperation(function (augend, addend) {
59559                 return augend + addend;
59560               }, 0);
59561               /**
59562                * Computes `number` rounded up to `precision`.
59563                *
59564                * @static
59565                * @memberOf _
59566                * @since 3.10.0
59567                * @category Math
59568                * @param {number} number The number to round up.
59569                * @param {number} [precision=0] The precision to round up to.
59570                * @returns {number} Returns the rounded up number.
59571                * @example
59572                *
59573                * _.ceil(4.006);
59574                * // => 5
59575                *
59576                * _.ceil(6.004, 2);
59577                * // => 6.01
59578                *
59579                * _.ceil(6040, -2);
59580                * // => 6100
59581                */
59582
59583               var ceil = createRound('ceil');
59584               /**
59585                * Divide two numbers.
59586                *
59587                * @static
59588                * @memberOf _
59589                * @since 4.7.0
59590                * @category Math
59591                * @param {number} dividend The first number in a division.
59592                * @param {number} divisor The second number in a division.
59593                * @returns {number} Returns the quotient.
59594                * @example
59595                *
59596                * _.divide(6, 4);
59597                * // => 1.5
59598                */
59599
59600               var divide = createMathOperation(function (dividend, divisor) {
59601                 return dividend / divisor;
59602               }, 1);
59603               /**
59604                * Computes `number` rounded down to `precision`.
59605                *
59606                * @static
59607                * @memberOf _
59608                * @since 3.10.0
59609                * @category Math
59610                * @param {number} number The number to round down.
59611                * @param {number} [precision=0] The precision to round down to.
59612                * @returns {number} Returns the rounded down number.
59613                * @example
59614                *
59615                * _.floor(4.006);
59616                * // => 4
59617                *
59618                * _.floor(0.046, 2);
59619                * // => 0.04
59620                *
59621                * _.floor(4060, -2);
59622                * // => 4000
59623                */
59624
59625               var floor = createRound('floor');
59626               /**
59627                * Computes the maximum value of `array`. If `array` is empty or falsey,
59628                * `undefined` is returned.
59629                *
59630                * @static
59631                * @since 0.1.0
59632                * @memberOf _
59633                * @category Math
59634                * @param {Array} array The array to iterate over.
59635                * @returns {*} Returns the maximum value.
59636                * @example
59637                *
59638                * _.max([4, 2, 8, 6]);
59639                * // => 8
59640                *
59641                * _.max([]);
59642                * // => undefined
59643                */
59644
59645               function max(array) {
59646                 return array && array.length ? baseExtremum(array, identity, baseGt) : undefined$1;
59647               }
59648               /**
59649                * This method is like `_.max` except that it accepts `iteratee` which is
59650                * invoked for each element in `array` to generate the criterion by which
59651                * the value is ranked. The iteratee is invoked with one argument: (value).
59652                *
59653                * @static
59654                * @memberOf _
59655                * @since 4.0.0
59656                * @category Math
59657                * @param {Array} array The array to iterate over.
59658                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
59659                * @returns {*} Returns the maximum value.
59660                * @example
59661                *
59662                * var objects = [{ 'n': 1 }, { 'n': 2 }];
59663                *
59664                * _.maxBy(objects, function(o) { return o.n; });
59665                * // => { 'n': 2 }
59666                *
59667                * // The `_.property` iteratee shorthand.
59668                * _.maxBy(objects, 'n');
59669                * // => { 'n': 2 }
59670                */
59671
59672
59673               function maxBy(array, iteratee) {
59674                 return array && array.length ? baseExtremum(array, getIteratee(iteratee, 2), baseGt) : undefined$1;
59675               }
59676               /**
59677                * Computes the mean of the values in `array`.
59678                *
59679                * @static
59680                * @memberOf _
59681                * @since 4.0.0
59682                * @category Math
59683                * @param {Array} array The array to iterate over.
59684                * @returns {number} Returns the mean.
59685                * @example
59686                *
59687                * _.mean([4, 2, 8, 6]);
59688                * // => 5
59689                */
59690
59691
59692               function mean(array) {
59693                 return baseMean(array, identity);
59694               }
59695               /**
59696                * This method is like `_.mean` except that it accepts `iteratee` which is
59697                * invoked for each element in `array` to generate the value to be averaged.
59698                * The iteratee is invoked with one argument: (value).
59699                *
59700                * @static
59701                * @memberOf _
59702                * @since 4.7.0
59703                * @category Math
59704                * @param {Array} array The array to iterate over.
59705                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
59706                * @returns {number} Returns the mean.
59707                * @example
59708                *
59709                * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
59710                *
59711                * _.meanBy(objects, function(o) { return o.n; });
59712                * // => 5
59713                *
59714                * // The `_.property` iteratee shorthand.
59715                * _.meanBy(objects, 'n');
59716                * // => 5
59717                */
59718
59719
59720               function meanBy(array, iteratee) {
59721                 return baseMean(array, getIteratee(iteratee, 2));
59722               }
59723               /**
59724                * Computes the minimum value of `array`. If `array` is empty or falsey,
59725                * `undefined` is returned.
59726                *
59727                * @static
59728                * @since 0.1.0
59729                * @memberOf _
59730                * @category Math
59731                * @param {Array} array The array to iterate over.
59732                * @returns {*} Returns the minimum value.
59733                * @example
59734                *
59735                * _.min([4, 2, 8, 6]);
59736                * // => 2
59737                *
59738                * _.min([]);
59739                * // => undefined
59740                */
59741
59742
59743               function min(array) {
59744                 return array && array.length ? baseExtremum(array, identity, baseLt) : undefined$1;
59745               }
59746               /**
59747                * This method is like `_.min` except that it accepts `iteratee` which is
59748                * invoked for each element in `array` to generate the criterion by which
59749                * the value is ranked. The iteratee is invoked with one argument: (value).
59750                *
59751                * @static
59752                * @memberOf _
59753                * @since 4.0.0
59754                * @category Math
59755                * @param {Array} array The array to iterate over.
59756                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
59757                * @returns {*} Returns the minimum value.
59758                * @example
59759                *
59760                * var objects = [{ 'n': 1 }, { 'n': 2 }];
59761                *
59762                * _.minBy(objects, function(o) { return o.n; });
59763                * // => { 'n': 1 }
59764                *
59765                * // The `_.property` iteratee shorthand.
59766                * _.minBy(objects, 'n');
59767                * // => { 'n': 1 }
59768                */
59769
59770
59771               function minBy(array, iteratee) {
59772                 return array && array.length ? baseExtremum(array, getIteratee(iteratee, 2), baseLt) : undefined$1;
59773               }
59774               /**
59775                * Multiply two numbers.
59776                *
59777                * @static
59778                * @memberOf _
59779                * @since 4.7.0
59780                * @category Math
59781                * @param {number} multiplier The first number in a multiplication.
59782                * @param {number} multiplicand The second number in a multiplication.
59783                * @returns {number} Returns the product.
59784                * @example
59785                *
59786                * _.multiply(6, 4);
59787                * // => 24
59788                */
59789
59790
59791               var multiply = createMathOperation(function (multiplier, multiplicand) {
59792                 return multiplier * multiplicand;
59793               }, 1);
59794               /**
59795                * Computes `number` rounded to `precision`.
59796                *
59797                * @static
59798                * @memberOf _
59799                * @since 3.10.0
59800                * @category Math
59801                * @param {number} number The number to round.
59802                * @param {number} [precision=0] The precision to round to.
59803                * @returns {number} Returns the rounded number.
59804                * @example
59805                *
59806                * _.round(4.006);
59807                * // => 4
59808                *
59809                * _.round(4.006, 2);
59810                * // => 4.01
59811                *
59812                * _.round(4060, -2);
59813                * // => 4100
59814                */
59815
59816               var round = createRound('round');
59817               /**
59818                * Subtract two numbers.
59819                *
59820                * @static
59821                * @memberOf _
59822                * @since 4.0.0
59823                * @category Math
59824                * @param {number} minuend The first number in a subtraction.
59825                * @param {number} subtrahend The second number in a subtraction.
59826                * @returns {number} Returns the difference.
59827                * @example
59828                *
59829                * _.subtract(6, 4);
59830                * // => 2
59831                */
59832
59833               var subtract = createMathOperation(function (minuend, subtrahend) {
59834                 return minuend - subtrahend;
59835               }, 0);
59836               /**
59837                * Computes the sum of the values in `array`.
59838                *
59839                * @static
59840                * @memberOf _
59841                * @since 3.4.0
59842                * @category Math
59843                * @param {Array} array The array to iterate over.
59844                * @returns {number} Returns the sum.
59845                * @example
59846                *
59847                * _.sum([4, 2, 8, 6]);
59848                * // => 20
59849                */
59850
59851               function sum(array) {
59852                 return array && array.length ? baseSum(array, identity) : 0;
59853               }
59854               /**
59855                * This method is like `_.sum` except that it accepts `iteratee` which is
59856                * invoked for each element in `array` to generate the value to be summed.
59857                * The iteratee is invoked with one argument: (value).
59858                *
59859                * @static
59860                * @memberOf _
59861                * @since 4.0.0
59862                * @category Math
59863                * @param {Array} array The array to iterate over.
59864                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
59865                * @returns {number} Returns the sum.
59866                * @example
59867                *
59868                * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
59869                *
59870                * _.sumBy(objects, function(o) { return o.n; });
59871                * // => 20
59872                *
59873                * // The `_.property` iteratee shorthand.
59874                * _.sumBy(objects, 'n');
59875                * // => 20
59876                */
59877
59878
59879               function sumBy(array, iteratee) {
59880                 return array && array.length ? baseSum(array, getIteratee(iteratee, 2)) : 0;
59881               }
59882               /*------------------------------------------------------------------------*/
59883               // Add methods that return wrapped values in chain sequences.
59884
59885
59886               lodash.after = after;
59887               lodash.ary = ary;
59888               lodash.assign = assign;
59889               lodash.assignIn = assignIn;
59890               lodash.assignInWith = assignInWith;
59891               lodash.assignWith = assignWith;
59892               lodash.at = at;
59893               lodash.before = before;
59894               lodash.bind = bind;
59895               lodash.bindAll = bindAll;
59896               lodash.bindKey = bindKey;
59897               lodash.castArray = castArray;
59898               lodash.chain = chain;
59899               lodash.chunk = chunk;
59900               lodash.compact = compact;
59901               lodash.concat = concat;
59902               lodash.cond = cond;
59903               lodash.conforms = conforms;
59904               lodash.constant = constant;
59905               lodash.countBy = countBy;
59906               lodash.create = create;
59907               lodash.curry = curry;
59908               lodash.curryRight = curryRight;
59909               lodash.debounce = debounce;
59910               lodash.defaults = defaults;
59911               lodash.defaultsDeep = defaultsDeep;
59912               lodash.defer = defer;
59913               lodash.delay = delay;
59914               lodash.difference = difference;
59915               lodash.differenceBy = differenceBy;
59916               lodash.differenceWith = differenceWith;
59917               lodash.drop = drop;
59918               lodash.dropRight = dropRight;
59919               lodash.dropRightWhile = dropRightWhile;
59920               lodash.dropWhile = dropWhile;
59921               lodash.fill = fill;
59922               lodash.filter = filter;
59923               lodash.flatMap = flatMap;
59924               lodash.flatMapDeep = flatMapDeep;
59925               lodash.flatMapDepth = flatMapDepth;
59926               lodash.flatten = flatten;
59927               lodash.flattenDeep = flattenDeep;
59928               lodash.flattenDepth = flattenDepth;
59929               lodash.flip = flip;
59930               lodash.flow = flow;
59931               lodash.flowRight = flowRight;
59932               lodash.fromPairs = fromPairs;
59933               lodash.functions = functions;
59934               lodash.functionsIn = functionsIn;
59935               lodash.groupBy = groupBy;
59936               lodash.initial = initial;
59937               lodash.intersection = intersection;
59938               lodash.intersectionBy = intersectionBy;
59939               lodash.intersectionWith = intersectionWith;
59940               lodash.invert = invert;
59941               lodash.invertBy = invertBy;
59942               lodash.invokeMap = invokeMap;
59943               lodash.iteratee = iteratee;
59944               lodash.keyBy = keyBy;
59945               lodash.keys = keys;
59946               lodash.keysIn = keysIn;
59947               lodash.map = map;
59948               lodash.mapKeys = mapKeys;
59949               lodash.mapValues = mapValues;
59950               lodash.matches = matches;
59951               lodash.matchesProperty = matchesProperty;
59952               lodash.memoize = memoize;
59953               lodash.merge = merge;
59954               lodash.mergeWith = mergeWith;
59955               lodash.method = method;
59956               lodash.methodOf = methodOf;
59957               lodash.mixin = mixin;
59958               lodash.negate = negate;
59959               lodash.nthArg = nthArg;
59960               lodash.omit = omit;
59961               lodash.omitBy = omitBy;
59962               lodash.once = once;
59963               lodash.orderBy = orderBy;
59964               lodash.over = over;
59965               lodash.overArgs = overArgs;
59966               lodash.overEvery = overEvery;
59967               lodash.overSome = overSome;
59968               lodash.partial = partial;
59969               lodash.partialRight = partialRight;
59970               lodash.partition = partition;
59971               lodash.pick = pick;
59972               lodash.pickBy = pickBy;
59973               lodash.property = property;
59974               lodash.propertyOf = propertyOf;
59975               lodash.pull = pull;
59976               lodash.pullAll = pullAll;
59977               lodash.pullAllBy = pullAllBy;
59978               lodash.pullAllWith = pullAllWith;
59979               lodash.pullAt = pullAt;
59980               lodash.range = range;
59981               lodash.rangeRight = rangeRight;
59982               lodash.rearg = rearg;
59983               lodash.reject = reject;
59984               lodash.remove = remove;
59985               lodash.rest = rest;
59986               lodash.reverse = reverse;
59987               lodash.sampleSize = sampleSize;
59988               lodash.set = set;
59989               lodash.setWith = setWith;
59990               lodash.shuffle = shuffle;
59991               lodash.slice = slice;
59992               lodash.sortBy = sortBy;
59993               lodash.sortedUniq = sortedUniq;
59994               lodash.sortedUniqBy = sortedUniqBy;
59995               lodash.split = split;
59996               lodash.spread = spread;
59997               lodash.tail = tail;
59998               lodash.take = take;
59999               lodash.takeRight = takeRight;
60000               lodash.takeRightWhile = takeRightWhile;
60001               lodash.takeWhile = takeWhile;
60002               lodash.tap = tap;
60003               lodash.throttle = throttle;
60004               lodash.thru = thru;
60005               lodash.toArray = toArray;
60006               lodash.toPairs = toPairs;
60007               lodash.toPairsIn = toPairsIn;
60008               lodash.toPath = toPath;
60009               lodash.toPlainObject = toPlainObject;
60010               lodash.transform = transform;
60011               lodash.unary = unary;
60012               lodash.union = union;
60013               lodash.unionBy = unionBy;
60014               lodash.unionWith = unionWith;
60015               lodash.uniq = uniq;
60016               lodash.uniqBy = uniqBy;
60017               lodash.uniqWith = uniqWith;
60018               lodash.unset = unset;
60019               lodash.unzip = unzip;
60020               lodash.unzipWith = unzipWith;
60021               lodash.update = update;
60022               lodash.updateWith = updateWith;
60023               lodash.values = values;
60024               lodash.valuesIn = valuesIn;
60025               lodash.without = without;
60026               lodash.words = words;
60027               lodash.wrap = wrap;
60028               lodash.xor = xor;
60029               lodash.xorBy = xorBy;
60030               lodash.xorWith = xorWith;
60031               lodash.zip = zip;
60032               lodash.zipObject = zipObject;
60033               lodash.zipObjectDeep = zipObjectDeep;
60034               lodash.zipWith = zipWith; // Add aliases.
60035
60036               lodash.entries = toPairs;
60037               lodash.entriesIn = toPairsIn;
60038               lodash.extend = assignIn;
60039               lodash.extendWith = assignInWith; // Add methods to `lodash.prototype`.
60040
60041               mixin(lodash, lodash);
60042               /*------------------------------------------------------------------------*/
60043               // Add methods that return unwrapped values in chain sequences.
60044
60045               lodash.add = add;
60046               lodash.attempt = attempt;
60047               lodash.camelCase = camelCase;
60048               lodash.capitalize = capitalize;
60049               lodash.ceil = ceil;
60050               lodash.clamp = clamp;
60051               lodash.clone = clone;
60052               lodash.cloneDeep = cloneDeep;
60053               lodash.cloneDeepWith = cloneDeepWith;
60054               lodash.cloneWith = cloneWith;
60055               lodash.conformsTo = conformsTo;
60056               lodash.deburr = deburr;
60057               lodash.defaultTo = defaultTo;
60058               lodash.divide = divide;
60059               lodash.endsWith = endsWith;
60060               lodash.eq = eq;
60061               lodash.escape = escape;
60062               lodash.escapeRegExp = escapeRegExp;
60063               lodash.every = every;
60064               lodash.find = find;
60065               lodash.findIndex = findIndex;
60066               lodash.findKey = findKey;
60067               lodash.findLast = findLast;
60068               lodash.findLastIndex = findLastIndex;
60069               lodash.findLastKey = findLastKey;
60070               lodash.floor = floor;
60071               lodash.forEach = forEach;
60072               lodash.forEachRight = forEachRight;
60073               lodash.forIn = forIn;
60074               lodash.forInRight = forInRight;
60075               lodash.forOwn = forOwn;
60076               lodash.forOwnRight = forOwnRight;
60077               lodash.get = get;
60078               lodash.gt = gt;
60079               lodash.gte = gte;
60080               lodash.has = has;
60081               lodash.hasIn = hasIn;
60082               lodash.head = head;
60083               lodash.identity = identity;
60084               lodash.includes = includes;
60085               lodash.indexOf = indexOf;
60086               lodash.inRange = inRange;
60087               lodash.invoke = invoke;
60088               lodash.isArguments = isArguments;
60089               lodash.isArray = isArray;
60090               lodash.isArrayBuffer = isArrayBuffer;
60091               lodash.isArrayLike = isArrayLike;
60092               lodash.isArrayLikeObject = isArrayLikeObject;
60093               lodash.isBoolean = isBoolean;
60094               lodash.isBuffer = isBuffer;
60095               lodash.isDate = isDate;
60096               lodash.isElement = isElement;
60097               lodash.isEmpty = isEmpty;
60098               lodash.isEqual = isEqual;
60099               lodash.isEqualWith = isEqualWith;
60100               lodash.isError = isError;
60101               lodash.isFinite = isFinite;
60102               lodash.isFunction = isFunction;
60103               lodash.isInteger = isInteger;
60104               lodash.isLength = isLength;
60105               lodash.isMap = isMap;
60106               lodash.isMatch = isMatch;
60107               lodash.isMatchWith = isMatchWith;
60108               lodash.isNaN = isNaN;
60109               lodash.isNative = isNative;
60110               lodash.isNil = isNil;
60111               lodash.isNull = isNull;
60112               lodash.isNumber = isNumber;
60113               lodash.isObject = isObject;
60114               lodash.isObjectLike = isObjectLike;
60115               lodash.isPlainObject = isPlainObject;
60116               lodash.isRegExp = isRegExp;
60117               lodash.isSafeInteger = isSafeInteger;
60118               lodash.isSet = isSet;
60119               lodash.isString = isString;
60120               lodash.isSymbol = isSymbol;
60121               lodash.isTypedArray = isTypedArray;
60122               lodash.isUndefined = isUndefined;
60123               lodash.isWeakMap = isWeakMap;
60124               lodash.isWeakSet = isWeakSet;
60125               lodash.join = join;
60126               lodash.kebabCase = kebabCase;
60127               lodash.last = last;
60128               lodash.lastIndexOf = lastIndexOf;
60129               lodash.lowerCase = lowerCase;
60130               lodash.lowerFirst = lowerFirst;
60131               lodash.lt = lt;
60132               lodash.lte = lte;
60133               lodash.max = max;
60134               lodash.maxBy = maxBy;
60135               lodash.mean = mean;
60136               lodash.meanBy = meanBy;
60137               lodash.min = min;
60138               lodash.minBy = minBy;
60139               lodash.stubArray = stubArray;
60140               lodash.stubFalse = stubFalse;
60141               lodash.stubObject = stubObject;
60142               lodash.stubString = stubString;
60143               lodash.stubTrue = stubTrue;
60144               lodash.multiply = multiply;
60145               lodash.nth = nth;
60146               lodash.noConflict = noConflict;
60147               lodash.noop = noop;
60148               lodash.now = now;
60149               lodash.pad = pad;
60150               lodash.padEnd = padEnd;
60151               lodash.padStart = padStart;
60152               lodash.parseInt = parseInt;
60153               lodash.random = random;
60154               lodash.reduce = reduce;
60155               lodash.reduceRight = reduceRight;
60156               lodash.repeat = repeat;
60157               lodash.replace = replace;
60158               lodash.result = result;
60159               lodash.round = round;
60160               lodash.runInContext = runInContext;
60161               lodash.sample = sample;
60162               lodash.size = size;
60163               lodash.snakeCase = snakeCase;
60164               lodash.some = some;
60165               lodash.sortedIndex = sortedIndex;
60166               lodash.sortedIndexBy = sortedIndexBy;
60167               lodash.sortedIndexOf = sortedIndexOf;
60168               lodash.sortedLastIndex = sortedLastIndex;
60169               lodash.sortedLastIndexBy = sortedLastIndexBy;
60170               lodash.sortedLastIndexOf = sortedLastIndexOf;
60171               lodash.startCase = startCase;
60172               lodash.startsWith = startsWith;
60173               lodash.subtract = subtract;
60174               lodash.sum = sum;
60175               lodash.sumBy = sumBy;
60176               lodash.template = template;
60177               lodash.times = times;
60178               lodash.toFinite = toFinite;
60179               lodash.toInteger = toInteger;
60180               lodash.toLength = toLength;
60181               lodash.toLower = toLower;
60182               lodash.toNumber = toNumber;
60183               lodash.toSafeInteger = toSafeInteger;
60184               lodash.toString = toString;
60185               lodash.toUpper = toUpper;
60186               lodash.trim = trim;
60187               lodash.trimEnd = trimEnd;
60188               lodash.trimStart = trimStart;
60189               lodash.truncate = truncate;
60190               lodash.unescape = unescape;
60191               lodash.uniqueId = uniqueId;
60192               lodash.upperCase = upperCase;
60193               lodash.upperFirst = upperFirst; // Add aliases.
60194
60195               lodash.each = forEach;
60196               lodash.eachRight = forEachRight;
60197               lodash.first = head;
60198               mixin(lodash, function () {
60199                 var source = {};
60200                 baseForOwn(lodash, function (func, methodName) {
60201                   if (!hasOwnProperty.call(lodash.prototype, methodName)) {
60202                     source[methodName] = func;
60203                   }
60204                 });
60205                 return source;
60206               }(), {
60207                 'chain': false
60208               });
60209               /*------------------------------------------------------------------------*/
60210
60211               /**
60212                * The semantic version number.
60213                *
60214                * @static
60215                * @memberOf _
60216                * @type {string}
60217                */
60218
60219               lodash.VERSION = VERSION; // Assign default placeholders.
60220
60221               arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function (methodName) {
60222                 lodash[methodName].placeholder = lodash;
60223               }); // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
60224
60225               arrayEach(['drop', 'take'], function (methodName, index) {
60226                 LazyWrapper.prototype[methodName] = function (n) {
60227                   n = n === undefined$1 ? 1 : nativeMax(toInteger(n), 0);
60228                   var result = this.__filtered__ && !index ? new LazyWrapper(this) : this.clone();
60229
60230                   if (result.__filtered__) {
60231                     result.__takeCount__ = nativeMin(n, result.__takeCount__);
60232                   } else {
60233                     result.__views__.push({
60234                       'size': nativeMin(n, MAX_ARRAY_LENGTH),
60235                       'type': methodName + (result.__dir__ < 0 ? 'Right' : '')
60236                     });
60237                   }
60238
60239                   return result;
60240                 };
60241
60242                 LazyWrapper.prototype[methodName + 'Right'] = function (n) {
60243                   return this.reverse()[methodName](n).reverse();
60244                 };
60245               }); // Add `LazyWrapper` methods that accept an `iteratee` value.
60246
60247               arrayEach(['filter', 'map', 'takeWhile'], function (methodName, index) {
60248                 var type = index + 1,
60249                     isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
60250
60251                 LazyWrapper.prototype[methodName] = function (iteratee) {
60252                   var result = this.clone();
60253
60254                   result.__iteratees__.push({
60255                     'iteratee': getIteratee(iteratee, 3),
60256                     'type': type
60257                   });
60258
60259                   result.__filtered__ = result.__filtered__ || isFilter;
60260                   return result;
60261                 };
60262               }); // Add `LazyWrapper` methods for `_.head` and `_.last`.
60263
60264               arrayEach(['head', 'last'], function (methodName, index) {
60265                 var takeName = 'take' + (index ? 'Right' : '');
60266
60267                 LazyWrapper.prototype[methodName] = function () {
60268                   return this[takeName](1).value()[0];
60269                 };
60270               }); // Add `LazyWrapper` methods for `_.initial` and `_.tail`.
60271
60272               arrayEach(['initial', 'tail'], function (methodName, index) {
60273                 var dropName = 'drop' + (index ? '' : 'Right');
60274
60275                 LazyWrapper.prototype[methodName] = function () {
60276                   return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
60277                 };
60278               });
60279
60280               LazyWrapper.prototype.compact = function () {
60281                 return this.filter(identity);
60282               };
60283
60284               LazyWrapper.prototype.find = function (predicate) {
60285                 return this.filter(predicate).head();
60286               };
60287
60288               LazyWrapper.prototype.findLast = function (predicate) {
60289                 return this.reverse().find(predicate);
60290               };
60291
60292               LazyWrapper.prototype.invokeMap = baseRest(function (path, args) {
60293                 if (typeof path == 'function') {
60294                   return new LazyWrapper(this);
60295                 }
60296
60297                 return this.map(function (value) {
60298                   return baseInvoke(value, path, args);
60299                 });
60300               });
60301
60302               LazyWrapper.prototype.reject = function (predicate) {
60303                 return this.filter(negate(getIteratee(predicate)));
60304               };
60305
60306               LazyWrapper.prototype.slice = function (start, end) {
60307                 start = toInteger(start);
60308                 var result = this;
60309
60310                 if (result.__filtered__ && (start > 0 || end < 0)) {
60311                   return new LazyWrapper(result);
60312                 }
60313
60314                 if (start < 0) {
60315                   result = result.takeRight(-start);
60316                 } else if (start) {
60317                   result = result.drop(start);
60318                 }
60319
60320                 if (end !== undefined$1) {
60321                   end = toInteger(end);
60322                   result = end < 0 ? result.dropRight(-end) : result.take(end - start);
60323                 }
60324
60325                 return result;
60326               };
60327
60328               LazyWrapper.prototype.takeRightWhile = function (predicate) {
60329                 return this.reverse().takeWhile(predicate).reverse();
60330               };
60331
60332               LazyWrapper.prototype.toArray = function () {
60333                 return this.take(MAX_ARRAY_LENGTH);
60334               }; // Add `LazyWrapper` methods to `lodash.prototype`.
60335
60336
60337               baseForOwn(LazyWrapper.prototype, function (func, methodName) {
60338                 var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),
60339                     isTaker = /^(?:head|last)$/.test(methodName),
60340                     lodashFunc = lodash[isTaker ? 'take' + (methodName == 'last' ? 'Right' : '') : methodName],
60341                     retUnwrapped = isTaker || /^find/.test(methodName);
60342
60343                 if (!lodashFunc) {
60344                   return;
60345                 }
60346
60347                 lodash.prototype[methodName] = function () {
60348                   var value = this.__wrapped__,
60349                       args = isTaker ? [1] : arguments,
60350                       isLazy = value instanceof LazyWrapper,
60351                       iteratee = args[0],
60352                       useLazy = isLazy || isArray(value);
60353
60354                   var interceptor = function interceptor(value) {
60355                     var result = lodashFunc.apply(lodash, arrayPush([value], args));
60356                     return isTaker && chainAll ? result[0] : result;
60357                   };
60358
60359                   if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
60360                     // Avoid lazy use if the iteratee has a "length" value other than `1`.
60361                     isLazy = useLazy = false;
60362                   }
60363
60364                   var chainAll = this.__chain__,
60365                       isHybrid = !!this.__actions__.length,
60366                       isUnwrapped = retUnwrapped && !chainAll,
60367                       onlyLazy = isLazy && !isHybrid;
60368
60369                   if (!retUnwrapped && useLazy) {
60370                     value = onlyLazy ? value : new LazyWrapper(this);
60371                     var result = func.apply(value, args);
60372
60373                     result.__actions__.push({
60374                       'func': thru,
60375                       'args': [interceptor],
60376                       'thisArg': undefined$1
60377                     });
60378
60379                     return new LodashWrapper(result, chainAll);
60380                   }
60381
60382                   if (isUnwrapped && onlyLazy) {
60383                     return func.apply(this, args);
60384                   }
60385
60386                   result = this.thru(interceptor);
60387                   return isUnwrapped ? isTaker ? result.value()[0] : result.value() : result;
60388                 };
60389               }); // Add `Array` methods to `lodash.prototype`.
60390
60391               arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function (methodName) {
60392                 var func = arrayProto[methodName],
60393                     chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
60394                     retUnwrapped = /^(?:pop|shift)$/.test(methodName);
60395
60396                 lodash.prototype[methodName] = function () {
60397                   var args = arguments;
60398
60399                   if (retUnwrapped && !this.__chain__) {
60400                     var value = this.value();
60401                     return func.apply(isArray(value) ? value : [], args);
60402                   }
60403
60404                   return this[chainName](function (value) {
60405                     return func.apply(isArray(value) ? value : [], args);
60406                   });
60407                 };
60408               }); // Map minified method names to their real names.
60409
60410               baseForOwn(LazyWrapper.prototype, function (func, methodName) {
60411                 var lodashFunc = lodash[methodName];
60412
60413                 if (lodashFunc) {
60414                   var key = lodashFunc.name + '';
60415
60416                   if (!hasOwnProperty.call(realNames, key)) {
60417                     realNames[key] = [];
60418                   }
60419
60420                   realNames[key].push({
60421                     'name': methodName,
60422                     'func': lodashFunc
60423                   });
60424                 }
60425               });
60426               realNames[createHybrid(undefined$1, WRAP_BIND_KEY_FLAG).name] = [{
60427                 'name': 'wrapper',
60428                 'func': undefined$1
60429               }]; // Add methods to `LazyWrapper`.
60430
60431               LazyWrapper.prototype.clone = lazyClone;
60432               LazyWrapper.prototype.reverse = lazyReverse;
60433               LazyWrapper.prototype.value = lazyValue; // Add chain sequence methods to the `lodash` wrapper.
60434
60435               lodash.prototype.at = wrapperAt;
60436               lodash.prototype.chain = wrapperChain;
60437               lodash.prototype.commit = wrapperCommit;
60438               lodash.prototype.next = wrapperNext;
60439               lodash.prototype.plant = wrapperPlant;
60440               lodash.prototype.reverse = wrapperReverse;
60441               lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; // Add lazy aliases.
60442
60443               lodash.prototype.first = lodash.prototype.head;
60444
60445               if (symIterator) {
60446                 lodash.prototype[symIterator] = wrapperToIterator;
60447               }
60448
60449               return lodash;
60450             };
60451             /*--------------------------------------------------------------------------*/
60452             // Export lodash.
60453
60454
60455             var _ = runInContext(); // Some AMD build optimizers, like r.js, check for condition patterns like:
60456
60457
60458             if (freeModule) {
60459               // Export for Node.js.
60460               (freeModule.exports = _)._ = _; // Export for CommonJS support.
60461
60462               freeExports._ = _;
60463             } else {
60464               // Export to the global object.
60465               root._ = _;
60466             }
60467           }).call(commonjsGlobal);
60468         })(lodash, lodash.exports);
60469
60470         function actionMergeRemoteChanges(id, localGraph, remoteGraph, discardTags, formatUser) {
60471           discardTags = discardTags || {};
60472           var _option = 'safe'; // 'safe', 'force_local', 'force_remote'
60473
60474           var _conflicts = [];
60475
60476           function user(d) {
60477             return typeof formatUser === 'function' ? formatUser(d) : lodash.exports.escape(d);
60478           }
60479
60480           function mergeLocation(remote, target) {
60481             function pointEqual(a, b) {
60482               var epsilon = 1e-6;
60483               return Math.abs(a[0] - b[0]) < epsilon && Math.abs(a[1] - b[1]) < epsilon;
60484             }
60485
60486             if (_option === 'force_local' || pointEqual(target.loc, remote.loc)) {
60487               return target;
60488             }
60489
60490             if (_option === 'force_remote') {
60491               return target.update({
60492                 loc: remote.loc
60493               });
60494             }
60495
60496             _conflicts.push(_t.html('merge_remote_changes.conflict.location', {
60497               user: {
60498                 html: user(remote.user)
60499               }
60500             }));
60501
60502             return target;
60503           }
60504
60505           function mergeNodes(base, remote, target) {
60506             if (_option === 'force_local' || fastDeepEqual(target.nodes, remote.nodes)) {
60507               return target;
60508             }
60509
60510             if (_option === 'force_remote') {
60511               return target.update({
60512                 nodes: remote.nodes
60513               });
60514             }
60515
60516             var ccount = _conflicts.length;
60517             var o = base.nodes || [];
60518             var a = target.nodes || [];
60519             var b = remote.nodes || [];
60520             var nodes = [];
60521             var hunks = diff3Merge(a, o, b, {
60522               excludeFalseConflicts: true
60523             });
60524
60525             for (var i = 0; i < hunks.length; i++) {
60526               var hunk = hunks[i];
60527
60528               if (hunk.ok) {
60529                 nodes.push.apply(nodes, hunk.ok);
60530               } else {
60531                 // for all conflicts, we can assume c.a !== c.b
60532                 // because `diff3Merge` called with `true` option to exclude false conflicts..
60533                 var c = hunk.conflict;
60534
60535                 if (fastDeepEqual(c.o, c.a)) {
60536                   // only changed remotely
60537                   nodes.push.apply(nodes, c.b);
60538                 } else if (fastDeepEqual(c.o, c.b)) {
60539                   // only changed locally
60540                   nodes.push.apply(nodes, c.a);
60541                 } else {
60542                   // changed both locally and remotely
60543                   _conflicts.push(_t.html('merge_remote_changes.conflict.nodelist', {
60544                     user: {
60545                       html: user(remote.user)
60546                     }
60547                   }));
60548
60549                   break;
60550                 }
60551               }
60552             }
60553
60554             return _conflicts.length === ccount ? target.update({
60555               nodes: nodes
60556             }) : target;
60557           }
60558
60559           function mergeChildren(targetWay, children, updates, graph) {
60560             function isUsed(node, targetWay) {
60561               var hasInterestingParent = graph.parentWays(node).some(function (way) {
60562                 return way.id !== targetWay.id;
60563               });
60564               return node.hasInterestingTags() || hasInterestingParent || graph.parentRelations(node).length > 0;
60565             }
60566
60567             var ccount = _conflicts.length;
60568
60569             for (var i = 0; i < children.length; i++) {
60570               var id = children[i];
60571               var node = graph.hasEntity(id); // remove unused childNodes..
60572
60573               if (targetWay.nodes.indexOf(id) === -1) {
60574                 if (node && !isUsed(node, targetWay)) {
60575                   updates.removeIds.push(id);
60576                 }
60577
60578                 continue;
60579               } // restore used childNodes..
60580
60581
60582               var local = localGraph.hasEntity(id);
60583               var remote = remoteGraph.hasEntity(id);
60584               var target;
60585
60586               if (_option === 'force_remote' && remote && remote.visible) {
60587                 updates.replacements.push(remote);
60588               } else if (_option === 'force_local' && local) {
60589                 target = osmEntity(local);
60590
60591                 if (remote) {
60592                   target = target.update({
60593                     version: remote.version
60594                   });
60595                 }
60596
60597                 updates.replacements.push(target);
60598               } else if (_option === 'safe' && local && remote && local.version !== remote.version) {
60599                 target = osmEntity(local, {
60600                   version: remote.version
60601                 });
60602
60603                 if (remote.visible) {
60604                   target = mergeLocation(remote, target);
60605                 } else {
60606                   _conflicts.push(_t.html('merge_remote_changes.conflict.deleted', {
60607                     user: {
60608                       html: user(remote.user)
60609                     }
60610                   }));
60611                 }
60612
60613                 if (_conflicts.length !== ccount) break;
60614                 updates.replacements.push(target);
60615               }
60616             }
60617
60618             return targetWay;
60619           }
60620
60621           function updateChildren(updates, graph) {
60622             for (var i = 0; i < updates.replacements.length; i++) {
60623               graph = graph.replace(updates.replacements[i]);
60624             }
60625
60626             if (updates.removeIds.length) {
60627               graph = actionDeleteMultiple(updates.removeIds)(graph);
60628             }
60629
60630             return graph;
60631           }
60632
60633           function mergeMembers(remote, target) {
60634             if (_option === 'force_local' || fastDeepEqual(target.members, remote.members)) {
60635               return target;
60636             }
60637
60638             if (_option === 'force_remote') {
60639               return target.update({
60640                 members: remote.members
60641               });
60642             }
60643
60644             _conflicts.push(_t.html('merge_remote_changes.conflict.memberlist', {
60645               user: {
60646                 html: user(remote.user)
60647               }
60648             }));
60649
60650             return target;
60651           }
60652
60653           function mergeTags(base, remote, target) {
60654             if (_option === 'force_local' || fastDeepEqual(target.tags, remote.tags)) {
60655               return target;
60656             }
60657
60658             if (_option === 'force_remote') {
60659               return target.update({
60660                 tags: remote.tags
60661               });
60662             }
60663
60664             var ccount = _conflicts.length;
60665             var o = base.tags || {};
60666             var a = target.tags || {};
60667             var b = remote.tags || {};
60668             var keys = utilArrayUnion(utilArrayUnion(Object.keys(o), Object.keys(a)), Object.keys(b)).filter(function (k) {
60669               return !discardTags[k];
60670             });
60671             var tags = Object.assign({}, a); // shallow copy
60672
60673             var changed = false;
60674
60675             for (var i = 0; i < keys.length; i++) {
60676               var k = keys[i];
60677
60678               if (o[k] !== b[k] && a[k] !== b[k]) {
60679                 // changed remotely..
60680                 if (o[k] !== a[k]) {
60681                   // changed locally..
60682                   _conflicts.push(_t.html('merge_remote_changes.conflict.tags', {
60683                     tag: k,
60684                     local: a[k],
60685                     remote: b[k],
60686                     user: {
60687                       html: user(remote.user)
60688                     }
60689                   }));
60690                 } else {
60691                   // unchanged locally, accept remote change..
60692                   if (b.hasOwnProperty(k)) {
60693                     tags[k] = b[k];
60694                   } else {
60695                     delete tags[k];
60696                   }
60697
60698                   changed = true;
60699                 }
60700               }
60701             }
60702
60703             return changed && _conflicts.length === ccount ? target.update({
60704               tags: tags
60705             }) : target;
60706           } //  `graph.base()` is the common ancestor of the two graphs.
60707           //  `localGraph` contains user's edits up to saving
60708           //  `remoteGraph` contains remote edits to modified nodes
60709           //  `graph` must be a descendent of `localGraph` and may include
60710           //      some conflict resolution actions performed on it.
60711           //
60712           //                  --- ... --- `localGraph` -- ... -- `graph`
60713           //                 /
60714           //  `graph.base()` --- ... --- `remoteGraph`
60715           //
60716
60717
60718           var action = function action(graph) {
60719             var updates = {
60720               replacements: [],
60721               removeIds: []
60722             };
60723             var base = graph.base().entities[id];
60724             var local = localGraph.entity(id);
60725             var remote = remoteGraph.entity(id);
60726             var target = osmEntity(local, {
60727               version: remote.version
60728             }); // delete/undelete
60729
60730             if (!remote.visible) {
60731               if (_option === 'force_remote') {
60732                 return actionDeleteMultiple([id])(graph);
60733               } else if (_option === 'force_local') {
60734                 if (target.type === 'way') {
60735                   target = mergeChildren(target, utilArrayUniq(local.nodes), updates, graph);
60736                   graph = updateChildren(updates, graph);
60737                 }
60738
60739                 return graph.replace(target);
60740               } else {
60741                 _conflicts.push(_t.html('merge_remote_changes.conflict.deleted', {
60742                   user: {
60743                     html: user(remote.user)
60744                   }
60745                 }));
60746
60747                 return graph; // do nothing
60748               }
60749             } // merge
60750
60751
60752             if (target.type === 'node') {
60753               target = mergeLocation(remote, target);
60754             } else if (target.type === 'way') {
60755               // pull in any child nodes that may not be present locally..
60756               graph.rebase(remoteGraph.childNodes(remote), [graph], false);
60757               target = mergeNodes(base, remote, target);
60758               target = mergeChildren(target, utilArrayUnion(local.nodes, remote.nodes), updates, graph);
60759             } else if (target.type === 'relation') {
60760               target = mergeMembers(remote, target);
60761             }
60762
60763             target = mergeTags(base, remote, target);
60764
60765             if (!_conflicts.length) {
60766               graph = updateChildren(updates, graph).replace(target);
60767             }
60768
60769             return graph;
60770           };
60771
60772           action.withOption = function (opt) {
60773             _option = opt;
60774             return action;
60775           };
60776
60777           action.conflicts = function () {
60778             return _conflicts;
60779           };
60780
60781           return action;
60782         }
60783
60784         // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
60785
60786         function actionMove(moveIDs, tryDelta, projection, cache) {
60787           var _delta = tryDelta;
60788
60789           function setupCache(graph) {
60790             function canMove(nodeID) {
60791               // Allow movement of any node that is in the selectedIDs list..
60792               if (moveIDs.indexOf(nodeID) !== -1) return true; // Allow movement of a vertex where 2 ways meet..
60793
60794               var parents = graph.parentWays(graph.entity(nodeID));
60795               if (parents.length < 3) return true; // Restrict movement of a vertex where >2 ways meet, unless all parentWays are moving too..
60796
60797               var parentsMoving = parents.every(function (way) {
60798                 return cache.moving[way.id];
60799               });
60800               if (!parentsMoving) delete cache.moving[nodeID];
60801               return parentsMoving;
60802             }
60803
60804             function cacheEntities(ids) {
60805               for (var i = 0; i < ids.length; i++) {
60806                 var id = ids[i];
60807                 if (cache.moving[id]) continue;
60808                 cache.moving[id] = true;
60809                 var entity = graph.hasEntity(id);
60810                 if (!entity) continue;
60811
60812                 if (entity.type === 'node') {
60813                   cache.nodes.push(id);
60814                   cache.startLoc[id] = entity.loc;
60815                 } else if (entity.type === 'way') {
60816                   cache.ways.push(id);
60817                   cacheEntities(entity.nodes);
60818                 } else {
60819                   cacheEntities(entity.members.map(function (member) {
60820                     return member.id;
60821                   }));
60822                 }
60823               }
60824             }
60825
60826             function cacheIntersections(ids) {
60827               function isEndpoint(way, id) {
60828                 return !way.isClosed() && !!way.affix(id);
60829               }
60830
60831               for (var i = 0; i < ids.length; i++) {
60832                 var id = ids[i]; // consider only intersections with 1 moved and 1 unmoved way.
60833
60834                 var childNodes = graph.childNodes(graph.entity(id));
60835
60836                 for (var j = 0; j < childNodes.length; j++) {
60837                   var node = childNodes[j];
60838                   var parents = graph.parentWays(node);
60839                   if (parents.length !== 2) continue;
60840                   var moved = graph.entity(id);
60841                   var unmoved = null;
60842
60843                   for (var k = 0; k < parents.length; k++) {
60844                     var way = parents[k];
60845
60846                     if (!cache.moving[way.id]) {
60847                       unmoved = way;
60848                       break;
60849                     }
60850                   }
60851
60852                   if (!unmoved) continue; // exclude ways that are overly connected..
60853
60854                   if (utilArrayIntersection(moved.nodes, unmoved.nodes).length > 2) continue;
60855                   if (moved.isArea() || unmoved.isArea()) continue;
60856                   cache.intersections.push({
60857                     nodeId: node.id,
60858                     movedId: moved.id,
60859                     unmovedId: unmoved.id,
60860                     movedIsEP: isEndpoint(moved, node.id),
60861                     unmovedIsEP: isEndpoint(unmoved, node.id)
60862                   });
60863                 }
60864               }
60865             }
60866
60867             if (!cache) {
60868               cache = {};
60869             }
60870
60871             if (!cache.ok) {
60872               cache.moving = {};
60873               cache.intersections = [];
60874               cache.replacedVertex = {};
60875               cache.startLoc = {};
60876               cache.nodes = [];
60877               cache.ways = [];
60878               cacheEntities(moveIDs);
60879               cacheIntersections(cache.ways);
60880               cache.nodes = cache.nodes.filter(canMove);
60881               cache.ok = true;
60882             }
60883           } // Place a vertex where the moved vertex used to be, to preserve way shape..
60884           //
60885           //  Start:
60886           //      b ---- e
60887           //     / \
60888           //    /   \
60889           //   /     \
60890           //  a       c
60891           //
60892           //      *               node '*' added to preserve shape
60893           //     / \
60894           //    /   b ---- e      way `b,e` moved here:
60895           //   /     \
60896           //  a       c
60897           //
60898           //
60899
60900
60901           function replaceMovedVertex(nodeId, wayId, graph, delta) {
60902             var way = graph.entity(wayId);
60903             var moved = graph.entity(nodeId);
60904             var movedIndex = way.nodes.indexOf(nodeId);
60905             var len, prevIndex, nextIndex;
60906
60907             if (way.isClosed()) {
60908               len = way.nodes.length - 1;
60909               prevIndex = (movedIndex + len - 1) % len;
60910               nextIndex = (movedIndex + len + 1) % len;
60911             } else {
60912               len = way.nodes.length;
60913               prevIndex = movedIndex - 1;
60914               nextIndex = movedIndex + 1;
60915             }
60916
60917             var prev = graph.hasEntity(way.nodes[prevIndex]);
60918             var next = graph.hasEntity(way.nodes[nextIndex]); // Don't add orig vertex at endpoint..
60919
60920             if (!prev || !next) return graph;
60921             var key = wayId + '_' + nodeId;
60922             var orig = cache.replacedVertex[key];
60923
60924             if (!orig) {
60925               orig = osmNode();
60926               cache.replacedVertex[key] = orig;
60927               cache.startLoc[orig.id] = cache.startLoc[nodeId];
60928             }
60929
60930             var start, end;
60931
60932             if (delta) {
60933               start = projection(cache.startLoc[nodeId]);
60934               end = projection.invert(geoVecAdd(start, delta));
60935             } else {
60936               end = cache.startLoc[nodeId];
60937             }
60938
60939             orig = orig.move(end);
60940             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..
60941
60942             if (angle > 175 && angle < 185) return graph; // moving forward or backward along way?
60943
60944             var p1 = [prev.loc, orig.loc, moved.loc, next.loc].map(projection);
60945             var p2 = [prev.loc, moved.loc, orig.loc, next.loc].map(projection);
60946             var d1 = geoPathLength(p1);
60947             var d2 = geoPathLength(p2);
60948             var insertAt = d1 <= d2 ? movedIndex : nextIndex; // moving around closed loop?
60949
60950             if (way.isClosed() && insertAt === 0) insertAt = len;
60951             way = way.addNode(orig.id, insertAt);
60952             return graph.replace(orig).replace(way);
60953           } // Remove duplicate vertex that might have been added by
60954           // replaceMovedVertex.  This is done after the unzorro checks.
60955
60956
60957           function removeDuplicateVertices(wayId, graph) {
60958             var way = graph.entity(wayId);
60959             var epsilon = 1e-6;
60960             var prev, curr;
60961
60962             function isInteresting(node, graph) {
60963               return graph.parentWays(node).length > 1 || graph.parentRelations(node).length || node.hasInterestingTags();
60964             }
60965
60966             for (var i = 0; i < way.nodes.length; i++) {
60967               curr = graph.entity(way.nodes[i]);
60968
60969               if (prev && curr && geoVecEqual(prev.loc, curr.loc, epsilon)) {
60970                 if (!isInteresting(prev, graph)) {
60971                   way = way.removeNode(prev.id);
60972                   graph = graph.replace(way).remove(prev);
60973                 } else if (!isInteresting(curr, graph)) {
60974                   way = way.removeNode(curr.id);
60975                   graph = graph.replace(way).remove(curr);
60976                 }
60977               }
60978
60979               prev = curr;
60980             }
60981
60982             return graph;
60983           } // Reorder nodes around intersections that have moved..
60984           //
60985           //  Start:                way1.nodes: b,e         (moving)
60986           //  a - b - c ----- d     way2.nodes: a,b,c,d     (static)
60987           //      |                 vertex: b
60988           //      e                 isEP1: true,  isEP2, false
60989           //
60990           //  way1 `b,e` moved here:
60991           //  a ----- c = b - d
60992           //              |
60993           //              e
60994           //
60995           //  reorder nodes         way1.nodes: b,e
60996           //  a ----- c - b - d     way2.nodes: a,c,b,d
60997           //              |
60998           //              e
60999           //
61000
61001
61002           function unZorroIntersection(intersection, graph) {
61003             var vertex = graph.entity(intersection.nodeId);
61004             var way1 = graph.entity(intersection.movedId);
61005             var way2 = graph.entity(intersection.unmovedId);
61006             var isEP1 = intersection.movedIsEP;
61007             var isEP2 = intersection.unmovedIsEP; // don't move the vertex if it is the endpoint of both ways.
61008
61009             if (isEP1 && isEP2) return graph;
61010             var nodes1 = graph.childNodes(way1).filter(function (n) {
61011               return n !== vertex;
61012             });
61013             var nodes2 = graph.childNodes(way2).filter(function (n) {
61014               return n !== vertex;
61015             });
61016             if (way1.isClosed() && way1.first() === vertex.id) nodes1.push(nodes1[0]);
61017             if (way2.isClosed() && way2.first() === vertex.id) nodes2.push(nodes2[0]);
61018             var edge1 = !isEP1 && geoChooseEdge(nodes1, projection(vertex.loc), projection);
61019             var edge2 = !isEP2 && geoChooseEdge(nodes2, projection(vertex.loc), projection);
61020             var loc; // snap vertex to nearest edge (or some point between them)..
61021
61022             if (!isEP1 && !isEP2) {
61023               var epsilon = 1e-6,
61024                   maxIter = 10;
61025
61026               for (var i = 0; i < maxIter; i++) {
61027                 loc = geoVecInterp(edge1.loc, edge2.loc, 0.5);
61028                 edge1 = geoChooseEdge(nodes1, projection(loc), projection);
61029                 edge2 = geoChooseEdge(nodes2, projection(loc), projection);
61030                 if (Math.abs(edge1.distance - edge2.distance) < epsilon) break;
61031               }
61032             } else if (!isEP1) {
61033               loc = edge1.loc;
61034             } else {
61035               loc = edge2.loc;
61036             }
61037
61038             graph = graph.replace(vertex.move(loc)); // if zorro happened, reorder nodes..
61039
61040             if (!isEP1 && edge1.index !== way1.nodes.indexOf(vertex.id)) {
61041               way1 = way1.removeNode(vertex.id).addNode(vertex.id, edge1.index);
61042               graph = graph.replace(way1);
61043             }
61044
61045             if (!isEP2 && edge2.index !== way2.nodes.indexOf(vertex.id)) {
61046               way2 = way2.removeNode(vertex.id).addNode(vertex.id, edge2.index);
61047               graph = graph.replace(way2);
61048             }
61049
61050             return graph;
61051           }
61052
61053           function cleanupIntersections(graph) {
61054             for (var i = 0; i < cache.intersections.length; i++) {
61055               var obj = cache.intersections[i];
61056               graph = replaceMovedVertex(obj.nodeId, obj.movedId, graph, _delta);
61057               graph = replaceMovedVertex(obj.nodeId, obj.unmovedId, graph, null);
61058               graph = unZorroIntersection(obj, graph);
61059               graph = removeDuplicateVertices(obj.movedId, graph);
61060               graph = removeDuplicateVertices(obj.unmovedId, graph);
61061             }
61062
61063             return graph;
61064           } // check if moving way endpoint can cross an unmoved way, if so limit delta..
61065
61066
61067           function limitDelta(graph) {
61068             function moveNode(loc) {
61069               return geoVecAdd(projection(loc), _delta);
61070             }
61071
61072             for (var i = 0; i < cache.intersections.length; i++) {
61073               var obj = cache.intersections[i]; // Don't limit movement if this is vertex joins 2 endpoints..
61074
61075               if (obj.movedIsEP && obj.unmovedIsEP) continue; // Don't limit movement if this vertex is not an endpoint anyway..
61076
61077               if (!obj.movedIsEP) continue;
61078               var node = graph.entity(obj.nodeId);
61079               var start = projection(node.loc);
61080               var end = geoVecAdd(start, _delta);
61081               var movedNodes = graph.childNodes(graph.entity(obj.movedId));
61082               var movedPath = movedNodes.map(function (n) {
61083                 return moveNode(n.loc);
61084               });
61085               var unmovedNodes = graph.childNodes(graph.entity(obj.unmovedId));
61086               var unmovedPath = unmovedNodes.map(function (n) {
61087                 return projection(n.loc);
61088               });
61089               var hits = geoPathIntersections(movedPath, unmovedPath);
61090
61091               for (var j = 0; i < hits.length; i++) {
61092                 if (geoVecEqual(hits[j], end)) continue;
61093                 var edge = geoChooseEdge(unmovedNodes, end, projection);
61094                 _delta = geoVecSubtract(projection(edge.loc), start);
61095               }
61096             }
61097           }
61098
61099           var action = function action(graph) {
61100             if (_delta[0] === 0 && _delta[1] === 0) return graph;
61101             setupCache(graph);
61102
61103             if (cache.intersections.length) {
61104               limitDelta(graph);
61105             }
61106
61107             for (var i = 0; i < cache.nodes.length; i++) {
61108               var node = graph.entity(cache.nodes[i]);
61109               var start = projection(node.loc);
61110               var end = geoVecAdd(start, _delta);
61111               graph = graph.replace(node.move(projection.invert(end)));
61112             }
61113
61114             if (cache.intersections.length) {
61115               graph = cleanupIntersections(graph);
61116             }
61117
61118             return graph;
61119           };
61120
61121           action.delta = function () {
61122             return _delta;
61123           };
61124
61125           return action;
61126         }
61127
61128         function actionMoveMember(relationId, fromIndex, toIndex) {
61129           return function (graph) {
61130             return graph.replace(graph.entity(relationId).moveMember(fromIndex, toIndex));
61131           };
61132         }
61133
61134         function actionMoveNode(nodeID, toLoc) {
61135           var action = function action(graph, t) {
61136             if (t === null || !isFinite(t)) t = 1;
61137             t = Math.min(Math.max(+t, 0), 1);
61138             var node = graph.entity(nodeID);
61139             return graph.replace(node.move(geoVecInterp(node.loc, toLoc, t)));
61140           };
61141
61142           action.transitionable = true;
61143           return action;
61144         }
61145
61146         function actionNoop() {
61147           return function (graph) {
61148             return graph;
61149           };
61150         }
61151
61152         function actionOrthogonalize(wayID, projection, vertexID, degThresh, ep) {
61153           var epsilon = ep || 1e-4;
61154           var threshold = degThresh || 13; // degrees within right or straight to alter
61155           // We test normalized dot products so we can compare as cos(angle)
61156
61157           var lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180);
61158           var upperThreshold = Math.cos(threshold * Math.PI / 180);
61159
61160           var action = function action(graph, t) {
61161             if (t === null || !isFinite(t)) t = 1;
61162             t = Math.min(Math.max(+t, 0), 1);
61163             var way = graph.entity(wayID);
61164             way = way.removeNode(''); // sanity check - remove any consecutive duplicates
61165
61166             if (way.tags.nonsquare) {
61167               var tags = Object.assign({}, way.tags); // since we're squaring, remove indication that this is physically unsquare
61168
61169               delete tags.nonsquare;
61170               way = way.update({
61171                 tags: tags
61172               });
61173             }
61174
61175             graph = graph.replace(way);
61176             var isClosed = way.isClosed();
61177             var nodes = graph.childNodes(way).slice(); // shallow copy
61178
61179             if (isClosed) nodes.pop();
61180
61181             if (vertexID !== undefined) {
61182               nodes = nodeSubset(nodes, vertexID, isClosed);
61183               if (nodes.length !== 3) return graph;
61184             } // note: all geometry functions here use the unclosed node/point/coord list
61185
61186
61187             var nodeCount = {};
61188             var points = [];
61189             var corner = {
61190               i: 0,
61191               dotp: 1
61192             };
61193             var node, point, loc, score, motions, i, j;
61194
61195             for (i = 0; i < nodes.length; i++) {
61196               node = nodes[i];
61197               nodeCount[node.id] = (nodeCount[node.id] || 0) + 1;
61198               points.push({
61199                 id: node.id,
61200                 coord: projection(node.loc)
61201               });
61202             }
61203
61204             if (points.length === 3) {
61205               // move only one vertex for right triangle
61206               for (i = 0; i < 1000; i++) {
61207                 motions = points.map(calcMotion);
61208                 points[corner.i].coord = geoVecAdd(points[corner.i].coord, motions[corner.i]);
61209                 score = corner.dotp;
61210
61211                 if (score < epsilon) {
61212                   break;
61213                 }
61214               }
61215
61216               node = graph.entity(nodes[corner.i].id);
61217               loc = projection.invert(points[corner.i].coord);
61218               graph = graph.replace(node.move(geoVecInterp(node.loc, loc, t)));
61219             } else {
61220               var straights = [];
61221               var simplified = []; // Remove points from nearly straight sections..
61222               // This produces a simplified shape to orthogonalize
61223
61224               for (i = 0; i < points.length; i++) {
61225                 point = points[i];
61226                 var dotp = 0;
61227
61228                 if (isClosed || i > 0 && i < points.length - 1) {
61229                   var a = points[(i - 1 + points.length) % points.length];
61230                   var b = points[(i + 1) % points.length];
61231                   dotp = Math.abs(geoOrthoNormalizedDotProduct(a.coord, b.coord, point.coord));
61232                 }
61233
61234                 if (dotp > upperThreshold) {
61235                   straights.push(point);
61236                 } else {
61237                   simplified.push(point);
61238                 }
61239               } // Orthogonalize the simplified shape
61240
61241
61242               var bestPoints = clonePoints(simplified);
61243               var originalPoints = clonePoints(simplified);
61244               score = Infinity;
61245
61246               for (i = 0; i < 1000; i++) {
61247                 motions = simplified.map(calcMotion);
61248
61249                 for (j = 0; j < motions.length; j++) {
61250                   simplified[j].coord = geoVecAdd(simplified[j].coord, motions[j]);
61251                 }
61252
61253                 var newScore = geoOrthoCalcScore(simplified, isClosed, epsilon, threshold);
61254
61255                 if (newScore < score) {
61256                   bestPoints = clonePoints(simplified);
61257                   score = newScore;
61258                 }
61259
61260                 if (score < epsilon) {
61261                   break;
61262                 }
61263               }
61264
61265               var bestCoords = bestPoints.map(function (p) {
61266                 return p.coord;
61267               });
61268               if (isClosed) bestCoords.push(bestCoords[0]); // move the nodes that should move
61269
61270               for (i = 0; i < bestPoints.length; i++) {
61271                 point = bestPoints[i];
61272
61273                 if (!geoVecEqual(originalPoints[i].coord, point.coord)) {
61274                   node = graph.entity(point.id);
61275                   loc = projection.invert(point.coord);
61276                   graph = graph.replace(node.move(geoVecInterp(node.loc, loc, t)));
61277                 }
61278               } // move the nodes along straight segments
61279
61280
61281               for (i = 0; i < straights.length; i++) {
61282                 point = straights[i];
61283                 if (nodeCount[point.id] > 1) continue; // skip self-intersections
61284
61285                 node = graph.entity(point.id);
61286
61287                 if (t === 1 && graph.parentWays(node).length === 1 && graph.parentRelations(node).length === 0 && !node.hasInterestingTags()) {
61288                   // remove uninteresting points..
61289                   graph = actionDeleteNode(node.id)(graph);
61290                 } else {
61291                   // move interesting points to the nearest edge..
61292                   var choice = geoVecProject(point.coord, bestCoords);
61293
61294                   if (choice) {
61295                     loc = projection.invert(choice.target);
61296                     graph = graph.replace(node.move(geoVecInterp(node.loc, loc, t)));
61297                   }
61298                 }
61299               }
61300             }
61301
61302             return graph;
61303
61304             function clonePoints(array) {
61305               return array.map(function (p) {
61306                 return {
61307                   id: p.id,
61308                   coord: [p.coord[0], p.coord[1]]
61309                 };
61310               });
61311             }
61312
61313             function calcMotion(point, i, array) {
61314               // don't try to move the endpoints of a non-closed way.
61315               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)
61316
61317               if (nodeCount[array[i].id] > 1) return [0, 0];
61318               var a = array[(i - 1 + array.length) % array.length].coord;
61319               var origin = point.coord;
61320               var b = array[(i + 1) % array.length].coord;
61321               var p = geoVecSubtract(a, origin);
61322               var q = geoVecSubtract(b, origin);
61323               var scale = 2 * Math.min(geoVecLength(p), geoVecLength(q));
61324               p = geoVecNormalize(p);
61325               q = geoVecNormalize(q);
61326               var dotp = p[0] * q[0] + p[1] * q[1];
61327               var val = Math.abs(dotp);
61328
61329               if (val < lowerThreshold) {
61330                 // nearly orthogonal
61331                 corner.i = i;
61332                 corner.dotp = val;
61333                 var vec = geoVecNormalize(geoVecAdd(p, q));
61334                 return geoVecScale(vec, 0.1 * dotp * scale);
61335               }
61336
61337               return [0, 0]; // do nothing
61338             }
61339           }; // if we are only orthogonalizing one vertex,
61340           // get that vertex and the previous and next
61341
61342
61343           function nodeSubset(nodes, vertexID, isClosed) {
61344             var first = isClosed ? 0 : 1;
61345             var last = isClosed ? nodes.length : nodes.length - 1;
61346
61347             for (var i = first; i < last; i++) {
61348               if (nodes[i].id === vertexID) {
61349                 return [nodes[(i - 1 + nodes.length) % nodes.length], nodes[i], nodes[(i + 1) % nodes.length]];
61350               }
61351             }
61352
61353             return [];
61354           }
61355
61356           action.disabled = function (graph) {
61357             var way = graph.entity(wayID);
61358             way = way.removeNode(''); // sanity check - remove any consecutive duplicates
61359
61360             graph = graph.replace(way);
61361             var isClosed = way.isClosed();
61362             var nodes = graph.childNodes(way).slice(); // shallow copy
61363
61364             if (isClosed) nodes.pop();
61365             var allowStraightAngles = false;
61366
61367             if (vertexID !== undefined) {
61368               allowStraightAngles = true;
61369               nodes = nodeSubset(nodes, vertexID, isClosed);
61370               if (nodes.length !== 3) return 'end_vertex';
61371             }
61372
61373             var coords = nodes.map(function (n) {
61374               return projection(n.loc);
61375             });
61376             var score = geoOrthoCanOrthogonalize(coords, isClosed, epsilon, threshold, allowStraightAngles);
61377
61378             if (score === null) {
61379               return 'not_squarish';
61380             } else if (score === 0) {
61381               return 'square_enough';
61382             } else {
61383               return false;
61384             }
61385           };
61386
61387           action.transitionable = true;
61388           return action;
61389         }
61390
61391         //
61392         // `turn` must be an `osmTurn` object
61393         // see osm/intersection.js, pathToTurn()
61394         //
61395         // This specifies a restriction of type `restriction` when traveling from
61396         // `turn.from.way` toward `turn.to.way` via `turn.via.node` OR `turn.via.ways`.
61397         // (The action does not check that these entities form a valid intersection.)
61398         //
61399         // From, to, and via ways should be split before calling this action.
61400         // (old versions of the code would split the ways here, but we no longer do it)
61401         //
61402         // For testing convenience, accepts a restrictionID to assign to the new
61403         // relation. Normally, this will be undefined and the relation will
61404         // automatically be assigned a new ID.
61405         //
61406
61407         function actionRestrictTurn(turn, restrictionType, restrictionID) {
61408           return function (graph) {
61409             var fromWay = graph.entity(turn.from.way);
61410             var toWay = graph.entity(turn.to.way);
61411             var viaNode = turn.via.node && graph.entity(turn.via.node);
61412             var viaWays = turn.via.ways && turn.via.ways.map(function (id) {
61413               return graph.entity(id);
61414             });
61415             var members = [];
61416             members.push({
61417               id: fromWay.id,
61418               type: 'way',
61419               role: 'from'
61420             });
61421
61422             if (viaNode) {
61423               members.push({
61424                 id: viaNode.id,
61425                 type: 'node',
61426                 role: 'via'
61427               });
61428             } else if (viaWays) {
61429               viaWays.forEach(function (viaWay) {
61430                 members.push({
61431                   id: viaWay.id,
61432                   type: 'way',
61433                   role: 'via'
61434                 });
61435               });
61436             }
61437
61438             members.push({
61439               id: toWay.id,
61440               type: 'way',
61441               role: 'to'
61442             });
61443             return graph.replace(osmRelation({
61444               id: restrictionID,
61445               tags: {
61446                 type: 'restriction',
61447                 restriction: restrictionType
61448               },
61449               members: members
61450             }));
61451           };
61452         }
61453
61454         function actionRevert(id) {
61455           var action = function action(graph) {
61456             var entity = graph.hasEntity(id),
61457                 base = graph.base().entities[id];
61458
61459             if (entity && !base) {
61460               // entity will be removed..
61461               if (entity.type === 'node') {
61462                 graph.parentWays(entity).forEach(function (parent) {
61463                   parent = parent.removeNode(id);
61464                   graph = graph.replace(parent);
61465
61466                   if (parent.isDegenerate()) {
61467                     graph = actionDeleteWay(parent.id)(graph);
61468                   }
61469                 });
61470               }
61471
61472               graph.parentRelations(entity).forEach(function (parent) {
61473                 parent = parent.removeMembersWithID(id);
61474                 graph = graph.replace(parent);
61475
61476                 if (parent.isDegenerate()) {
61477                   graph = actionDeleteRelation(parent.id)(graph);
61478                 }
61479               });
61480             }
61481
61482             return graph.revert(id);
61483           };
61484
61485           return action;
61486         }
61487
61488         function actionRotate(rotateIds, pivot, angle, projection) {
61489           var action = function action(graph) {
61490             return graph.update(function (graph) {
61491               utilGetAllNodes(rotateIds, graph).forEach(function (node) {
61492                 var point = geoRotate([projection(node.loc)], angle, pivot)[0];
61493                 graph = graph.replace(node.move(projection.invert(point)));
61494               });
61495             });
61496           };
61497
61498           return action;
61499         }
61500
61501         function actionScale(ids, pivotLoc, scaleFactor, projection) {
61502           return function (graph) {
61503             return graph.update(function (graph) {
61504               var point, radial;
61505               utilGetAllNodes(ids, graph).forEach(function (node) {
61506                 point = projection(node.loc);
61507                 radial = [point[0] - pivotLoc[0], point[1] - pivotLoc[1]];
61508                 point = [pivotLoc[0] + scaleFactor * radial[0], pivotLoc[1] + scaleFactor * radial[1]];
61509                 graph = graph.replace(node.move(projection.invert(point)));
61510               });
61511             });
61512           };
61513         }
61514
61515         /* Align nodes along their common axis */
61516
61517         function actionStraightenNodes(nodeIDs, projection) {
61518           function positionAlongWay(a, o, b) {
61519             return geoVecDot(a, b, o) / geoVecDot(b, b, o);
61520           } // returns the endpoints of the long axis of symmetry of the `points` bounding rect
61521
61522
61523           function getEndpoints(points) {
61524             var ssr = geoGetSmallestSurroundingRectangle(points); // Choose line pq = axis of symmetry.
61525             // The shape's surrounding rectangle has 2 axes of symmetry.
61526             // Snap points to the long axis
61527
61528             var p1 = [(ssr.poly[0][0] + ssr.poly[1][0]) / 2, (ssr.poly[0][1] + ssr.poly[1][1]) / 2];
61529             var q1 = [(ssr.poly[2][0] + ssr.poly[3][0]) / 2, (ssr.poly[2][1] + ssr.poly[3][1]) / 2];
61530             var p2 = [(ssr.poly[3][0] + ssr.poly[4][0]) / 2, (ssr.poly[3][1] + ssr.poly[4][1]) / 2];
61531             var q2 = [(ssr.poly[1][0] + ssr.poly[2][0]) / 2, (ssr.poly[1][1] + ssr.poly[2][1]) / 2];
61532             var isLong = geoVecLength(p1, q1) > geoVecLength(p2, q2);
61533
61534             if (isLong) {
61535               return [p1, q1];
61536             }
61537
61538             return [p2, q2];
61539           }
61540
61541           var action = function action(graph, t) {
61542             if (t === null || !isFinite(t)) t = 1;
61543             t = Math.min(Math.max(+t, 0), 1);
61544             var nodes = nodeIDs.map(function (id) {
61545               return graph.entity(id);
61546             });
61547             var points = nodes.map(function (n) {
61548               return projection(n.loc);
61549             });
61550             var endpoints = getEndpoints(points);
61551             var startPoint = endpoints[0];
61552             var endPoint = endpoints[1]; // Move points onto the line connecting the endpoints
61553
61554             for (var i = 0; i < points.length; i++) {
61555               var node = nodes[i];
61556               var point = points[i];
61557               var u = positionAlongWay(point, startPoint, endPoint);
61558               var point2 = geoVecInterp(startPoint, endPoint, u);
61559               var loc2 = projection.invert(point2);
61560               graph = graph.replace(node.move(geoVecInterp(node.loc, loc2, t)));
61561             }
61562
61563             return graph;
61564           };
61565
61566           action.disabled = function (graph) {
61567             var nodes = nodeIDs.map(function (id) {
61568               return graph.entity(id);
61569             });
61570             var points = nodes.map(function (n) {
61571               return projection(n.loc);
61572             });
61573             var endpoints = getEndpoints(points);
61574             var startPoint = endpoints[0];
61575             var endPoint = endpoints[1];
61576             var maxDistance = 0;
61577
61578             for (var i = 0; i < points.length; i++) {
61579               var point = points[i];
61580               var u = positionAlongWay(point, startPoint, endPoint);
61581               var p = geoVecInterp(startPoint, endPoint, u);
61582               var dist = geoVecLength(p, point);
61583
61584               if (!isNaN(dist) && dist > maxDistance) {
61585                 maxDistance = dist;
61586               }
61587             }
61588
61589             if (maxDistance < 0.0001) {
61590               return 'straight_enough';
61591             }
61592           };
61593
61594           action.transitionable = true;
61595           return action;
61596         }
61597
61598         /*
61599          * Based on https://github.com/openstreetmap/potlatch2/net/systemeD/potlatch2/tools/Straighten.as
61600          */
61601
61602         function actionStraightenWay(selectedIDs, projection) {
61603           function positionAlongWay(a, o, b) {
61604             return geoVecDot(a, b, o) / geoVecDot(b, b, o);
61605           } // Return all selected ways as a continuous, ordered array of nodes
61606
61607
61608           function allNodes(graph) {
61609             var nodes = [];
61610             var startNodes = [];
61611             var endNodes = [];
61612             var remainingWays = [];
61613             var selectedWays = selectedIDs.filter(function (w) {
61614               return graph.entity(w).type === 'way';
61615             });
61616             var selectedNodes = selectedIDs.filter(function (n) {
61617               return graph.entity(n).type === 'node';
61618             });
61619
61620             for (var i = 0; i < selectedWays.length; i++) {
61621               var way = graph.entity(selectedWays[i]);
61622               nodes = way.nodes.slice(0);
61623               remainingWays.push(nodes);
61624               startNodes.push(nodes[0]);
61625               endNodes.push(nodes[nodes.length - 1]);
61626             } // Remove duplicate end/startNodes (duplicate nodes cannot be at the line end,
61627             //   and need to be removed so currNode difference calculation below works)
61628             // i.e. ["n-1", "n-1", "n-2"] => ["n-2"]
61629
61630
61631             startNodes = startNodes.filter(function (n) {
61632               return startNodes.indexOf(n) === startNodes.lastIndexOf(n);
61633             });
61634             endNodes = endNodes.filter(function (n) {
61635               return endNodes.indexOf(n) === endNodes.lastIndexOf(n);
61636             }); // Choose the initial endpoint to start from
61637
61638             var currNode = utilArrayDifference(startNodes, endNodes).concat(utilArrayDifference(endNodes, startNodes))[0];
61639             var nextWay = [];
61640             nodes = []; // Create nested function outside of loop to avoid "function in loop" lint error
61641
61642             var getNextWay = function getNextWay(currNode, remainingWays) {
61643               return remainingWays.filter(function (way) {
61644                 return way[0] === currNode || way[way.length - 1] === currNode;
61645               })[0];
61646             }; // Add nodes to end of nodes array, until all ways are added
61647
61648
61649             while (remainingWays.length) {
61650               nextWay = getNextWay(currNode, remainingWays);
61651               remainingWays = utilArrayDifference(remainingWays, [nextWay]);
61652
61653               if (nextWay[0] !== currNode) {
61654                 nextWay.reverse();
61655               }
61656
61657               nodes = nodes.concat(nextWay);
61658               currNode = nodes[nodes.length - 1];
61659             } // If user selected 2 nodes to straighten between, then slice nodes array to those nodes
61660
61661
61662             if (selectedNodes.length === 2) {
61663               var startNodeIdx = nodes.indexOf(selectedNodes[0]);
61664               var endNodeIdx = nodes.indexOf(selectedNodes[1]);
61665               var sortedStartEnd = [startNodeIdx, endNodeIdx];
61666               sortedStartEnd.sort(function (a, b) {
61667                 return a - b;
61668               });
61669               nodes = nodes.slice(sortedStartEnd[0], sortedStartEnd[1] + 1);
61670             }
61671
61672             return nodes.map(function (n) {
61673               return graph.entity(n);
61674             });
61675           }
61676
61677           function shouldKeepNode(node, graph) {
61678             return graph.parentWays(node).length > 1 || graph.parentRelations(node).length || node.hasInterestingTags();
61679           }
61680
61681           var action = function action(graph, t) {
61682             if (t === null || !isFinite(t)) t = 1;
61683             t = Math.min(Math.max(+t, 0), 1);
61684             var nodes = allNodes(graph);
61685             var points = nodes.map(function (n) {
61686               return projection(n.loc);
61687             });
61688             var startPoint = points[0];
61689             var endPoint = points[points.length - 1];
61690             var toDelete = [];
61691             var i;
61692
61693             for (i = 1; i < points.length - 1; i++) {
61694               var node = nodes[i];
61695               var point = points[i];
61696
61697               if (t < 1 || shouldKeepNode(node, graph)) {
61698                 var u = positionAlongWay(point, startPoint, endPoint);
61699                 var p = geoVecInterp(startPoint, endPoint, u);
61700                 var loc2 = projection.invert(p);
61701                 graph = graph.replace(node.move(geoVecInterp(node.loc, loc2, t)));
61702               } else {
61703                 // safe to delete
61704                 if (toDelete.indexOf(node) === -1) {
61705                   toDelete.push(node);
61706                 }
61707               }
61708             }
61709
61710             for (i = 0; i < toDelete.length; i++) {
61711               graph = actionDeleteNode(toDelete[i].id)(graph);
61712             }
61713
61714             return graph;
61715           };
61716
61717           action.disabled = function (graph) {
61718             // check way isn't too bendy
61719             var nodes = allNodes(graph);
61720             var points = nodes.map(function (n) {
61721               return projection(n.loc);
61722             });
61723             var startPoint = points[0];
61724             var endPoint = points[points.length - 1];
61725             var threshold = 0.2 * geoVecLength(startPoint, endPoint);
61726             var i;
61727
61728             if (threshold === 0) {
61729               return 'too_bendy';
61730             }
61731
61732             var maxDistance = 0;
61733
61734             for (i = 1; i < points.length - 1; i++) {
61735               var point = points[i];
61736               var u = positionAlongWay(point, startPoint, endPoint);
61737               var p = geoVecInterp(startPoint, endPoint, u);
61738               var dist = geoVecLength(p, point); // to bendy if point is off by 20% of total start/end distance in projected space
61739
61740               if (isNaN(dist) || dist > threshold) {
61741                 return 'too_bendy';
61742               } else if (dist > maxDistance) {
61743                 maxDistance = dist;
61744               }
61745             }
61746
61747             var keepingAllNodes = nodes.every(function (node, i) {
61748               return i === 0 || i === nodes.length - 1 || shouldKeepNode(node, graph);
61749             });
61750
61751             if (maxDistance < 0.0001 && // Allow straightening even if already straight in order to remove extraneous nodes
61752             keepingAllNodes) {
61753               return 'straight_enough';
61754             }
61755           };
61756
61757           action.transitionable = true;
61758           return action;
61759         }
61760
61761         //
61762         // `turn` must be an `osmTurn` object with a `restrictionID` property.
61763         // see osm/intersection.js, pathToTurn()
61764         //
61765
61766         function actionUnrestrictTurn(turn) {
61767           return function (graph) {
61768             return actionDeleteRelation(turn.restrictionID)(graph);
61769           };
61770         }
61771
61772         /* Reflect the given area around its axis of symmetry */
61773
61774         function actionReflect(reflectIds, projection) {
61775           var _useLongAxis = true;
61776
61777           var action = function action(graph, t) {
61778             if (t === null || !isFinite(t)) t = 1;
61779             t = Math.min(Math.max(+t, 0), 1);
61780             var nodes = utilGetAllNodes(reflectIds, graph);
61781             var points = nodes.map(function (n) {
61782               return projection(n.loc);
61783             });
61784             var ssr = geoGetSmallestSurroundingRectangle(points); // Choose line pq = axis of symmetry.
61785             // The shape's surrounding rectangle has 2 axes of symmetry.
61786             // Reflect across the longer axis by default.
61787
61788             var p1 = [(ssr.poly[0][0] + ssr.poly[1][0]) / 2, (ssr.poly[0][1] + ssr.poly[1][1]) / 2];
61789             var q1 = [(ssr.poly[2][0] + ssr.poly[3][0]) / 2, (ssr.poly[2][1] + ssr.poly[3][1]) / 2];
61790             var p2 = [(ssr.poly[3][0] + ssr.poly[4][0]) / 2, (ssr.poly[3][1] + ssr.poly[4][1]) / 2];
61791             var q2 = [(ssr.poly[1][0] + ssr.poly[2][0]) / 2, (ssr.poly[1][1] + ssr.poly[2][1]) / 2];
61792             var p, q;
61793             var isLong = geoVecLength(p1, q1) > geoVecLength(p2, q2);
61794
61795             if (_useLongAxis && isLong || !_useLongAxis && !isLong) {
61796               p = p1;
61797               q = q1;
61798             } else {
61799               p = p2;
61800               q = q2;
61801             } // reflect c across pq
61802             // http://math.stackexchange.com/questions/65503/point-reflection-over-a-line
61803
61804
61805             var dx = q[0] - p[0];
61806             var dy = q[1] - p[1];
61807             var a = (dx * dx - dy * dy) / (dx * dx + dy * dy);
61808             var b = 2 * dx * dy / (dx * dx + dy * dy);
61809
61810             for (var i = 0; i < nodes.length; i++) {
61811               var node = nodes[i];
61812               var c = projection(node.loc);
61813               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]];
61814               var loc2 = projection.invert(c2);
61815               node = node.move(geoVecInterp(node.loc, loc2, t));
61816               graph = graph.replace(node);
61817             }
61818
61819             return graph;
61820           };
61821
61822           action.useLongAxis = function (val) {
61823             if (!arguments.length) return _useLongAxis;
61824             _useLongAxis = val;
61825             return action;
61826           };
61827
61828           action.transitionable = true;
61829           return action;
61830         }
61831
61832         function actionUpgradeTags(entityId, oldTags, replaceTags) {
61833           return function (graph) {
61834             var entity = graph.entity(entityId);
61835             var tags = Object.assign({}, entity.tags); // shallow copy
61836
61837             var transferValue;
61838             var semiIndex;
61839
61840             for (var oldTagKey in oldTags) {
61841               if (!(oldTagKey in tags)) continue; // wildcard match
61842
61843               if (oldTags[oldTagKey] === '*') {
61844                 // note the value since we might need to transfer it
61845                 transferValue = tags[oldTagKey];
61846                 delete tags[oldTagKey]; // exact match
61847               } else if (oldTags[oldTagKey] === tags[oldTagKey]) {
61848                 delete tags[oldTagKey]; // match is within semicolon-delimited values
61849               } else {
61850                 var vals = tags[oldTagKey].split(';').filter(Boolean);
61851                 var oldIndex = vals.indexOf(oldTags[oldTagKey]);
61852
61853                 if (vals.length === 1 || oldIndex === -1) {
61854                   delete tags[oldTagKey];
61855                 } else {
61856                   if (replaceTags && replaceTags[oldTagKey]) {
61857                     // replacing a value within a semicolon-delimited value, note the index
61858                     semiIndex = oldIndex;
61859                   }
61860
61861                   vals.splice(oldIndex, 1);
61862                   tags[oldTagKey] = vals.join(';');
61863                 }
61864               }
61865             }
61866
61867             if (replaceTags) {
61868               for (var replaceKey in replaceTags) {
61869                 var replaceValue = replaceTags[replaceKey];
61870
61871                 if (replaceValue === '*') {
61872                   if (tags[replaceKey] && tags[replaceKey] !== 'no') {
61873                     // allow any pre-existing value except `no` (troll tag)
61874                     continue;
61875                   } else {
61876                     // otherwise assume `yes` is okay
61877                     tags[replaceKey] = 'yes';
61878                   }
61879                 } else if (replaceValue === '$1') {
61880                   tags[replaceKey] = transferValue;
61881                 } else {
61882                   if (tags[replaceKey] && oldTags[replaceKey] && semiIndex !== undefined) {
61883                     // don't override preexisting values
61884                     var existingVals = tags[replaceKey].split(';').filter(Boolean);
61885
61886                     if (existingVals.indexOf(replaceValue) === -1) {
61887                       existingVals.splice(semiIndex, 0, replaceValue);
61888                       tags[replaceKey] = existingVals.join(';');
61889                     }
61890                   } else {
61891                     tags[replaceKey] = replaceValue;
61892                   }
61893                 }
61894               }
61895             }
61896
61897             return graph.replace(entity.update({
61898               tags: tags
61899             }));
61900           };
61901         }
61902
61903         function behaviorEdit(context) {
61904           function behavior() {
61905             context.map().minzoom(context.minEditableZoom());
61906           }
61907
61908           behavior.off = function () {
61909             context.map().minzoom(0);
61910           };
61911
61912           return behavior;
61913         }
61914
61915         /*
61916            The hover behavior adds the `.hover` class on pointerover to all elements to which
61917            the identical datum is bound, and removes it on pointerout.
61918
61919            The :hover pseudo-class is insufficient for iD's purposes because a datum's visual
61920            representation may consist of several elements scattered throughout the DOM hierarchy.
61921            Only one of these elements can have the :hover pseudo-class, but all of them will
61922            have the .hover class.
61923          */
61924
61925         function behaviorHover(context) {
61926           var dispatch = dispatch$8('hover');
61927
61928           var _selection = select(null);
61929
61930           var _newNodeId = null;
61931           var _initialNodeID = null;
61932
61933           var _altDisables;
61934
61935           var _ignoreVertex;
61936
61937           var _targets = []; // use pointer events on supported platforms; fallback to mouse events
61938
61939           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
61940
61941           function keydown(d3_event) {
61942             if (_altDisables && d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
61943               _selection.selectAll('.hover').classed('hover-suppressed', true).classed('hover', false);
61944
61945               _selection.classed('hover-disabled', true);
61946
61947               dispatch.call('hover', this, null);
61948             }
61949           }
61950
61951           function keyup(d3_event) {
61952             if (_altDisables && d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
61953               _selection.selectAll('.hover-suppressed').classed('hover-suppressed', false).classed('hover', true);
61954
61955               _selection.classed('hover-disabled', false);
61956
61957               dispatch.call('hover', this, _targets);
61958             }
61959           }
61960
61961           function behavior(selection) {
61962             _selection = selection;
61963             _targets = [];
61964
61965             if (_initialNodeID) {
61966               _newNodeId = _initialNodeID;
61967               _initialNodeID = null;
61968             } else {
61969               _newNodeId = null;
61970             }
61971
61972             _selection.on(_pointerPrefix + 'over.hover', pointerover).on(_pointerPrefix + 'out.hover', pointerout) // treat pointerdown as pointerover for touch devices
61973             .on(_pointerPrefix + 'down.hover', pointerover);
61974
61975             select(window).on(_pointerPrefix + 'up.hover pointercancel.hover', pointerout, true).on('keydown.hover', keydown).on('keyup.hover', keyup);
61976
61977             function eventTarget(d3_event) {
61978               var datum = d3_event.target && d3_event.target.__data__;
61979               if (_typeof(datum) !== 'object') return null;
61980
61981               if (!(datum instanceof osmEntity) && datum.properties && datum.properties.entity instanceof osmEntity) {
61982                 return datum.properties.entity;
61983               }
61984
61985               return datum;
61986             }
61987
61988             function pointerover(d3_event) {
61989               // ignore mouse hovers with buttons pressed unless dragging
61990               if (context.mode().id.indexOf('drag') === -1 && (!d3_event.pointerType || d3_event.pointerType === 'mouse') && d3_event.buttons) return;
61991               var target = eventTarget(d3_event);
61992
61993               if (target && _targets.indexOf(target) === -1) {
61994                 _targets.push(target);
61995
61996                 updateHover(d3_event, _targets);
61997               }
61998             }
61999
62000             function pointerout(d3_event) {
62001               var target = eventTarget(d3_event);
62002
62003               var index = _targets.indexOf(target);
62004
62005               if (index !== -1) {
62006                 _targets.splice(index);
62007
62008                 updateHover(d3_event, _targets);
62009               }
62010             }
62011
62012             function allowsVertex(d) {
62013               return d.geometry(context.graph()) === 'vertex' || _mainPresetIndex.allowsVertex(d, context.graph());
62014             }
62015
62016             function modeAllowsHover(target) {
62017               var mode = context.mode();
62018
62019               if (mode.id === 'add-point') {
62020                 return mode.preset.matchGeometry('vertex') || target.type !== 'way' && target.geometry(context.graph()) !== 'vertex';
62021               }
62022
62023               return true;
62024             }
62025
62026             function updateHover(d3_event, targets) {
62027               _selection.selectAll('.hover').classed('hover', false);
62028
62029               _selection.selectAll('.hover-suppressed').classed('hover-suppressed', false);
62030
62031               var mode = context.mode();
62032
62033               if (!_newNodeId && (mode.id === 'draw-line' || mode.id === 'draw-area')) {
62034                 var node = targets.find(function (target) {
62035                   return target instanceof osmEntity && target.type === 'node';
62036                 });
62037                 _newNodeId = node && node.id;
62038               }
62039
62040               targets = targets.filter(function (datum) {
62041                 if (datum instanceof osmEntity) {
62042                   // If drawing a way, don't hover on a node that was just placed. #3974
62043                   return datum.id !== _newNodeId && (datum.type !== 'node' || !_ignoreVertex || allowsVertex(datum)) && modeAllowsHover(datum);
62044                 }
62045
62046                 return true;
62047               });
62048               var selector = '';
62049
62050               for (var i in targets) {
62051                 var datum = targets[i]; // What are we hovering over?
62052
62053                 if (datum.__featurehash__) {
62054                   // hovering custom data
62055                   selector += ', .data' + datum.__featurehash__;
62056                 } else if (datum instanceof QAItem) {
62057                   selector += ', .' + datum.service + '.itemId-' + datum.id;
62058                 } else if (datum instanceof osmNote) {
62059                   selector += ', .note-' + datum.id;
62060                 } else if (datum instanceof osmEntity) {
62061                   selector += ', .' + datum.id;
62062
62063                   if (datum.type === 'relation') {
62064                     for (var j in datum.members) {
62065                       selector += ', .' + datum.members[j].id;
62066                     }
62067                   }
62068                 }
62069               }
62070
62071               var suppressed = _altDisables && d3_event && d3_event.altKey;
62072
62073               if (selector.trim().length) {
62074                 // remove the first comma
62075                 selector = selector.slice(1);
62076
62077                 _selection.selectAll(selector).classed(suppressed ? 'hover-suppressed' : 'hover', true);
62078               }
62079
62080               dispatch.call('hover', this, !suppressed && targets);
62081             }
62082           }
62083
62084           behavior.off = function (selection) {
62085             selection.selectAll('.hover').classed('hover', false);
62086             selection.selectAll('.hover-suppressed').classed('hover-suppressed', false);
62087             selection.classed('hover-disabled', false);
62088             selection.on(_pointerPrefix + 'over.hover', null).on(_pointerPrefix + 'out.hover', null).on(_pointerPrefix + 'down.hover', null);
62089             select(window).on(_pointerPrefix + 'up.hover pointercancel.hover', null, true).on('keydown.hover', null).on('keyup.hover', null);
62090           };
62091
62092           behavior.altDisables = function (val) {
62093             if (!arguments.length) return _altDisables;
62094             _altDisables = val;
62095             return behavior;
62096           };
62097
62098           behavior.ignoreVertex = function (val) {
62099             if (!arguments.length) return _ignoreVertex;
62100             _ignoreVertex = val;
62101             return behavior;
62102           };
62103
62104           behavior.initialNodeID = function (nodeId) {
62105             _initialNodeID = nodeId;
62106             return behavior;
62107           };
62108
62109           return utilRebind(behavior, dispatch, 'on');
62110         }
62111
62112         var _disableSpace = false;
62113         var _lastSpace = null;
62114         function behaviorDraw(context) {
62115           var dispatch = dispatch$8('move', 'down', 'downcancel', 'click', 'clickWay', 'clickNode', 'undo', 'cancel', 'finish');
62116           var keybinding = utilKeybinding('draw');
62117
62118           var _hover = behaviorHover(context).altDisables(true).ignoreVertex(true).on('hover', context.ui().sidebar.hover);
62119
62120           var _edit = behaviorEdit(context);
62121
62122           var _closeTolerance = 4;
62123           var _tolerance = 12;
62124           var _mouseLeave = false;
62125           var _lastMouse = null;
62126
62127           var _lastPointerUpEvent;
62128
62129           var _downPointer; // use pointer events on supported platforms; fallback to mouse events
62130
62131
62132           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse'; // related code
62133           // - `mode/drag_node.js` `datum()`
62134
62135
62136           function datum(d3_event) {
62137             var mode = context.mode();
62138             var isNote = mode && mode.id.indexOf('note') !== -1;
62139             if (d3_event.altKey || isNote) return {};
62140             var element;
62141
62142             if (d3_event.type === 'keydown') {
62143               element = _lastMouse && _lastMouse.target;
62144             } else {
62145               element = d3_event.target;
62146             } // When drawing, snap only to touch targets..
62147             // (this excludes area fills and active drawing elements)
62148
62149
62150             var d = element.__data__;
62151             return d && d.properties && d.properties.target ? d : {};
62152           }
62153
62154           function pointerdown(d3_event) {
62155             if (_downPointer) return;
62156             var pointerLocGetter = utilFastMouse(this);
62157             _downPointer = {
62158               id: d3_event.pointerId || 'mouse',
62159               pointerLocGetter: pointerLocGetter,
62160               downTime: +new Date(),
62161               downLoc: pointerLocGetter(d3_event)
62162             };
62163             dispatch.call('down', this, d3_event, datum(d3_event));
62164           }
62165
62166           function pointerup(d3_event) {
62167             if (!_downPointer || _downPointer.id !== (d3_event.pointerId || 'mouse')) return;
62168             var downPointer = _downPointer;
62169             _downPointer = null;
62170             _lastPointerUpEvent = d3_event;
62171             if (downPointer.isCancelled) return;
62172             var t2 = +new Date();
62173             var p2 = downPointer.pointerLocGetter(d3_event);
62174             var dist = geoVecLength(downPointer.downLoc, p2);
62175
62176             if (dist < _closeTolerance || dist < _tolerance && t2 - downPointer.downTime < 500) {
62177               // Prevent a quick second click
62178               select(window).on('click.draw-block', function () {
62179                 d3_event.stopPropagation();
62180               }, true);
62181               context.map().dblclickZoomEnable(false);
62182               window.setTimeout(function () {
62183                 context.map().dblclickZoomEnable(true);
62184                 select(window).on('click.draw-block', null);
62185               }, 500);
62186               click(d3_event, p2);
62187             }
62188           }
62189
62190           function pointermove(d3_event) {
62191             if (_downPointer && _downPointer.id === (d3_event.pointerId || 'mouse') && !_downPointer.isCancelled) {
62192               var p2 = _downPointer.pointerLocGetter(d3_event);
62193
62194               var dist = geoVecLength(_downPointer.downLoc, p2);
62195
62196               if (dist >= _closeTolerance) {
62197                 _downPointer.isCancelled = true;
62198                 dispatch.call('downcancel', this);
62199               }
62200             }
62201
62202             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
62203             // events immediately after non-mouse pointerup events; detect and ignore them.
62204
62205             if (_lastPointerUpEvent && _lastPointerUpEvent.pointerType !== 'mouse' && d3_event.timeStamp - _lastPointerUpEvent.timeStamp < 100) return;
62206             _lastMouse = d3_event;
62207             dispatch.call('move', this, d3_event, datum(d3_event));
62208           }
62209
62210           function pointercancel(d3_event) {
62211             if (_downPointer && _downPointer.id === (d3_event.pointerId || 'mouse')) {
62212               if (!_downPointer.isCancelled) {
62213                 dispatch.call('downcancel', this);
62214               }
62215
62216               _downPointer = null;
62217             }
62218           }
62219
62220           function mouseenter() {
62221             _mouseLeave = false;
62222           }
62223
62224           function mouseleave() {
62225             _mouseLeave = true;
62226           }
62227
62228           function allowsVertex(d) {
62229             return d.geometry(context.graph()) === 'vertex' || _mainPresetIndex.allowsVertex(d, context.graph());
62230           } // related code
62231           // - `mode/drag_node.js`     `doMove()`
62232           // - `behavior/draw.js`      `click()`
62233           // - `behavior/draw_way.js`  `move()`
62234
62235
62236           function click(d3_event, loc) {
62237             var d = datum(d3_event);
62238             var target = d && d.properties && d.properties.entity;
62239             var mode = context.mode();
62240
62241             if (target && target.type === 'node' && allowsVertex(target)) {
62242               // Snap to a node
62243               dispatch.call('clickNode', this, target, d);
62244               return;
62245             } else if (target && target.type === 'way' && (mode.id !== 'add-point' || mode.preset.matchGeometry('vertex'))) {
62246               // Snap to a way
62247               var choice = geoChooseEdge(context.graph().childNodes(target), loc, context.projection, context.activeID());
62248
62249               if (choice) {
62250                 var edge = [target.nodes[choice.index - 1], target.nodes[choice.index]];
62251                 dispatch.call('clickWay', this, choice.loc, edge, d);
62252                 return;
62253               }
62254             } else if (mode.id !== 'add-point' || mode.preset.matchGeometry('point')) {
62255               var locLatLng = context.projection.invert(loc);
62256               dispatch.call('click', this, locLatLng, d);
62257             }
62258           } // treat a spacebar press like a click
62259
62260
62261           function space(d3_event) {
62262             d3_event.preventDefault();
62263             d3_event.stopPropagation();
62264             var currSpace = context.map().mouse();
62265
62266             if (_disableSpace && _lastSpace) {
62267               var dist = geoVecLength(_lastSpace, currSpace);
62268
62269               if (dist > _tolerance) {
62270                 _disableSpace = false;
62271               }
62272             }
62273
62274             if (_disableSpace || _mouseLeave || !_lastMouse) return; // user must move mouse or release space bar to allow another click
62275
62276             _lastSpace = currSpace;
62277             _disableSpace = true;
62278             select(window).on('keyup.space-block', function () {
62279               d3_event.preventDefault();
62280               d3_event.stopPropagation();
62281               _disableSpace = false;
62282               select(window).on('keyup.space-block', null);
62283             }); // get the current mouse position
62284
62285             var loc = context.map().mouse() || // or the map center if the mouse has never entered the map
62286             context.projection(context.map().center());
62287             click(d3_event, loc);
62288           }
62289
62290           function backspace(d3_event) {
62291             d3_event.preventDefault();
62292             dispatch.call('undo');
62293           }
62294
62295           function del(d3_event) {
62296             d3_event.preventDefault();
62297             dispatch.call('cancel');
62298           }
62299
62300           function ret(d3_event) {
62301             d3_event.preventDefault();
62302             dispatch.call('finish');
62303           }
62304
62305           function behavior(selection) {
62306             context.install(_hover);
62307             context.install(_edit);
62308             _downPointer = null;
62309             keybinding.on('⌫', backspace).on('⌦', del).on('⎋', ret).on('↩', ret).on('space', space).on('⌥space', space);
62310             selection.on('mouseenter.draw', mouseenter).on('mouseleave.draw', mouseleave).on(_pointerPrefix + 'down.draw', pointerdown).on(_pointerPrefix + 'move.draw', pointermove);
62311             select(window).on(_pointerPrefix + 'up.draw', pointerup, true).on('pointercancel.draw', pointercancel, true);
62312             select(document).call(keybinding);
62313             return behavior;
62314           }
62315
62316           behavior.off = function (selection) {
62317             context.ui().sidebar.hover.cancel();
62318             context.uninstall(_hover);
62319             context.uninstall(_edit);
62320             selection.on('mouseenter.draw', null).on('mouseleave.draw', null).on(_pointerPrefix + 'down.draw', null).on(_pointerPrefix + 'move.draw', null);
62321             select(window).on(_pointerPrefix + 'up.draw', null).on('pointercancel.draw', null); // note: keyup.space-block, click.draw-block should remain
62322
62323             select(document).call(keybinding.unbind);
62324           };
62325
62326           behavior.hover = function () {
62327             return _hover;
62328           };
62329
62330           return utilRebind(behavior, dispatch, 'on');
62331         }
62332
62333         function initRange(domain, range) {
62334           switch (arguments.length) {
62335             case 0:
62336               break;
62337
62338             case 1:
62339               this.range(domain);
62340               break;
62341
62342             default:
62343               this.range(range).domain(domain);
62344               break;
62345           }
62346
62347           return this;
62348         }
62349
62350         function constants(x) {
62351           return function () {
62352             return x;
62353           };
62354         }
62355
62356         function number(x) {
62357           return +x;
62358         }
62359
62360         var unit = [0, 1];
62361         function identity$1(x) {
62362           return x;
62363         }
62364
62365         function normalize(a, b) {
62366           return (b -= a = +a) ? function (x) {
62367             return (x - a) / b;
62368           } : constants(isNaN(b) ? NaN : 0.5);
62369         }
62370
62371         function clamper(a, b) {
62372           var t;
62373           if (a > b) t = a, a = b, b = t;
62374           return function (x) {
62375             return Math.max(a, Math.min(b, x));
62376           };
62377         } // normalize(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1].
62378         // interpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding range value x in [a,b].
62379
62380
62381         function bimap(domain, range, interpolate) {
62382           var d0 = domain[0],
62383               d1 = domain[1],
62384               r0 = range[0],
62385               r1 = range[1];
62386           if (d1 < d0) d0 = normalize(d1, d0), r0 = interpolate(r1, r0);else d0 = normalize(d0, d1), r0 = interpolate(r0, r1);
62387           return function (x) {
62388             return r0(d0(x));
62389           };
62390         }
62391
62392         function polymap(domain, range, interpolate) {
62393           var j = Math.min(domain.length, range.length) - 1,
62394               d = new Array(j),
62395               r = new Array(j),
62396               i = -1; // Reverse descending domains.
62397
62398           if (domain[j] < domain[0]) {
62399             domain = domain.slice().reverse();
62400             range = range.slice().reverse();
62401           }
62402
62403           while (++i < j) {
62404             d[i] = normalize(domain[i], domain[i + 1]);
62405             r[i] = interpolate(range[i], range[i + 1]);
62406           }
62407
62408           return function (x) {
62409             var i = bisectRight(domain, x, 1, j) - 1;
62410             return r[i](d[i](x));
62411           };
62412         }
62413
62414         function copy(source, target) {
62415           return target.domain(source.domain()).range(source.range()).interpolate(source.interpolate()).clamp(source.clamp()).unknown(source.unknown());
62416         }
62417         function transformer() {
62418           var domain = unit,
62419               range = unit,
62420               interpolate = interpolate$1,
62421               transform,
62422               untransform,
62423               unknown,
62424               clamp = identity$1,
62425               piecewise,
62426               output,
62427               input;
62428
62429           function rescale() {
62430             var n = Math.min(domain.length, range.length);
62431             if (clamp !== identity$1) clamp = clamper(domain[0], domain[n - 1]);
62432             piecewise = n > 2 ? polymap : bimap;
62433             output = input = null;
62434             return scale;
62435           }
62436
62437           function scale(x) {
62438             return x == null || isNaN(x = +x) ? unknown : (output || (output = piecewise(domain.map(transform), range, interpolate)))(transform(clamp(x)));
62439           }
62440
62441           scale.invert = function (y) {
62442             return clamp(untransform((input || (input = piecewise(range, domain.map(transform), d3_interpolateNumber)))(y)));
62443           };
62444
62445           scale.domain = function (_) {
62446             return arguments.length ? (domain = Array.from(_, number), rescale()) : domain.slice();
62447           };
62448
62449           scale.range = function (_) {
62450             return arguments.length ? (range = Array.from(_), rescale()) : range.slice();
62451           };
62452
62453           scale.rangeRound = function (_) {
62454             return range = Array.from(_), interpolate = interpolateRound, rescale();
62455           };
62456
62457           scale.clamp = function (_) {
62458             return arguments.length ? (clamp = _ ? true : identity$1, rescale()) : clamp !== identity$1;
62459           };
62460
62461           scale.interpolate = function (_) {
62462             return arguments.length ? (interpolate = _, rescale()) : interpolate;
62463           };
62464
62465           scale.unknown = function (_) {
62466             return arguments.length ? (unknown = _, scale) : unknown;
62467           };
62468
62469           return function (t, u) {
62470             transform = t, untransform = u;
62471             return rescale();
62472           };
62473         }
62474         function continuous() {
62475           return transformer()(identity$1, identity$1);
62476         }
62477
62478         function formatDecimal (x) {
62479           return Math.abs(x = Math.round(x)) >= 1e21 ? x.toLocaleString("en").replace(/,/g, "") : x.toString(10);
62480         } // Computes the decimal coefficient and exponent of the specified number x with
62481         // significant digits p, where x is positive and p is in [1, 21] or undefined.
62482         // For example, formatDecimalParts(1.23) returns ["123", 0].
62483
62484         function formatDecimalParts(x, p) {
62485           if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity
62486
62487           var i,
62488               coefficient = x.slice(0, i); // The string returned by toExponential either has the form \d\.\d+e[-+]\d+
62489           // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
62490
62491           return [coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient, +x.slice(i + 1)];
62492         }
62493
62494         function exponent (x) {
62495           return x = formatDecimalParts(Math.abs(x)), x ? x[1] : NaN;
62496         }
62497
62498         function formatGroup (grouping, thousands) {
62499           return function (value, width) {
62500             var i = value.length,
62501                 t = [],
62502                 j = 0,
62503                 g = grouping[0],
62504                 length = 0;
62505
62506             while (i > 0 && g > 0) {
62507               if (length + g + 1 > width) g = Math.max(1, width - length);
62508               t.push(value.substring(i -= g, i + g));
62509               if ((length += g + 1) > width) break;
62510               g = grouping[j = (j + 1) % grouping.length];
62511             }
62512
62513             return t.reverse().join(thousands);
62514           };
62515         }
62516
62517         function formatNumerals (numerals) {
62518           return function (value) {
62519             return value.replace(/[0-9]/g, function (i) {
62520               return numerals[+i];
62521             });
62522           };
62523         }
62524
62525         // [[fill]align][sign][symbol][0][width][,][.precision][~][type]
62526         var re = /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;
62527         function formatSpecifier(specifier) {
62528           if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
62529           var match;
62530           return new FormatSpecifier({
62531             fill: match[1],
62532             align: match[2],
62533             sign: match[3],
62534             symbol: match[4],
62535             zero: match[5],
62536             width: match[6],
62537             comma: match[7],
62538             precision: match[8] && match[8].slice(1),
62539             trim: match[9],
62540             type: match[10]
62541           });
62542         }
62543         formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof
62544
62545         function FormatSpecifier(specifier) {
62546           this.fill = specifier.fill === undefined ? " " : specifier.fill + "";
62547           this.align = specifier.align === undefined ? ">" : specifier.align + "";
62548           this.sign = specifier.sign === undefined ? "-" : specifier.sign + "";
62549           this.symbol = specifier.symbol === undefined ? "" : specifier.symbol + "";
62550           this.zero = !!specifier.zero;
62551           this.width = specifier.width === undefined ? undefined : +specifier.width;
62552           this.comma = !!specifier.comma;
62553           this.precision = specifier.precision === undefined ? undefined : +specifier.precision;
62554           this.trim = !!specifier.trim;
62555           this.type = specifier.type === undefined ? "" : specifier.type + "";
62556         }
62557
62558         FormatSpecifier.prototype.toString = function () {
62559           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;
62560         };
62561
62562         // Trims insignificant zeros, e.g., replaces 1.2000k with 1.2k.
62563         function formatTrim (s) {
62564           out: for (var n = s.length, i = 1, i0 = -1, i1; i < n; ++i) {
62565             switch (s[i]) {
62566               case ".":
62567                 i0 = i1 = i;
62568                 break;
62569
62570               case "0":
62571                 if (i0 === 0) i0 = i;
62572                 i1 = i;
62573                 break;
62574
62575               default:
62576                 if (!+s[i]) break out;
62577                 if (i0 > 0) i0 = 0;
62578                 break;
62579             }
62580           }
62581
62582           return i0 > 0 ? s.slice(0, i0) + s.slice(i1 + 1) : s;
62583         }
62584
62585         var $$5 = _export;
62586         var uncurryThis$3 = functionUncurryThis;
62587         var fails$3 = fails$S;
62588         var thisNumberValue = thisNumberValue$3;
62589
62590         var un$ToPrecision = uncurryThis$3(1.0.toPrecision);
62591
62592         var FORCED$1 = fails$3(function () {
62593           // IE7-
62594           return un$ToPrecision(1, undefined) !== '1';
62595         }) || !fails$3(function () {
62596           // V8 ~ Android 4.3-
62597           un$ToPrecision({});
62598         });
62599
62600         // `Number.prototype.toPrecision` method
62601         // https://tc39.es/ecma262/#sec-number.prototype.toprecision
62602         $$5({ target: 'Number', proto: true, forced: FORCED$1 }, {
62603           toPrecision: function toPrecision(precision) {
62604             return precision === undefined
62605               ? un$ToPrecision(thisNumberValue(this))
62606               : un$ToPrecision(thisNumberValue(this), precision);
62607           }
62608         });
62609
62610         var prefixExponent;
62611         function formatPrefixAuto (x, p) {
62612           var d = formatDecimalParts(x, p);
62613           if (!d) return x + "";
62614           var coefficient = d[0],
62615               exponent = d[1],
62616               i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
62617               n = coefficient.length;
62618           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!
62619         }
62620
62621         function formatRounded (x, p) {
62622           var d = formatDecimalParts(x, p);
62623           if (!d) return x + "";
62624           var coefficient = d[0],
62625               exponent = d[1];
62626           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");
62627         }
62628
62629         var formatTypes = {
62630           "%": function _(x, p) {
62631             return (x * 100).toFixed(p);
62632           },
62633           "b": function b(x) {
62634             return Math.round(x).toString(2);
62635           },
62636           "c": function c(x) {
62637             return x + "";
62638           },
62639           "d": formatDecimal,
62640           "e": function e(x, p) {
62641             return x.toExponential(p);
62642           },
62643           "f": function f(x, p) {
62644             return x.toFixed(p);
62645           },
62646           "g": function g(x, p) {
62647             return x.toPrecision(p);
62648           },
62649           "o": function o(x) {
62650             return Math.round(x).toString(8);
62651           },
62652           "p": function p(x, _p) {
62653             return formatRounded(x * 100, _p);
62654           },
62655           "r": formatRounded,
62656           "s": formatPrefixAuto,
62657           "X": function X(x) {
62658             return Math.round(x).toString(16).toUpperCase();
62659           },
62660           "x": function x(_x) {
62661             return Math.round(_x).toString(16);
62662           }
62663         };
62664
62665         function identity (x) {
62666           return x;
62667         }
62668
62669         var map$1 = Array.prototype.map,
62670             prefixes = ["y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y"];
62671         function formatLocale (locale) {
62672           var group = locale.grouping === undefined || locale.thousands === undefined ? identity : formatGroup(map$1.call(locale.grouping, Number), locale.thousands + ""),
62673               currencyPrefix = locale.currency === undefined ? "" : locale.currency[0] + "",
62674               currencySuffix = locale.currency === undefined ? "" : locale.currency[1] + "",
62675               decimal = locale.decimal === undefined ? "." : locale.decimal + "",
62676               numerals = locale.numerals === undefined ? identity : formatNumerals(map$1.call(locale.numerals, String)),
62677               percent = locale.percent === undefined ? "%" : locale.percent + "",
62678               minus = locale.minus === undefined ? "−" : locale.minus + "",
62679               nan = locale.nan === undefined ? "NaN" : locale.nan + "";
62680
62681           function newFormat(specifier) {
62682             specifier = formatSpecifier(specifier);
62683             var fill = specifier.fill,
62684                 align = specifier.align,
62685                 sign = specifier.sign,
62686                 symbol = specifier.symbol,
62687                 zero = specifier.zero,
62688                 width = specifier.width,
62689                 comma = specifier.comma,
62690                 precision = specifier.precision,
62691                 trim = specifier.trim,
62692                 type = specifier.type; // The "n" type is an alias for ",g".
62693
62694             if (type === "n") comma = true, type = "g"; // The "" type, and any invalid type, is an alias for ".12~g".
62695             else if (!formatTypes[type]) precision === undefined && (precision = 12), trim = true, type = "g"; // If zero fill is specified, padding goes after sign and before digits.
62696
62697             if (zero || fill === "0" && align === "=") zero = true, fill = "0", align = "="; // Compute the prefix and suffix.
62698             // For SI-prefix, the suffix is lazily computed.
62699
62700             var prefix = symbol === "$" ? currencyPrefix : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
62701                 suffix = symbol === "$" ? currencySuffix : /[%p]/.test(type) ? percent : ""; // What format function should we use?
62702             // Is this an integer type?
62703             // Can this type generate exponential notation?
62704
62705             var formatType = formatTypes[type],
62706                 maybeSuffix = /[defgprs%]/.test(type); // Set the default precision if not specified,
62707             // or clamp the specified precision to the supported range.
62708             // For significant precision, it must be in [1, 21].
62709             // For fixed precision, it must be in [0, 20].
62710
62711             precision = precision === undefined ? 6 : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision)) : Math.max(0, Math.min(20, precision));
62712
62713             function format(value) {
62714               var valuePrefix = prefix,
62715                   valueSuffix = suffix,
62716                   i,
62717                   n,
62718                   c;
62719
62720               if (type === "c") {
62721                 valueSuffix = formatType(value) + valueSuffix;
62722                 value = "";
62723               } else {
62724                 value = +value; // Determine the sign. -0 is not less than 0, but 1 / -0 is!
62725
62726                 var valueNegative = value < 0 || 1 / value < 0; // Perform the initial formatting.
62727
62728                 value = isNaN(value) ? nan : formatType(Math.abs(value), precision); // Trim insignificant zeros.
62729
62730                 if (trim) value = formatTrim(value); // If a negative value rounds to zero after formatting, and no explicit positive sign is requested, hide the sign.
62731
62732                 if (valueNegative && +value === 0 && sign !== "+") valueNegative = false; // Compute the prefix and suffix.
62733
62734                 valuePrefix = (valueNegative ? sign === "(" ? sign : minus : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
62735                 valueSuffix = (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : ""); // Break the formatted value into the integer “value” part that can be
62736                 // grouped, and fractional or exponential “suffix” part that is not.
62737
62738                 if (maybeSuffix) {
62739                   i = -1, n = value.length;
62740
62741                   while (++i < n) {
62742                     if (c = value.charCodeAt(i), 48 > c || c > 57) {
62743                       valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
62744                       value = value.slice(0, i);
62745                       break;
62746                     }
62747                   }
62748                 }
62749               } // If the fill character is not "0", grouping is applied before padding.
62750
62751
62752               if (comma && !zero) value = group(value, Infinity); // Compute the padding.
62753
62754               var length = valuePrefix.length + value.length + valueSuffix.length,
62755                   padding = length < width ? new Array(width - length + 1).join(fill) : ""; // If the fill character is "0", grouping is applied after padding.
62756
62757               if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = ""; // Reconstruct the final output based on the desired alignment.
62758
62759               switch (align) {
62760                 case "<":
62761                   value = valuePrefix + value + valueSuffix + padding;
62762                   break;
62763
62764                 case "=":
62765                   value = valuePrefix + padding + value + valueSuffix;
62766                   break;
62767
62768                 case "^":
62769                   value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length);
62770                   break;
62771
62772                 default:
62773                   value = padding + valuePrefix + value + valueSuffix;
62774                   break;
62775               }
62776
62777               return numerals(value);
62778             }
62779
62780             format.toString = function () {
62781               return specifier + "";
62782             };
62783
62784             return format;
62785           }
62786
62787           function formatPrefix(specifier, value) {
62788             var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
62789                 e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3,
62790                 k = Math.pow(10, -e),
62791                 prefix = prefixes[8 + e / 3];
62792             return function (value) {
62793               return f(k * value) + prefix;
62794             };
62795           }
62796
62797           return {
62798             format: newFormat,
62799             formatPrefix: formatPrefix
62800           };
62801         }
62802
62803         var locale;
62804         var format$1;
62805         var formatPrefix;
62806         defaultLocale({
62807           thousands: ",",
62808           grouping: [3],
62809           currency: ["$", ""]
62810         });
62811         function defaultLocale(definition) {
62812           locale = formatLocale(definition);
62813           format$1 = locale.format;
62814           formatPrefix = locale.formatPrefix;
62815           return locale;
62816         }
62817
62818         function precisionFixed (step) {
62819           return Math.max(0, -exponent(Math.abs(step)));
62820         }
62821
62822         function precisionPrefix (step, value) {
62823           return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3 - exponent(Math.abs(step)));
62824         }
62825
62826         function precisionRound (step, max) {
62827           step = Math.abs(step), max = Math.abs(max) - step;
62828           return Math.max(0, exponent(max) - exponent(step)) + 1;
62829         }
62830
62831         function tickFormat(start, stop, count, specifier) {
62832           var step = tickStep(start, stop, count),
62833               precision;
62834           specifier = formatSpecifier(specifier == null ? ",f" : specifier);
62835
62836           switch (specifier.type) {
62837             case "s":
62838               {
62839                 var value = Math.max(Math.abs(start), Math.abs(stop));
62840                 if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision;
62841                 return formatPrefix(specifier, value);
62842               }
62843
62844             case "":
62845             case "e":
62846             case "g":
62847             case "p":
62848             case "r":
62849               {
62850                 if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e");
62851                 break;
62852               }
62853
62854             case "f":
62855             case "%":
62856               {
62857                 if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2;
62858                 break;
62859               }
62860           }
62861
62862           return format$1(specifier);
62863         }
62864
62865         function linearish(scale) {
62866           var domain = scale.domain;
62867
62868           scale.ticks = function (count) {
62869             var d = domain();
62870             return ticks(d[0], d[d.length - 1], count == null ? 10 : count);
62871           };
62872
62873           scale.tickFormat = function (count, specifier) {
62874             var d = domain();
62875             return tickFormat(d[0], d[d.length - 1], count == null ? 10 : count, specifier);
62876           };
62877
62878           scale.nice = function (count) {
62879             if (count == null) count = 10;
62880             var d = domain();
62881             var i0 = 0;
62882             var i1 = d.length - 1;
62883             var start = d[i0];
62884             var stop = d[i1];
62885             var prestep;
62886             var step;
62887             var maxIter = 10;
62888
62889             if (stop < start) {
62890               step = start, start = stop, stop = step;
62891               step = i0, i0 = i1, i1 = step;
62892             }
62893
62894             while (maxIter-- > 0) {
62895               step = tickIncrement(start, stop, count);
62896
62897               if (step === prestep) {
62898                 d[i0] = start;
62899                 d[i1] = stop;
62900                 return domain(d);
62901               } else if (step > 0) {
62902                 start = Math.floor(start / step) * step;
62903                 stop = Math.ceil(stop / step) * step;
62904               } else if (step < 0) {
62905                 start = Math.ceil(start * step) / step;
62906                 stop = Math.floor(stop * step) / step;
62907               } else {
62908                 break;
62909               }
62910
62911               prestep = step;
62912             }
62913
62914             return scale;
62915           };
62916
62917           return scale;
62918         }
62919         function linear() {
62920           var scale = continuous();
62921
62922           scale.copy = function () {
62923             return copy(scale, linear());
62924           };
62925
62926           initRange.apply(scale, arguments);
62927           return linearish(scale);
62928         }
62929
62930         // eslint-disable-next-line es/no-math-expm1 -- safe
62931         var $expm1 = Math.expm1;
62932         var exp$1 = Math.exp;
62933
62934         // `Math.expm1` method implementation
62935         // https://tc39.es/ecma262/#sec-math.expm1
62936         var mathExpm1 = (!$expm1
62937           // Old FF bug
62938           || $expm1(10) > 22025.465794806719 || $expm1(10) < 22025.4657948067165168
62939           // Tor Browser bug
62940           || $expm1(-2e-17) != -2e-17
62941         ) ? function expm1(x) {
62942           return (x = +x) == 0 ? x : x > -1e-6 && x < 1e-6 ? x + x * x / 2 : exp$1(x) - 1;
62943         } : $expm1;
62944
62945         function quantize() {
62946           var x0 = 0,
62947               x1 = 1,
62948               n = 1,
62949               domain = [0.5],
62950               range = [0, 1],
62951               unknown;
62952
62953           function scale(x) {
62954             return x != null && x <= x ? range[bisectRight(domain, x, 0, n)] : unknown;
62955           }
62956
62957           function rescale() {
62958             var i = -1;
62959             domain = new Array(n);
62960
62961             while (++i < n) {
62962               domain[i] = ((i + 1) * x1 - (i - n) * x0) / (n + 1);
62963             }
62964
62965             return scale;
62966           }
62967
62968           scale.domain = function (_) {
62969             var _ref, _ref2;
62970
62971             return arguments.length ? ((_ref = _, _ref2 = _slicedToArray(_ref, 2), x0 = _ref2[0], x1 = _ref2[1], _ref), x0 = +x0, x1 = +x1, rescale()) : [x0, x1];
62972           };
62973
62974           scale.range = function (_) {
62975             return arguments.length ? (n = (range = Array.from(_)).length - 1, rescale()) : range.slice();
62976           };
62977
62978           scale.invertExtent = function (y) {
62979             var i = range.indexOf(y);
62980             return i < 0 ? [NaN, NaN] : i < 1 ? [x0, domain[0]] : i >= n ? [domain[n - 1], x1] : [domain[i - 1], domain[i]];
62981           };
62982
62983           scale.unknown = function (_) {
62984             return arguments.length ? (unknown = _, scale) : scale;
62985           };
62986
62987           scale.thresholds = function () {
62988             return domain.slice();
62989           };
62990
62991           scale.copy = function () {
62992             return quantize().domain([x0, x1]).range(range).unknown(unknown);
62993           };
62994
62995           return initRange.apply(linearish(scale), arguments);
62996         }
62997
62998         var global$3 = global$1m;
62999         var uncurryThis$2 = functionUncurryThis;
63000         var fails$2 = fails$S;
63001         var padStart = stringPad.start;
63002
63003         var RangeError$2 = global$3.RangeError;
63004         var abs$1 = Math.abs;
63005         var DatePrototype = Date.prototype;
63006         var n$DateToISOString = DatePrototype.toISOString;
63007         var getTime = uncurryThis$2(DatePrototype.getTime);
63008         var getUTCDate = uncurryThis$2(DatePrototype.getUTCDate);
63009         var getUTCFullYear = uncurryThis$2(DatePrototype.getUTCFullYear);
63010         var getUTCHours = uncurryThis$2(DatePrototype.getUTCHours);
63011         var getUTCMilliseconds = uncurryThis$2(DatePrototype.getUTCMilliseconds);
63012         var getUTCMinutes = uncurryThis$2(DatePrototype.getUTCMinutes);
63013         var getUTCMonth = uncurryThis$2(DatePrototype.getUTCMonth);
63014         var getUTCSeconds = uncurryThis$2(DatePrototype.getUTCSeconds);
63015
63016         // `Date.prototype.toISOString` method implementation
63017         // https://tc39.es/ecma262/#sec-date.prototype.toisostring
63018         // PhantomJS / old WebKit fails here:
63019         var dateToIsoString = (fails$2(function () {
63020           return n$DateToISOString.call(new Date(-5e13 - 1)) != '0385-07-25T07:06:39.999Z';
63021         }) || !fails$2(function () {
63022           n$DateToISOString.call(new Date(NaN));
63023         })) ? function toISOString() {
63024           if (!isFinite(getTime(this))) throw RangeError$2('Invalid time value');
63025           var date = this;
63026           var year = getUTCFullYear(date);
63027           var milliseconds = getUTCMilliseconds(date);
63028           var sign = year < 0 ? '-' : year > 9999 ? '+' : '';
63029           return sign + padStart(abs$1(year), sign ? 6 : 4, 0) +
63030             '-' + padStart(getUTCMonth(date) + 1, 2, 0) +
63031             '-' + padStart(getUTCDate(date), 2, 0) +
63032             'T' + padStart(getUTCHours(date), 2, 0) +
63033             ':' + padStart(getUTCMinutes(date), 2, 0) +
63034             ':' + padStart(getUTCSeconds(date), 2, 0) +
63035             '.' + padStart(milliseconds, 3, 0) +
63036             'Z';
63037         } : n$DateToISOString;
63038
63039         var $$4 = _export;
63040         var toISOString = dateToIsoString;
63041
63042         // `Date.prototype.toISOString` method
63043         // https://tc39.es/ecma262/#sec-date.prototype.toisostring
63044         // PhantomJS / old WebKit has a broken implementations
63045         $$4({ target: 'Date', proto: true, forced: Date.prototype.toISOString !== toISOString }, {
63046           toISOString: toISOString
63047         });
63048
63049         function behaviorBreathe() {
63050           var duration = 800;
63051           var steps = 4;
63052           var selector = '.selected.shadow, .selected .shadow';
63053
63054           var _selected = select(null);
63055
63056           var _classed = '';
63057           var _params = {};
63058           var _done = false;
63059
63060           var _timer;
63061
63062           function ratchetyInterpolator(a, b, steps, units) {
63063             a = parseFloat(a);
63064             b = parseFloat(b);
63065             var sample = quantize().domain([0, 1]).range(d3_quantize(d3_interpolateNumber(a, b), steps));
63066             return function (t) {
63067               return String(sample(t)) + (units || '');
63068             };
63069           }
63070
63071           function reset(selection) {
63072             selection.style('stroke-opacity', null).style('stroke-width', null).style('fill-opacity', null).style('r', null);
63073           }
63074
63075           function setAnimationParams(transition, fromTo) {
63076             var toFrom = fromTo === 'from' ? 'to' : 'from';
63077             transition.styleTween('stroke-opacity', function (d) {
63078               return ratchetyInterpolator(_params[d.id][toFrom].opacity, _params[d.id][fromTo].opacity, steps);
63079             }).styleTween('stroke-width', function (d) {
63080               return ratchetyInterpolator(_params[d.id][toFrom].width, _params[d.id][fromTo].width, steps, 'px');
63081             }).styleTween('fill-opacity', function (d) {
63082               return ratchetyInterpolator(_params[d.id][toFrom].opacity, _params[d.id][fromTo].opacity, steps);
63083             }).styleTween('r', function (d) {
63084               return ratchetyInterpolator(_params[d.id][toFrom].width, _params[d.id][fromTo].width, steps, 'px');
63085             });
63086           }
63087
63088           function calcAnimationParams(selection) {
63089             selection.call(reset).each(function (d) {
63090               var s = select(this);
63091               var tag = s.node().tagName;
63092               var p = {
63093                 'from': {},
63094                 'to': {}
63095               };
63096               var opacity;
63097               var width; // determine base opacity and width
63098
63099               if (tag === 'circle') {
63100                 opacity = parseFloat(s.style('fill-opacity') || 0.5);
63101                 width = parseFloat(s.style('r') || 15.5);
63102               } else {
63103                 opacity = parseFloat(s.style('stroke-opacity') || 0.7);
63104                 width = parseFloat(s.style('stroke-width') || 10);
63105               } // calculate from/to interpolation params..
63106
63107
63108               p.tag = tag;
63109               p.from.opacity = opacity * 0.6;
63110               p.to.opacity = opacity * 1.25;
63111               p.from.width = width * 0.7;
63112               p.to.width = width * (tag === 'circle' ? 1.5 : 1);
63113               _params[d.id] = p;
63114             });
63115           }
63116
63117           function run(surface, fromTo) {
63118             var toFrom = fromTo === 'from' ? 'to' : 'from';
63119             var currSelected = surface.selectAll(selector);
63120             var currClassed = surface.attr('class');
63121
63122             if (_done || currSelected.empty()) {
63123               _selected.call(reset);
63124
63125               _selected = select(null);
63126               return;
63127             }
63128
63129             if (!fastDeepEqual(currSelected.data(), _selected.data()) || currClassed !== _classed) {
63130               _selected.call(reset);
63131
63132               _classed = currClassed;
63133               _selected = currSelected.call(calcAnimationParams);
63134             }
63135
63136             var didCallNextRun = false;
63137
63138             _selected.transition().duration(duration).call(setAnimationParams, fromTo).on('end', function () {
63139               // `end` event is called for each selected element, but we want
63140               // it to run only once
63141               if (!didCallNextRun) {
63142                 surface.call(run, toFrom);
63143                 didCallNextRun = true;
63144               } // if entity was deselected, remove breathe styling
63145
63146
63147               if (!select(this).classed('selected')) {
63148                 reset(select(this));
63149               }
63150             });
63151           }
63152
63153           function behavior(surface) {
63154             _done = false;
63155             _timer = timer(function () {
63156               // wait for elements to actually become selected
63157               if (surface.selectAll(selector).empty()) {
63158                 return false;
63159               }
63160
63161               surface.call(run, 'from');
63162
63163               _timer.stop();
63164
63165               return true;
63166             }, 20);
63167           }
63168
63169           behavior.restartIfNeeded = function (surface) {
63170             if (_selected.empty()) {
63171               surface.call(run, 'from');
63172
63173               if (_timer) {
63174                 _timer.stop();
63175               }
63176             }
63177           };
63178
63179           behavior.off = function () {
63180             _done = true;
63181
63182             if (_timer) {
63183               _timer.stop();
63184             }
63185
63186             _selected.interrupt().call(reset);
63187           };
63188
63189           return behavior;
63190         }
63191
63192         /* Creates a keybinding behavior for an operation */
63193         function behaviorOperation(context) {
63194           var _operation;
63195
63196           function keypress(d3_event) {
63197             // prevent operations during low zoom selection
63198             if (!context.map().withinEditableZoom()) return;
63199             if (_operation.availableForKeypress && !_operation.availableForKeypress()) return;
63200             d3_event.preventDefault();
63201
63202             var disabled = _operation.disabled();
63203
63204             if (disabled) {
63205               context.ui().flash.duration(4000).iconName('#iD-operation-' + _operation.id).iconClass('operation disabled').label(_operation.tooltip)();
63206             } else {
63207               context.ui().flash.duration(2000).iconName('#iD-operation-' + _operation.id).iconClass('operation').label(_operation.annotation() || _operation.title)();
63208               if (_operation.point) _operation.point(null);
63209
63210               _operation();
63211             }
63212           }
63213
63214           function behavior() {
63215             if (_operation && _operation.available()) {
63216               context.keybinding().on(_operation.keys, keypress);
63217             }
63218
63219             return behavior;
63220           }
63221
63222           behavior.off = function () {
63223             context.keybinding().off(_operation.keys);
63224           };
63225
63226           behavior.which = function (_) {
63227             if (!arguments.length) return _operation;
63228             _operation = _;
63229             return behavior;
63230           };
63231
63232           return behavior;
63233         }
63234
63235         function operationCircularize(context, selectedIDs) {
63236           var _extent;
63237
63238           var _actions = selectedIDs.map(getAction).filter(Boolean);
63239
63240           var _amount = _actions.length === 1 ? 'single' : 'multiple';
63241
63242           var _coords = utilGetAllNodes(selectedIDs, context.graph()).map(function (n) {
63243             return n.loc;
63244           });
63245
63246           function getAction(entityID) {
63247             var entity = context.entity(entityID);
63248             if (entity.type !== 'way' || new Set(entity.nodes).size <= 1) return null;
63249
63250             if (!_extent) {
63251               _extent = entity.extent(context.graph());
63252             } else {
63253               _extent = _extent.extend(entity.extent(context.graph()));
63254             }
63255
63256             return actionCircularize(entityID, context.projection);
63257           }
63258
63259           var operation = function operation() {
63260             if (!_actions.length) return;
63261
63262             var combinedAction = function combinedAction(graph, t) {
63263               _actions.forEach(function (action) {
63264                 if (!action.disabled(graph)) {
63265                   graph = action(graph, t);
63266                 }
63267               });
63268
63269               return graph;
63270             };
63271
63272             combinedAction.transitionable = true;
63273             context.perform(combinedAction, operation.annotation());
63274             window.setTimeout(function () {
63275               context.validator().validate();
63276             }, 300); // after any transition
63277           };
63278
63279           operation.available = function () {
63280             return _actions.length && selectedIDs.length === _actions.length;
63281           }; // don't cache this because the visible extent could change
63282
63283
63284           operation.disabled = function () {
63285             if (!_actions.length) return '';
63286
63287             var actionDisableds = _actions.map(function (action) {
63288               return action.disabled(context.graph());
63289             }).filter(Boolean);
63290
63291             if (actionDisableds.length === _actions.length) {
63292               // none of the features can be circularized
63293               if (new Set(actionDisableds).size > 1) {
63294                 return 'multiple_blockers';
63295               }
63296
63297               return actionDisableds[0];
63298             } else if (_extent.percentContainedIn(context.map().extent()) < 0.8) {
63299               return 'too_large';
63300             } else if (someMissing()) {
63301               return 'not_downloaded';
63302             } else if (selectedIDs.some(context.hasHiddenConnections)) {
63303               return 'connected_to_hidden';
63304             }
63305
63306             return false;
63307
63308             function someMissing() {
63309               if (context.inIntro()) return false;
63310               var osm = context.connection();
63311
63312               if (osm) {
63313                 var missing = _coords.filter(function (loc) {
63314                   return !osm.isDataLoaded(loc);
63315                 });
63316
63317                 if (missing.length) {
63318                   missing.forEach(function (loc) {
63319                     context.loadTileAtLoc(loc);
63320                   });
63321                   return true;
63322                 }
63323               }
63324
63325               return false;
63326             }
63327           };
63328
63329           operation.tooltip = function () {
63330             var disable = operation.disabled();
63331             return disable ? _t('operations.circularize.' + disable + '.' + _amount) : _t('operations.circularize.description.' + _amount);
63332           };
63333
63334           operation.annotation = function () {
63335             return _t('operations.circularize.annotation.feature', {
63336               n: _actions.length
63337             });
63338           };
63339
63340           operation.id = 'circularize';
63341           operation.keys = [_t('operations.circularize.key')];
63342           operation.title = _t('operations.circularize.title');
63343           operation.behavior = behaviorOperation(context).which(operation);
63344           return operation;
63345         }
63346
63347         // For example, ⌘Z -> Ctrl+Z
63348
63349         var uiCmd = function uiCmd(code) {
63350           var detected = utilDetect();
63351
63352           if (detected.os === 'mac') {
63353             return code;
63354           }
63355
63356           if (detected.os === 'win') {
63357             if (code === '⌘⇧Z') return 'Ctrl+Y';
63358           }
63359
63360           var result = '',
63361               replacements = {
63362             '⌘': 'Ctrl',
63363             '⇧': 'Shift',
63364             '⌥': 'Alt',
63365             '⌫': 'Backspace',
63366             '⌦': 'Delete'
63367           };
63368
63369           for (var i = 0; i < code.length; i++) {
63370             if (code[i] in replacements) {
63371               result += replacements[code[i]] + (i < code.length - 1 ? '+' : '');
63372             } else {
63373               result += code[i];
63374             }
63375           }
63376
63377           return result;
63378         }; // return a display-focused string for a given keyboard code
63379
63380         uiCmd.display = function (code) {
63381           if (code.length !== 1) return code;
63382           var detected = utilDetect();
63383           var mac = detected.os === 'mac';
63384           var replacements = {
63385             '⌘': mac ? '⌘ ' + _t('shortcuts.key.cmd') : _t('shortcuts.key.ctrl'),
63386             '⇧': mac ? '⇧ ' + _t('shortcuts.key.shift') : _t('shortcuts.key.shift'),
63387             '⌥': mac ? '⌥ ' + _t('shortcuts.key.option') : _t('shortcuts.key.alt'),
63388             '⌃': mac ? '⌃ ' + _t('shortcuts.key.ctrl') : _t('shortcuts.key.ctrl'),
63389             '⌫': mac ? '⌫ ' + _t('shortcuts.key.delete') : _t('shortcuts.key.backspace'),
63390             '⌦': mac ? '⌦ ' + _t('shortcuts.key.del') : _t('shortcuts.key.del'),
63391             '↖': mac ? '↖ ' + _t('shortcuts.key.pgup') : _t('shortcuts.key.pgup'),
63392             '↘': mac ? '↘ ' + _t('shortcuts.key.pgdn') : _t('shortcuts.key.pgdn'),
63393             '⇞': mac ? '⇞ ' + _t('shortcuts.key.home') : _t('shortcuts.key.home'),
63394             '⇟': mac ? '⇟ ' + _t('shortcuts.key.end') : _t('shortcuts.key.end'),
63395             '↵': mac ? '⏎ ' + _t('shortcuts.key.return') : _t('shortcuts.key.enter'),
63396             '⎋': mac ? '⎋ ' + _t('shortcuts.key.esc') : _t('shortcuts.key.esc'),
63397             '☰': mac ? '☰ ' + _t('shortcuts.key.menu') : _t('shortcuts.key.menu')
63398           };
63399           return replacements[code] || code;
63400         };
63401
63402         function operationDelete(context, selectedIDs) {
63403           var multi = selectedIDs.length === 1 ? 'single' : 'multiple';
63404           var action = actionDeleteMultiple(selectedIDs);
63405           var nodes = utilGetAllNodes(selectedIDs, context.graph());
63406           var coords = nodes.map(function (n) {
63407             return n.loc;
63408           });
63409           var extent = utilTotalExtent(selectedIDs, context.graph());
63410
63411           var operation = function operation() {
63412             var nextSelectedID;
63413             var nextSelectedLoc;
63414
63415             if (selectedIDs.length === 1) {
63416               var id = selectedIDs[0];
63417               var entity = context.entity(id);
63418               var geometry = entity.geometry(context.graph());
63419               var parents = context.graph().parentWays(entity);
63420               var parent = parents[0]; // Select the next closest node in the way.
63421
63422               if (geometry === 'vertex') {
63423                 var nodes = parent.nodes;
63424                 var i = nodes.indexOf(id);
63425
63426                 if (i === 0) {
63427                   i++;
63428                 } else if (i === nodes.length - 1) {
63429                   i--;
63430                 } else {
63431                   var a = geoSphericalDistance(entity.loc, context.entity(nodes[i - 1]).loc);
63432                   var b = geoSphericalDistance(entity.loc, context.entity(nodes[i + 1]).loc);
63433                   i = a < b ? i - 1 : i + 1;
63434                 }
63435
63436                 nextSelectedID = nodes[i];
63437                 nextSelectedLoc = context.entity(nextSelectedID).loc;
63438               }
63439             }
63440
63441             context.perform(action, operation.annotation());
63442             context.validator().validate();
63443
63444             if (nextSelectedID && nextSelectedLoc) {
63445               if (context.hasEntity(nextSelectedID)) {
63446                 context.enter(modeSelect(context, [nextSelectedID]).follow(true));
63447               } else {
63448                 context.map().centerEase(nextSelectedLoc);
63449                 context.enter(modeBrowse(context));
63450               }
63451             } else {
63452               context.enter(modeBrowse(context));
63453             }
63454           };
63455
63456           operation.available = function () {
63457             return true;
63458           };
63459
63460           operation.disabled = function () {
63461             if (extent.percentContainedIn(context.map().extent()) < 0.8) {
63462               return 'too_large';
63463             } else if (someMissing()) {
63464               return 'not_downloaded';
63465             } else if (selectedIDs.some(context.hasHiddenConnections)) {
63466               return 'connected_to_hidden';
63467             } else if (selectedIDs.some(protectedMember)) {
63468               return 'part_of_relation';
63469             } else if (selectedIDs.some(incompleteRelation)) {
63470               return 'incomplete_relation';
63471             } else if (selectedIDs.some(hasWikidataTag)) {
63472               return 'has_wikidata_tag';
63473             }
63474
63475             return false;
63476
63477             function someMissing() {
63478               if (context.inIntro()) return false;
63479               var osm = context.connection();
63480
63481               if (osm) {
63482                 var missing = coords.filter(function (loc) {
63483                   return !osm.isDataLoaded(loc);
63484                 });
63485
63486                 if (missing.length) {
63487                   missing.forEach(function (loc) {
63488                     context.loadTileAtLoc(loc);
63489                   });
63490                   return true;
63491                 }
63492               }
63493
63494               return false;
63495             }
63496
63497             function hasWikidataTag(id) {
63498               var entity = context.entity(id);
63499               return entity.tags.wikidata && entity.tags.wikidata.trim().length > 0;
63500             }
63501
63502             function incompleteRelation(id) {
63503               var entity = context.entity(id);
63504               return entity.type === 'relation' && !entity.isComplete(context.graph());
63505             }
63506
63507             function protectedMember(id) {
63508               var entity = context.entity(id);
63509               if (entity.type !== 'way') return false;
63510               var parents = context.graph().parentRelations(entity);
63511
63512               for (var i = 0; i < parents.length; i++) {
63513                 var parent = parents[i];
63514                 var type = parent.tags.type;
63515                 var role = parent.memberById(id).role || 'outer';
63516
63517                 if (type === 'route' || type === 'boundary' || type === 'multipolygon' && role === 'outer') {
63518                   return true;
63519                 }
63520               }
63521
63522               return false;
63523             }
63524           };
63525
63526           operation.tooltip = function () {
63527             var disable = operation.disabled();
63528             return disable ? _t('operations.delete.' + disable + '.' + multi) : _t('operations.delete.description.' + multi);
63529           };
63530
63531           operation.annotation = function () {
63532             return selectedIDs.length === 1 ? _t('operations.delete.annotation.' + context.graph().geometry(selectedIDs[0])) : _t('operations.delete.annotation.feature', {
63533               n: selectedIDs.length
63534             });
63535           };
63536
63537           operation.id = 'delete';
63538           operation.keys = [uiCmd('⌘⌫'), uiCmd('⌘⌦'), uiCmd('⌦')];
63539           operation.title = _t('operations.delete.title');
63540           operation.behavior = behaviorOperation(context).which(operation);
63541           return operation;
63542         }
63543
63544         function operationOrthogonalize(context, selectedIDs) {
63545           var _extent;
63546
63547           var _type;
63548
63549           var _actions = selectedIDs.map(chooseAction).filter(Boolean);
63550
63551           var _amount = _actions.length === 1 ? 'single' : 'multiple';
63552
63553           var _coords = utilGetAllNodes(selectedIDs, context.graph()).map(function (n) {
63554             return n.loc;
63555           });
63556
63557           function chooseAction(entityID) {
63558             var entity = context.entity(entityID);
63559             var geometry = entity.geometry(context.graph());
63560
63561             if (!_extent) {
63562               _extent = entity.extent(context.graph());
63563             } else {
63564               _extent = _extent.extend(entity.extent(context.graph()));
63565             } // square a line/area
63566
63567
63568             if (entity.type === 'way' && new Set(entity.nodes).size > 2) {
63569               if (_type && _type !== 'feature') return null;
63570               _type = 'feature';
63571               return actionOrthogonalize(entityID, context.projection); // square a single vertex
63572             } else if (geometry === 'vertex') {
63573               if (_type && _type !== 'corner') return null;
63574               _type = 'corner';
63575               var graph = context.graph();
63576               var parents = graph.parentWays(entity);
63577
63578               if (parents.length === 1) {
63579                 var way = parents[0];
63580
63581                 if (way.nodes.indexOf(entityID) !== -1) {
63582                   return actionOrthogonalize(way.id, context.projection, entityID);
63583                 }
63584               }
63585             }
63586
63587             return null;
63588           }
63589
63590           var operation = function operation() {
63591             if (!_actions.length) return;
63592
63593             var combinedAction = function combinedAction(graph, t) {
63594               _actions.forEach(function (action) {
63595                 if (!action.disabled(graph)) {
63596                   graph = action(graph, t);
63597                 }
63598               });
63599
63600               return graph;
63601             };
63602
63603             combinedAction.transitionable = true;
63604             context.perform(combinedAction, operation.annotation());
63605             window.setTimeout(function () {
63606               context.validator().validate();
63607             }, 300); // after any transition
63608           };
63609
63610           operation.available = function () {
63611             return _actions.length && selectedIDs.length === _actions.length;
63612           }; // don't cache this because the visible extent could change
63613
63614
63615           operation.disabled = function () {
63616             if (!_actions.length) return '';
63617
63618             var actionDisableds = _actions.map(function (action) {
63619               return action.disabled(context.graph());
63620             }).filter(Boolean);
63621
63622             if (actionDisableds.length === _actions.length) {
63623               // none of the features can be squared
63624               if (new Set(actionDisableds).size > 1) {
63625                 return 'multiple_blockers';
63626               }
63627
63628               return actionDisableds[0];
63629             } else if (_extent && _extent.percentContainedIn(context.map().extent()) < 0.8) {
63630               return 'too_large';
63631             } else if (someMissing()) {
63632               return 'not_downloaded';
63633             } else if (selectedIDs.some(context.hasHiddenConnections)) {
63634               return 'connected_to_hidden';
63635             }
63636
63637             return false;
63638
63639             function someMissing() {
63640               if (context.inIntro()) return false;
63641               var osm = context.connection();
63642
63643               if (osm) {
63644                 var missing = _coords.filter(function (loc) {
63645                   return !osm.isDataLoaded(loc);
63646                 });
63647
63648                 if (missing.length) {
63649                   missing.forEach(function (loc) {
63650                     context.loadTileAtLoc(loc);
63651                   });
63652                   return true;
63653                 }
63654               }
63655
63656               return false;
63657             }
63658           };
63659
63660           operation.tooltip = function () {
63661             var disable = operation.disabled();
63662             return disable ? _t('operations.orthogonalize.' + disable + '.' + _amount) : _t('operations.orthogonalize.description.' + _type + '.' + _amount);
63663           };
63664
63665           operation.annotation = function () {
63666             return _t('operations.orthogonalize.annotation.' + _type, {
63667               n: _actions.length
63668             });
63669           };
63670
63671           operation.id = 'orthogonalize';
63672           operation.keys = [_t('operations.orthogonalize.key')];
63673           operation.title = _t('operations.orthogonalize.title');
63674           operation.behavior = behaviorOperation(context).which(operation);
63675           return operation;
63676         }
63677
63678         function operationReflectShort(context, selectedIDs) {
63679           return operationReflect(context, selectedIDs, 'short');
63680         }
63681         function operationReflectLong(context, selectedIDs) {
63682           return operationReflect(context, selectedIDs, 'long');
63683         }
63684         function operationReflect(context, selectedIDs, axis) {
63685           axis = axis || 'long';
63686           var multi = selectedIDs.length === 1 ? 'single' : 'multiple';
63687           var nodes = utilGetAllNodes(selectedIDs, context.graph());
63688           var coords = nodes.map(function (n) {
63689             return n.loc;
63690           });
63691           var extent = utilTotalExtent(selectedIDs, context.graph());
63692
63693           var operation = function operation() {
63694             var action = actionReflect(selectedIDs, context.projection).useLongAxis(Boolean(axis === 'long'));
63695             context.perform(action, operation.annotation());
63696             window.setTimeout(function () {
63697               context.validator().validate();
63698             }, 300); // after any transition
63699           };
63700
63701           operation.available = function () {
63702             return nodes.length >= 3;
63703           }; // don't cache this because the visible extent could change
63704
63705
63706           operation.disabled = function () {
63707             if (extent.percentContainedIn(context.map().extent()) < 0.8) {
63708               return 'too_large';
63709             } else if (someMissing()) {
63710               return 'not_downloaded';
63711             } else if (selectedIDs.some(context.hasHiddenConnections)) {
63712               return 'connected_to_hidden';
63713             } else if (selectedIDs.some(incompleteRelation)) {
63714               return 'incomplete_relation';
63715             }
63716
63717             return false;
63718
63719             function someMissing() {
63720               if (context.inIntro()) return false;
63721               var osm = context.connection();
63722
63723               if (osm) {
63724                 var missing = coords.filter(function (loc) {
63725                   return !osm.isDataLoaded(loc);
63726                 });
63727
63728                 if (missing.length) {
63729                   missing.forEach(function (loc) {
63730                     context.loadTileAtLoc(loc);
63731                   });
63732                   return true;
63733                 }
63734               }
63735
63736               return false;
63737             }
63738
63739             function incompleteRelation(id) {
63740               var entity = context.entity(id);
63741               return entity.type === 'relation' && !entity.isComplete(context.graph());
63742             }
63743           };
63744
63745           operation.tooltip = function () {
63746             var disable = operation.disabled();
63747             return disable ? _t('operations.reflect.' + disable + '.' + multi) : _t('operations.reflect.description.' + axis + '.' + multi);
63748           };
63749
63750           operation.annotation = function () {
63751             return _t('operations.reflect.annotation.' + axis + '.feature', {
63752               n: selectedIDs.length
63753             });
63754           };
63755
63756           operation.id = 'reflect-' + axis;
63757           operation.keys = [_t('operations.reflect.key.' + axis)];
63758           operation.title = _t('operations.reflect.title.' + axis);
63759           operation.behavior = behaviorOperation(context).which(operation);
63760           return operation;
63761         }
63762
63763         function operationMove(context, selectedIDs) {
63764           var multi = selectedIDs.length === 1 ? 'single' : 'multiple';
63765           var nodes = utilGetAllNodes(selectedIDs, context.graph());
63766           var coords = nodes.map(function (n) {
63767             return n.loc;
63768           });
63769           var extent = utilTotalExtent(selectedIDs, context.graph());
63770
63771           var operation = function operation() {
63772             context.enter(modeMove(context, selectedIDs));
63773           };
63774
63775           operation.available = function () {
63776             return selectedIDs.length > 0;
63777           };
63778
63779           operation.disabled = function () {
63780             if (extent.percentContainedIn(context.map().extent()) < 0.8) {
63781               return 'too_large';
63782             } else if (someMissing()) {
63783               return 'not_downloaded';
63784             } else if (selectedIDs.some(context.hasHiddenConnections)) {
63785               return 'connected_to_hidden';
63786             } else if (selectedIDs.some(incompleteRelation)) {
63787               return 'incomplete_relation';
63788             }
63789
63790             return false;
63791
63792             function someMissing() {
63793               if (context.inIntro()) return false;
63794               var osm = context.connection();
63795
63796               if (osm) {
63797                 var missing = coords.filter(function (loc) {
63798                   return !osm.isDataLoaded(loc);
63799                 });
63800
63801                 if (missing.length) {
63802                   missing.forEach(function (loc) {
63803                     context.loadTileAtLoc(loc);
63804                   });
63805                   return true;
63806                 }
63807               }
63808
63809               return false;
63810             }
63811
63812             function incompleteRelation(id) {
63813               var entity = context.entity(id);
63814               return entity.type === 'relation' && !entity.isComplete(context.graph());
63815             }
63816           };
63817
63818           operation.tooltip = function () {
63819             var disable = operation.disabled();
63820             return disable ? _t('operations.move.' + disable + '.' + multi) : _t('operations.move.description.' + multi);
63821           };
63822
63823           operation.annotation = function () {
63824             return selectedIDs.length === 1 ? _t('operations.move.annotation.' + context.graph().geometry(selectedIDs[0])) : _t('operations.move.annotation.feature', {
63825               n: selectedIDs.length
63826             });
63827           };
63828
63829           operation.id = 'move';
63830           operation.keys = [_t('operations.move.key')];
63831           operation.title = _t('operations.move.title');
63832           operation.behavior = behaviorOperation(context).which(operation);
63833           operation.mouseOnly = true;
63834           return operation;
63835         }
63836
63837         function modeRotate(context, entityIDs) {
63838           var _tolerancePx = 4; // see also behaviorDrag, behaviorSelect, modeMove
63839
63840           var mode = {
63841             id: 'rotate',
63842             button: 'browse'
63843           };
63844           var keybinding = utilKeybinding('rotate');
63845           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];
63846           var annotation = entityIDs.length === 1 ? _t('operations.rotate.annotation.' + context.graph().geometry(entityIDs[0])) : _t('operations.rotate.annotation.feature', {
63847             n: entityIDs.length
63848           });
63849
63850           var _prevGraph;
63851
63852           var _prevAngle;
63853
63854           var _prevTransform;
63855
63856           var _pivot; // use pointer events on supported platforms; fallback to mouse events
63857
63858
63859           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
63860
63861           function doRotate(d3_event) {
63862             var fn;
63863
63864             if (context.graph() !== _prevGraph) {
63865               fn = context.perform;
63866             } else {
63867               fn = context.replace;
63868             } // projection changed, recalculate _pivot
63869
63870
63871             var projection = context.projection;
63872             var currTransform = projection.transform();
63873
63874             if (!_prevTransform || currTransform.k !== _prevTransform.k || currTransform.x !== _prevTransform.x || currTransform.y !== _prevTransform.y) {
63875               var nodes = utilGetAllNodes(entityIDs, context.graph());
63876               var points = nodes.map(function (n) {
63877                 return projection(n.loc);
63878               });
63879               _pivot = getPivot(points);
63880               _prevAngle = undefined;
63881             }
63882
63883             var currMouse = context.map().mouse(d3_event);
63884             var currAngle = Math.atan2(currMouse[1] - _pivot[1], currMouse[0] - _pivot[0]);
63885             if (typeof _prevAngle === 'undefined') _prevAngle = currAngle;
63886             var delta = currAngle - _prevAngle;
63887             fn(actionRotate(entityIDs, _pivot, delta, projection));
63888             _prevTransform = currTransform;
63889             _prevAngle = currAngle;
63890             _prevGraph = context.graph();
63891           }
63892
63893           function getPivot(points) {
63894             var _pivot;
63895
63896             if (points.length === 1) {
63897               _pivot = points[0];
63898             } else if (points.length === 2) {
63899               _pivot = geoVecInterp(points[0], points[1], 0.5);
63900             } else {
63901               var polygonHull = d3_polygonHull(points);
63902
63903               if (polygonHull.length === 2) {
63904                 _pivot = geoVecInterp(points[0], points[1], 0.5);
63905               } else {
63906                 _pivot = d3_polygonCentroid(d3_polygonHull(points));
63907               }
63908             }
63909
63910             return _pivot;
63911           }
63912
63913           function finish(d3_event) {
63914             d3_event.stopPropagation();
63915             context.replace(actionNoop(), annotation);
63916             context.enter(modeSelect(context, entityIDs));
63917           }
63918
63919           function cancel() {
63920             if (_prevGraph) context.pop(); // remove the rotate
63921
63922             context.enter(modeSelect(context, entityIDs));
63923           }
63924
63925           function undone() {
63926             context.enter(modeBrowse(context));
63927           }
63928
63929           mode.enter = function () {
63930             _prevGraph = null;
63931             context.features().forceVisible(entityIDs);
63932             behaviors.forEach(context.install);
63933             var downEvent;
63934             context.surface().on(_pointerPrefix + 'down.modeRotate', function (d3_event) {
63935               downEvent = d3_event;
63936             });
63937             select(window).on(_pointerPrefix + 'move.modeRotate', doRotate, true).on(_pointerPrefix + 'up.modeRotate', function (d3_event) {
63938               if (!downEvent) return;
63939               var mapNode = context.container().select('.main-map').node();
63940               var pointGetter = utilFastMouse(mapNode);
63941               var p1 = pointGetter(downEvent);
63942               var p2 = pointGetter(d3_event);
63943               var dist = geoVecLength(p1, p2);
63944               if (dist <= _tolerancePx) finish(d3_event);
63945               downEvent = null;
63946             }, true);
63947             context.history().on('undone.modeRotate', undone);
63948             keybinding.on('⎋', cancel).on('↩', finish);
63949             select(document).call(keybinding);
63950           };
63951
63952           mode.exit = function () {
63953             behaviors.forEach(context.uninstall);
63954             context.surface().on(_pointerPrefix + 'down.modeRotate', null);
63955             select(window).on(_pointerPrefix + 'move.modeRotate', null, true).on(_pointerPrefix + 'up.modeRotate', null, true);
63956             context.history().on('undone.modeRotate', null);
63957             select(document).call(keybinding.unbind);
63958             context.features().forceVisible([]);
63959           };
63960
63961           mode.selectedIDs = function () {
63962             if (!arguments.length) return entityIDs; // no assign
63963
63964             return mode;
63965           };
63966
63967           return mode;
63968         }
63969
63970         function operationRotate(context, selectedIDs) {
63971           var multi = selectedIDs.length === 1 ? 'single' : 'multiple';
63972           var nodes = utilGetAllNodes(selectedIDs, context.graph());
63973           var coords = nodes.map(function (n) {
63974             return n.loc;
63975           });
63976           var extent = utilTotalExtent(selectedIDs, context.graph());
63977
63978           var operation = function operation() {
63979             context.enter(modeRotate(context, selectedIDs));
63980           };
63981
63982           operation.available = function () {
63983             return nodes.length >= 2;
63984           };
63985
63986           operation.disabled = function () {
63987             if (extent.percentContainedIn(context.map().extent()) < 0.8) {
63988               return 'too_large';
63989             } else if (someMissing()) {
63990               return 'not_downloaded';
63991             } else if (selectedIDs.some(context.hasHiddenConnections)) {
63992               return 'connected_to_hidden';
63993             } else if (selectedIDs.some(incompleteRelation)) {
63994               return 'incomplete_relation';
63995             }
63996
63997             return false;
63998
63999             function someMissing() {
64000               if (context.inIntro()) return false;
64001               var osm = context.connection();
64002
64003               if (osm) {
64004                 var missing = coords.filter(function (loc) {
64005                   return !osm.isDataLoaded(loc);
64006                 });
64007
64008                 if (missing.length) {
64009                   missing.forEach(function (loc) {
64010                     context.loadTileAtLoc(loc);
64011                   });
64012                   return true;
64013                 }
64014               }
64015
64016               return false;
64017             }
64018
64019             function incompleteRelation(id) {
64020               var entity = context.entity(id);
64021               return entity.type === 'relation' && !entity.isComplete(context.graph());
64022             }
64023           };
64024
64025           operation.tooltip = function () {
64026             var disable = operation.disabled();
64027             return disable ? _t('operations.rotate.' + disable + '.' + multi) : _t('operations.rotate.description.' + multi);
64028           };
64029
64030           operation.annotation = function () {
64031             return selectedIDs.length === 1 ? _t('operations.rotate.annotation.' + context.graph().geometry(selectedIDs[0])) : _t('operations.rotate.annotation.feature', {
64032               n: selectedIDs.length
64033             });
64034           };
64035
64036           operation.id = 'rotate';
64037           operation.keys = [_t('operations.rotate.key')];
64038           operation.title = _t('operations.rotate.title');
64039           operation.behavior = behaviorOperation(context).which(operation);
64040           operation.mouseOnly = true;
64041           return operation;
64042         }
64043
64044         function modeMove(context, entityIDs, baseGraph) {
64045           var _tolerancePx = 4; // see also behaviorDrag, behaviorSelect, modeRotate
64046
64047           var mode = {
64048             id: 'move',
64049             button: 'browse'
64050           };
64051           var keybinding = utilKeybinding('move');
64052           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];
64053           var annotation = entityIDs.length === 1 ? _t('operations.move.annotation.' + context.graph().geometry(entityIDs[0])) : _t('operations.move.annotation.feature', {
64054             n: entityIDs.length
64055           });
64056
64057           var _prevGraph;
64058
64059           var _cache;
64060
64061           var _origin;
64062
64063           var _nudgeInterval; // use pointer events on supported platforms; fallback to mouse events
64064
64065
64066           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
64067
64068           function doMove(nudge) {
64069             nudge = nudge || [0, 0];
64070             var fn;
64071
64072             if (_prevGraph !== context.graph()) {
64073               _cache = {};
64074               _origin = context.map().mouseCoordinates();
64075               fn = context.perform;
64076             } else {
64077               fn = context.overwrite;
64078             }
64079
64080             var currMouse = context.map().mouse();
64081             var origMouse = context.projection(_origin);
64082             var delta = geoVecSubtract(geoVecSubtract(currMouse, origMouse), nudge);
64083             fn(actionMove(entityIDs, delta, context.projection, _cache));
64084             _prevGraph = context.graph();
64085           }
64086
64087           function startNudge(nudge) {
64088             if (_nudgeInterval) window.clearInterval(_nudgeInterval);
64089             _nudgeInterval = window.setInterval(function () {
64090               context.map().pan(nudge);
64091               doMove(nudge);
64092             }, 50);
64093           }
64094
64095           function stopNudge() {
64096             if (_nudgeInterval) {
64097               window.clearInterval(_nudgeInterval);
64098               _nudgeInterval = null;
64099             }
64100           }
64101
64102           function move() {
64103             doMove();
64104             var nudge = geoViewportEdge(context.map().mouse(), context.map().dimensions());
64105
64106             if (nudge) {
64107               startNudge(nudge);
64108             } else {
64109               stopNudge();
64110             }
64111           }
64112
64113           function finish(d3_event) {
64114             d3_event.stopPropagation();
64115             context.replace(actionNoop(), annotation);
64116             context.enter(modeSelect(context, entityIDs));
64117             stopNudge();
64118           }
64119
64120           function cancel() {
64121             if (baseGraph) {
64122               while (context.graph() !== baseGraph) {
64123                 context.pop();
64124               } // reset to baseGraph
64125
64126
64127               context.enter(modeBrowse(context));
64128             } else {
64129               if (_prevGraph) context.pop(); // remove the move
64130
64131               context.enter(modeSelect(context, entityIDs));
64132             }
64133
64134             stopNudge();
64135           }
64136
64137           function undone() {
64138             context.enter(modeBrowse(context));
64139           }
64140
64141           mode.enter = function () {
64142             _origin = context.map().mouseCoordinates();
64143             _prevGraph = null;
64144             _cache = {};
64145             context.features().forceVisible(entityIDs);
64146             behaviors.forEach(context.install);
64147             var downEvent;
64148             context.surface().on(_pointerPrefix + 'down.modeMove', function (d3_event) {
64149               downEvent = d3_event;
64150             });
64151             select(window).on(_pointerPrefix + 'move.modeMove', move, true).on(_pointerPrefix + 'up.modeMove', function (d3_event) {
64152               if (!downEvent) return;
64153               var mapNode = context.container().select('.main-map').node();
64154               var pointGetter = utilFastMouse(mapNode);
64155               var p1 = pointGetter(downEvent);
64156               var p2 = pointGetter(d3_event);
64157               var dist = geoVecLength(p1, p2);
64158               if (dist <= _tolerancePx) finish(d3_event);
64159               downEvent = null;
64160             }, true);
64161             context.history().on('undone.modeMove', undone);
64162             keybinding.on('⎋', cancel).on('↩', finish);
64163             select(document).call(keybinding);
64164           };
64165
64166           mode.exit = function () {
64167             stopNudge();
64168             behaviors.forEach(function (behavior) {
64169               context.uninstall(behavior);
64170             });
64171             context.surface().on(_pointerPrefix + 'down.modeMove', null);
64172             select(window).on(_pointerPrefix + 'move.modeMove', null, true).on(_pointerPrefix + 'up.modeMove', null, true);
64173             context.history().on('undone.modeMove', null);
64174             select(document).call(keybinding.unbind);
64175             context.features().forceVisible([]);
64176           };
64177
64178           mode.selectedIDs = function () {
64179             if (!arguments.length) return entityIDs; // no assign
64180
64181             return mode;
64182           };
64183
64184           return mode;
64185         }
64186
64187         function behaviorPaste(context) {
64188           function doPaste(d3_event) {
64189             // prevent paste during low zoom selection
64190             if (!context.map().withinEditableZoom()) return;
64191             d3_event.preventDefault();
64192             var baseGraph = context.graph();
64193             var mouse = context.map().mouse();
64194             var projection = context.projection;
64195             var viewport = geoExtent(projection.clipExtent()).polygon();
64196             if (!geoPointInPolygon(mouse, viewport)) return;
64197             var oldIDs = context.copyIDs();
64198             if (!oldIDs.length) return;
64199             var extent = geoExtent();
64200             var oldGraph = context.copyGraph();
64201             var newIDs = [];
64202             var action = actionCopyEntities(oldIDs, oldGraph);
64203             context.perform(action);
64204             var copies = action.copies();
64205             var originals = new Set();
64206             Object.values(copies).forEach(function (entity) {
64207               originals.add(entity.id);
64208             });
64209
64210             for (var id in copies) {
64211               var oldEntity = oldGraph.entity(id);
64212               var newEntity = copies[id];
64213
64214               extent._extend(oldEntity.extent(oldGraph)); // Exclude child nodes from newIDs if their parent way was also copied.
64215
64216
64217               var parents = context.graph().parentWays(newEntity);
64218               var parentCopied = parents.some(function (parent) {
64219                 return originals.has(parent.id);
64220               });
64221
64222               if (!parentCopied) {
64223                 newIDs.push(newEntity.id);
64224               }
64225             } // Put pasted objects where mouse pointer is..
64226
64227
64228             var copyPoint = context.copyLonLat() && projection(context.copyLonLat()) || projection(extent.center());
64229             var delta = geoVecSubtract(mouse, copyPoint);
64230             context.perform(actionMove(newIDs, delta, projection));
64231             context.enter(modeMove(context, newIDs, baseGraph));
64232           }
64233
64234           function behavior() {
64235             context.keybinding().on(uiCmd('⌘V'), doPaste);
64236             return behavior;
64237           }
64238
64239           behavior.off = function () {
64240             context.keybinding().off(uiCmd('⌘V'));
64241           };
64242
64243           return behavior;
64244         }
64245
64246         /*
64247             `behaviorDrag` is like `d3_behavior.drag`, with the following differences:
64248
64249             * The `origin` function is expected to return an [x, y] tuple rather than an
64250               {x, y} object.
64251             * The events are `start`, `move`, and `end`.
64252               (https://github.com/mbostock/d3/issues/563)
64253             * The `start` event is not dispatched until the first cursor movement occurs.
64254               (https://github.com/mbostock/d3/pull/368)
64255             * The `move` event has a `point` and `delta` [x, y] tuple properties rather
64256               than `x`, `y`, `dx`, and `dy` properties.
64257             * The `end` event is not dispatched if no movement occurs.
64258             * An `off` function is available that unbinds the drag's internal event handlers.
64259          */
64260
64261         function behaviorDrag() {
64262           var dispatch = dispatch$8('start', 'move', 'end'); // see also behaviorSelect
64263
64264           var _tolerancePx = 1; // keep this low to facilitate pixel-perfect micromapping
64265
64266           var _penTolerancePx = 4; // styluses can be touchy so require greater movement - #1981
64267
64268           var _origin = null;
64269           var _selector = '';
64270
64271           var _targetNode;
64272
64273           var _targetEntity;
64274
64275           var _surface;
64276
64277           var _pointerId; // use pointer events on supported platforms; fallback to mouse events
64278
64279
64280           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
64281
64282           var d3_event_userSelectProperty = utilPrefixCSSProperty('UserSelect');
64283
64284           var d3_event_userSelectSuppress = function d3_event_userSelectSuppress() {
64285             var selection$1 = selection();
64286             var select = selection$1.style(d3_event_userSelectProperty);
64287             selection$1.style(d3_event_userSelectProperty, 'none');
64288             return function () {
64289               selection$1.style(d3_event_userSelectProperty, select);
64290             };
64291           };
64292
64293           function pointerdown(d3_event) {
64294             if (_pointerId) return;
64295             _pointerId = d3_event.pointerId || 'mouse';
64296             _targetNode = this; // only force reflow once per drag
64297
64298             var pointerLocGetter = utilFastMouse(_surface || _targetNode.parentNode);
64299             var offset;
64300             var startOrigin = pointerLocGetter(d3_event);
64301             var started = false;
64302             var selectEnable = d3_event_userSelectSuppress();
64303             select(window).on(_pointerPrefix + 'move.drag', pointermove).on(_pointerPrefix + 'up.drag pointercancel.drag', pointerup, true);
64304
64305             if (_origin) {
64306               offset = _origin.call(_targetNode, _targetEntity);
64307               offset = [offset[0] - startOrigin[0], offset[1] - startOrigin[1]];
64308             } else {
64309               offset = [0, 0];
64310             }
64311
64312             d3_event.stopPropagation();
64313
64314             function pointermove(d3_event) {
64315               if (_pointerId !== (d3_event.pointerId || 'mouse')) return;
64316               var p = pointerLocGetter(d3_event);
64317
64318               if (!started) {
64319                 var dist = geoVecLength(startOrigin, p);
64320                 var tolerance = d3_event.pointerType === 'pen' ? _penTolerancePx : _tolerancePx; // don't start until the drag has actually moved somewhat
64321
64322                 if (dist < tolerance) return;
64323                 started = true;
64324                 dispatch.call('start', this, d3_event, _targetEntity); // Don't send a `move` event in the same cycle as `start` since dragging
64325                 // a midpoint will convert the target to a node.
64326               } else {
64327                 startOrigin = p;
64328                 d3_event.stopPropagation();
64329                 d3_event.preventDefault();
64330                 var dx = p[0] - startOrigin[0];
64331                 var dy = p[1] - startOrigin[1];
64332                 dispatch.call('move', this, d3_event, _targetEntity, [p[0] + offset[0], p[1] + offset[1]], [dx, dy]);
64333               }
64334             }
64335
64336             function pointerup(d3_event) {
64337               if (_pointerId !== (d3_event.pointerId || 'mouse')) return;
64338               _pointerId = null;
64339
64340               if (started) {
64341                 dispatch.call('end', this, d3_event, _targetEntity);
64342                 d3_event.preventDefault();
64343               }
64344
64345               select(window).on(_pointerPrefix + 'move.drag', null).on(_pointerPrefix + 'up.drag pointercancel.drag', null);
64346               selectEnable();
64347             }
64348           }
64349
64350           function behavior(selection) {
64351             var matchesSelector = utilPrefixDOMProperty('matchesSelector');
64352             var delegate = pointerdown;
64353
64354             if (_selector) {
64355               delegate = function delegate(d3_event) {
64356                 var root = this;
64357                 var target = d3_event.target;
64358
64359                 for (; target && target !== root; target = target.parentNode) {
64360                   var datum = target.__data__;
64361                   _targetEntity = datum instanceof osmNote ? datum : datum && datum.properties && datum.properties.entity;
64362
64363                   if (_targetEntity && target[matchesSelector](_selector)) {
64364                     return pointerdown.call(target, d3_event);
64365                   }
64366                 }
64367               };
64368             }
64369
64370             selection.on(_pointerPrefix + 'down.drag' + _selector, delegate);
64371           }
64372
64373           behavior.off = function (selection) {
64374             selection.on(_pointerPrefix + 'down.drag' + _selector, null);
64375           };
64376
64377           behavior.selector = function (_) {
64378             if (!arguments.length) return _selector;
64379             _selector = _;
64380             return behavior;
64381           };
64382
64383           behavior.origin = function (_) {
64384             if (!arguments.length) return _origin;
64385             _origin = _;
64386             return behavior;
64387           };
64388
64389           behavior.cancel = function () {
64390             select(window).on(_pointerPrefix + 'move.drag', null).on(_pointerPrefix + 'up.drag pointercancel.drag', null);
64391             return behavior;
64392           };
64393
64394           behavior.targetNode = function (_) {
64395             if (!arguments.length) return _targetNode;
64396             _targetNode = _;
64397             return behavior;
64398           };
64399
64400           behavior.targetEntity = function (_) {
64401             if (!arguments.length) return _targetEntity;
64402             _targetEntity = _;
64403             return behavior;
64404           };
64405
64406           behavior.surface = function (_) {
64407             if (!arguments.length) return _surface;
64408             _surface = _;
64409             return behavior;
64410           };
64411
64412           return utilRebind(behavior, dispatch, 'on');
64413         }
64414
64415         function modeDragNode(context) {
64416           var mode = {
64417             id: 'drag-node',
64418             button: 'browse'
64419           };
64420           var hover = behaviorHover(context).altDisables(true).on('hover', context.ui().sidebar.hover);
64421           var edit = behaviorEdit(context);
64422
64423           var _nudgeInterval;
64424
64425           var _restoreSelectedIDs = [];
64426           var _wasMidpoint = false;
64427           var _isCancelled = false;
64428
64429           var _activeEntity;
64430
64431           var _startLoc;
64432
64433           var _lastLoc;
64434
64435           function startNudge(d3_event, entity, nudge) {
64436             if (_nudgeInterval) window.clearInterval(_nudgeInterval);
64437             _nudgeInterval = window.setInterval(function () {
64438               context.map().pan(nudge);
64439               doMove(d3_event, entity, nudge);
64440             }, 50);
64441           }
64442
64443           function stopNudge() {
64444             if (_nudgeInterval) {
64445               window.clearInterval(_nudgeInterval);
64446               _nudgeInterval = null;
64447             }
64448           }
64449
64450           function moveAnnotation(entity) {
64451             return _t('operations.move.annotation.' + entity.geometry(context.graph()));
64452           }
64453
64454           function connectAnnotation(nodeEntity, targetEntity) {
64455             var nodeGeometry = nodeEntity.geometry(context.graph());
64456             var targetGeometry = targetEntity.geometry(context.graph());
64457
64458             if (nodeGeometry === 'vertex' && targetGeometry === 'vertex') {
64459               var nodeParentWayIDs = context.graph().parentWays(nodeEntity);
64460               var targetParentWayIDs = context.graph().parentWays(targetEntity);
64461               var sharedParentWays = utilArrayIntersection(nodeParentWayIDs, targetParentWayIDs); // if both vertices are part of the same way
64462
64463               if (sharedParentWays.length !== 0) {
64464                 // if the nodes are next to each other, they are merged
64465                 if (sharedParentWays[0].areAdjacent(nodeEntity.id, targetEntity.id)) {
64466                   return _t('operations.connect.annotation.from_vertex.to_adjacent_vertex');
64467                 }
64468
64469                 return _t('operations.connect.annotation.from_vertex.to_sibling_vertex');
64470               }
64471             }
64472
64473             return _t('operations.connect.annotation.from_' + nodeGeometry + '.to_' + targetGeometry);
64474           }
64475
64476           function shouldSnapToNode(target) {
64477             if (!_activeEntity) return false;
64478             return _activeEntity.geometry(context.graph()) !== 'vertex' || target.geometry(context.graph()) === 'vertex' || _mainPresetIndex.allowsVertex(target, context.graph());
64479           }
64480
64481           function origin(entity) {
64482             return context.projection(entity.loc);
64483           }
64484
64485           function keydown(d3_event) {
64486             if (d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
64487               if (context.surface().classed('nope')) {
64488                 context.surface().classed('nope-suppressed', true);
64489               }
64490
64491               context.surface().classed('nope', false).classed('nope-disabled', true);
64492             }
64493           }
64494
64495           function keyup(d3_event) {
64496             if (d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
64497               if (context.surface().classed('nope-suppressed')) {
64498                 context.surface().classed('nope', true);
64499               }
64500
64501               context.surface().classed('nope-suppressed', false).classed('nope-disabled', false);
64502             }
64503           }
64504
64505           function start(d3_event, entity) {
64506             _wasMidpoint = entity.type === 'midpoint';
64507             var hasHidden = context.features().hasHiddenConnections(entity, context.graph());
64508             _isCancelled = !context.editable() || d3_event.shiftKey || hasHidden;
64509
64510             if (_isCancelled) {
64511               if (hasHidden) {
64512                 context.ui().flash.duration(4000).iconName('#iD-icon-no').label(_t('modes.drag_node.connected_to_hidden'))();
64513               }
64514
64515               return drag.cancel();
64516             }
64517
64518             if (_wasMidpoint) {
64519               var midpoint = entity;
64520               entity = osmNode();
64521               context.perform(actionAddMidpoint(midpoint, entity));
64522               entity = context.entity(entity.id); // get post-action entity
64523
64524               var vertex = context.surface().selectAll('.' + entity.id);
64525               drag.targetNode(vertex.node()).targetEntity(entity);
64526             } else {
64527               context.perform(actionNoop());
64528             }
64529
64530             _activeEntity = entity;
64531             _startLoc = entity.loc;
64532             hover.ignoreVertex(entity.geometry(context.graph()) === 'vertex');
64533             context.surface().selectAll('.' + _activeEntity.id).classed('active', true);
64534             context.enter(mode);
64535           } // related code
64536           // - `behavior/draw.js` `datum()`
64537
64538
64539           function datum(d3_event) {
64540             if (!d3_event || d3_event.altKey) {
64541               return {};
64542             } else {
64543               // When dragging, snap only to touch targets..
64544               // (this excludes area fills and active drawing elements)
64545               var d = d3_event.target.__data__;
64546               return d && d.properties && d.properties.target ? d : {};
64547             }
64548           }
64549
64550           function doMove(d3_event, entity, nudge) {
64551             nudge = nudge || [0, 0];
64552             var currPoint = d3_event && d3_event.point || context.projection(_lastLoc);
64553             var currMouse = geoVecSubtract(currPoint, nudge);
64554             var loc = context.projection.invert(currMouse);
64555             var target, edge;
64556
64557             if (!_nudgeInterval) {
64558               // If not nudging at the edge of the viewport, try to snap..
64559               // related code
64560               // - `mode/drag_node.js`     `doMove()`
64561               // - `behavior/draw.js`      `click()`
64562               // - `behavior/draw_way.js`  `move()`
64563               var d = datum(d3_event);
64564               target = d && d.properties && d.properties.entity;
64565               var targetLoc = target && target.loc;
64566               var targetNodes = d && d.properties && d.properties.nodes;
64567
64568               if (targetLoc) {
64569                 // snap to node/vertex - a point target with `.loc`
64570                 if (shouldSnapToNode(target)) {
64571                   loc = targetLoc;
64572                 }
64573               } else if (targetNodes) {
64574                 // snap to way - a line target with `.nodes`
64575                 edge = geoChooseEdge(targetNodes, context.map().mouse(), context.projection, end.id);
64576
64577                 if (edge) {
64578                   loc = edge.loc;
64579                 }
64580               }
64581             }
64582
64583             context.replace(actionMoveNode(entity.id, loc)); // Below here: validations
64584
64585             var isInvalid = false; // Check if this connection to `target` could cause relations to break..
64586
64587             if (target) {
64588               isInvalid = hasRelationConflict(entity, target, edge, context.graph());
64589             } // Check if this drag causes the geometry to break..
64590
64591
64592             if (!isInvalid) {
64593               isInvalid = hasInvalidGeometry(entity, context.graph());
64594             }
64595
64596             var nope = context.surface().classed('nope');
64597
64598             if (isInvalid === 'relation' || isInvalid === 'restriction') {
64599               if (!nope) {
64600                 // about to nope - show hint
64601                 context.ui().flash.duration(4000).iconName('#iD-icon-no').label(_t.html('operations.connect.' + isInvalid, {
64602                   relation: _mainPresetIndex.item('type/restriction').name()
64603                 }))();
64604               }
64605             } else if (isInvalid) {
64606               var errorID = isInvalid === 'line' ? 'lines' : 'areas';
64607               context.ui().flash.duration(3000).iconName('#iD-icon-no').label(_t.html('self_intersection.error.' + errorID))();
64608             } else {
64609               if (nope) {
64610                 // about to un-nope, remove hint
64611                 context.ui().flash.duration(1).label('')();
64612               }
64613             }
64614
64615             var nopeDisabled = context.surface().classed('nope-disabled');
64616
64617             if (nopeDisabled) {
64618               context.surface().classed('nope', false).classed('nope-suppressed', isInvalid);
64619             } else {
64620               context.surface().classed('nope', isInvalid).classed('nope-suppressed', false);
64621             }
64622
64623             _lastLoc = loc;
64624           } // Uses `actionConnect.disabled()` to know whether this connection is ok..
64625
64626
64627           function hasRelationConflict(entity, target, edge, graph) {
64628             var testGraph = graph.update(); // copy
64629             // if snapping to way - add midpoint there and consider that the target..
64630
64631             if (edge) {
64632               var midpoint = osmNode();
64633               var action = actionAddMidpoint({
64634                 loc: edge.loc,
64635                 edge: [target.nodes[edge.index - 1], target.nodes[edge.index]]
64636               }, midpoint);
64637               testGraph = action(testGraph);
64638               target = midpoint;
64639             } // can we connect to it?
64640
64641
64642             var ids = [entity.id, target.id];
64643             return actionConnect(ids).disabled(testGraph);
64644           }
64645
64646           function hasInvalidGeometry(entity, graph) {
64647             var parents = graph.parentWays(entity);
64648             var i, j, k;
64649
64650             for (i = 0; i < parents.length; i++) {
64651               var parent = parents[i];
64652               var nodes = [];
64653               var activeIndex = null; // which multipolygon ring contains node being dragged
64654               // test any parent multipolygons for valid geometry
64655
64656               var relations = graph.parentRelations(parent);
64657
64658               for (j = 0; j < relations.length; j++) {
64659                 if (!relations[j].isMultipolygon()) continue;
64660                 var rings = osmJoinWays(relations[j].members, graph); // find active ring and test it for self intersections
64661
64662                 for (k = 0; k < rings.length; k++) {
64663                   nodes = rings[k].nodes;
64664
64665                   if (nodes.find(function (n) {
64666                     return n.id === entity.id;
64667                   })) {
64668                     activeIndex = k;
64669
64670                     if (geoHasSelfIntersections(nodes, entity.id)) {
64671                       return 'multipolygonMember';
64672                     }
64673                   }
64674
64675                   rings[k].coords = nodes.map(function (n) {
64676                     return n.loc;
64677                   });
64678                 } // test active ring for intersections with other rings in the multipolygon
64679
64680
64681                 for (k = 0; k < rings.length; k++) {
64682                   if (k === activeIndex) continue; // make sure active ring doesn't cross passive rings
64683
64684                   if (geoHasLineIntersections(rings[activeIndex].nodes, rings[k].nodes, entity.id)) {
64685                     return 'multipolygonRing';
64686                   }
64687                 }
64688               } // If we still haven't tested this node's parent way for self-intersections.
64689               // (because it's not a member of a multipolygon), test it now.
64690
64691
64692               if (activeIndex === null) {
64693                 nodes = parent.nodes.map(function (nodeID) {
64694                   return graph.entity(nodeID);
64695                 });
64696
64697                 if (nodes.length && geoHasSelfIntersections(nodes, entity.id)) {
64698                   return parent.geometry(graph);
64699                 }
64700               }
64701             }
64702
64703             return false;
64704           }
64705
64706           function move(d3_event, entity, point) {
64707             if (_isCancelled) return;
64708             d3_event.stopPropagation();
64709             context.surface().classed('nope-disabled', d3_event.altKey);
64710             _lastLoc = context.projection.invert(point);
64711             doMove(d3_event, entity);
64712             var nudge = geoViewportEdge(point, context.map().dimensions());
64713
64714             if (nudge) {
64715               startNudge(d3_event, entity, nudge);
64716             } else {
64717               stopNudge();
64718             }
64719           }
64720
64721           function end(d3_event, entity) {
64722             if (_isCancelled) return;
64723             var wasPoint = entity.geometry(context.graph()) === 'point';
64724             var d = datum(d3_event);
64725             var nope = d && d.properties && d.properties.nope || context.surface().classed('nope');
64726             var target = d && d.properties && d.properties.entity; // entity to snap to
64727
64728             if (nope) {
64729               // bounce back
64730               context.perform(_actionBounceBack(entity.id, _startLoc));
64731             } else if (target && target.type === 'way') {
64732               var choice = geoChooseEdge(context.graph().childNodes(target), context.map().mouse(), context.projection, entity.id);
64733               context.replace(actionAddMidpoint({
64734                 loc: choice.loc,
64735                 edge: [target.nodes[choice.index - 1], target.nodes[choice.index]]
64736               }, entity), connectAnnotation(entity, target));
64737             } else if (target && target.type === 'node' && shouldSnapToNode(target)) {
64738               context.replace(actionConnect([target.id, entity.id]), connectAnnotation(entity, target));
64739             } else if (_wasMidpoint) {
64740               context.replace(actionNoop(), _t('operations.add.annotation.vertex'));
64741             } else {
64742               context.replace(actionNoop(), moveAnnotation(entity));
64743             }
64744
64745             if (wasPoint) {
64746               context.enter(modeSelect(context, [entity.id]));
64747             } else {
64748               var reselection = _restoreSelectedIDs.filter(function (id) {
64749                 return context.graph().hasEntity(id);
64750               });
64751
64752               if (reselection.length) {
64753                 context.enter(modeSelect(context, reselection));
64754               } else {
64755                 context.enter(modeBrowse(context));
64756               }
64757             }
64758           }
64759
64760           function _actionBounceBack(nodeID, toLoc) {
64761             var moveNode = actionMoveNode(nodeID, toLoc);
64762
64763             var action = function action(graph, t) {
64764               // last time through, pop off the bounceback perform.
64765               // it will then overwrite the initial perform with a moveNode that does nothing
64766               if (t === 1) context.pop();
64767               return moveNode(graph, t);
64768             };
64769
64770             action.transitionable = true;
64771             return action;
64772           }
64773
64774           function cancel() {
64775             drag.cancel();
64776             context.enter(modeBrowse(context));
64777           }
64778
64779           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);
64780
64781           mode.enter = function () {
64782             context.install(hover);
64783             context.install(edit);
64784             select(window).on('keydown.dragNode', keydown).on('keyup.dragNode', keyup);
64785             context.history().on('undone.drag-node', cancel);
64786           };
64787
64788           mode.exit = function () {
64789             context.ui().sidebar.hover.cancel();
64790             context.uninstall(hover);
64791             context.uninstall(edit);
64792             select(window).on('keydown.dragNode', null).on('keyup.dragNode', null);
64793             context.history().on('undone.drag-node', null);
64794             _activeEntity = null;
64795             context.surface().classed('nope', false).classed('nope-suppressed', false).classed('nope-disabled', false).selectAll('.active').classed('active', false);
64796             stopNudge();
64797           };
64798
64799           mode.selectedIDs = function () {
64800             if (!arguments.length) return _activeEntity ? [_activeEntity.id] : []; // no assign
64801
64802             return mode;
64803           };
64804
64805           mode.activeID = function () {
64806             if (!arguments.length) return _activeEntity && _activeEntity.id; // no assign
64807
64808             return mode;
64809           };
64810
64811           mode.restoreSelectedIDs = function (_) {
64812             if (!arguments.length) return _restoreSelectedIDs;
64813             _restoreSelectedIDs = _;
64814             return mode;
64815           };
64816
64817           mode.behavior = drag;
64818           return mode;
64819         }
64820
64821         var $$3 = _export;
64822         var NativePromise = nativePromiseConstructor;
64823         var fails$1 = fails$S;
64824         var getBuiltIn = getBuiltIn$b;
64825         var isCallable = isCallable$r;
64826         var speciesConstructor = speciesConstructor$5;
64827         var promiseResolve = promiseResolve$2;
64828         var redefine$1 = redefine$h.exports;
64829
64830         // Safari bug https://bugs.webkit.org/show_bug.cgi?id=200829
64831         var NON_GENERIC = !!NativePromise && fails$1(function () {
64832           NativePromise.prototype['finally'].call({ then: function () { /* empty */ } }, function () { /* empty */ });
64833         });
64834
64835         // `Promise.prototype.finally` method
64836         // https://tc39.es/ecma262/#sec-promise.prototype.finally
64837         $$3({ target: 'Promise', proto: true, real: true, forced: NON_GENERIC }, {
64838           'finally': function (onFinally) {
64839             var C = speciesConstructor(this, getBuiltIn('Promise'));
64840             var isFunction = isCallable(onFinally);
64841             return this.then(
64842               isFunction ? function (x) {
64843                 return promiseResolve(C, onFinally()).then(function () { return x; });
64844               } : onFinally,
64845               isFunction ? function (e) {
64846                 return promiseResolve(C, onFinally()).then(function () { throw e; });
64847               } : onFinally
64848             );
64849           }
64850         });
64851
64852         // makes sure that native promise-based APIs `Promise#finally` properly works with patched `Promise#then`
64853         if (isCallable(NativePromise)) {
64854           var method = getBuiltIn('Promise').prototype['finally'];
64855           if (NativePromise.prototype['finally'] !== method) {
64856             redefine$1(NativePromise.prototype, 'finally', method, { unsafe: true });
64857           }
64858         }
64859
64860         function quickselect(arr, k, left, right, compare) {
64861           quickselectStep(arr, k, left || 0, right || arr.length - 1, compare || defaultCompare);
64862         }
64863
64864         function quickselectStep(arr, k, left, right, compare) {
64865           while (right > left) {
64866             if (right - left > 600) {
64867               var n = right - left + 1;
64868               var m = k - left + 1;
64869               var z = Math.log(n);
64870               var s = 0.5 * Math.exp(2 * z / 3);
64871               var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
64872               var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
64873               var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
64874               quickselectStep(arr, k, newLeft, newRight, compare);
64875             }
64876
64877             var t = arr[k];
64878             var i = left;
64879             var j = right;
64880             swap(arr, left, k);
64881             if (compare(arr[right], t) > 0) swap(arr, left, right);
64882
64883             while (i < j) {
64884               swap(arr, i, j);
64885               i++;
64886               j--;
64887
64888               while (compare(arr[i], t) < 0) {
64889                 i++;
64890               }
64891
64892               while (compare(arr[j], t) > 0) {
64893                 j--;
64894               }
64895             }
64896
64897             if (compare(arr[left], t) === 0) swap(arr, left, j);else {
64898               j++;
64899               swap(arr, j, right);
64900             }
64901             if (j <= k) left = j + 1;
64902             if (k <= j) right = j - 1;
64903           }
64904         }
64905
64906         function swap(arr, i, j) {
64907           var tmp = arr[i];
64908           arr[i] = arr[j];
64909           arr[j] = tmp;
64910         }
64911
64912         function defaultCompare(a, b) {
64913           return a < b ? -1 : a > b ? 1 : 0;
64914         }
64915
64916         var RBush = /*#__PURE__*/function () {
64917           function RBush() {
64918             var maxEntries = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 9;
64919
64920             _classCallCheck$1(this, RBush);
64921
64922             // max entries in a node is 9 by default; min node fill is 40% for best performance
64923             this._maxEntries = Math.max(4, maxEntries);
64924             this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
64925             this.clear();
64926           }
64927
64928           _createClass$1(RBush, [{
64929             key: "all",
64930             value: function all() {
64931               return this._all(this.data, []);
64932             }
64933           }, {
64934             key: "search",
64935             value: function search(bbox) {
64936               var node = this.data;
64937               var result = [];
64938               if (!intersects(bbox, node)) return result;
64939               var toBBox = this.toBBox;
64940               var nodesToSearch = [];
64941
64942               while (node) {
64943                 for (var i = 0; i < node.children.length; i++) {
64944                   var child = node.children[i];
64945                   var childBBox = node.leaf ? toBBox(child) : child;
64946
64947                   if (intersects(bbox, childBBox)) {
64948                     if (node.leaf) result.push(child);else if (contains(bbox, childBBox)) this._all(child, result);else nodesToSearch.push(child);
64949                   }
64950                 }
64951
64952                 node = nodesToSearch.pop();
64953               }
64954
64955               return result;
64956             }
64957           }, {
64958             key: "collides",
64959             value: function collides(bbox) {
64960               var node = this.data;
64961               if (!intersects(bbox, node)) return false;
64962               var nodesToSearch = [];
64963
64964               while (node) {
64965                 for (var i = 0; i < node.children.length; i++) {
64966                   var child = node.children[i];
64967                   var childBBox = node.leaf ? this.toBBox(child) : child;
64968
64969                   if (intersects(bbox, childBBox)) {
64970                     if (node.leaf || contains(bbox, childBBox)) return true;
64971                     nodesToSearch.push(child);
64972                   }
64973                 }
64974
64975                 node = nodesToSearch.pop();
64976               }
64977
64978               return false;
64979             }
64980           }, {
64981             key: "load",
64982             value: function load(data) {
64983               if (!(data && data.length)) return this;
64984
64985               if (data.length < this._minEntries) {
64986                 for (var i = 0; i < data.length; i++) {
64987                   this.insert(data[i]);
64988                 }
64989
64990                 return this;
64991               } // recursively build the tree with the given data from scratch using OMT algorithm
64992
64993
64994               var node = this._build(data.slice(), 0, data.length - 1, 0);
64995
64996               if (!this.data.children.length) {
64997                 // save as is if tree is empty
64998                 this.data = node;
64999               } else if (this.data.height === node.height) {
65000                 // split root if trees have the same height
65001                 this._splitRoot(this.data, node);
65002               } else {
65003                 if (this.data.height < node.height) {
65004                   // swap trees if inserted one is bigger
65005                   var tmpNode = this.data;
65006                   this.data = node;
65007                   node = tmpNode;
65008                 } // insert the small tree into the large tree at appropriate level
65009
65010
65011                 this._insert(node, this.data.height - node.height - 1, true);
65012               }
65013
65014               return this;
65015             }
65016           }, {
65017             key: "insert",
65018             value: function insert(item) {
65019               if (item) this._insert(item, this.data.height - 1);
65020               return this;
65021             }
65022           }, {
65023             key: "clear",
65024             value: function clear() {
65025               this.data = createNode([]);
65026               return this;
65027             }
65028           }, {
65029             key: "remove",
65030             value: function remove(item, equalsFn) {
65031               if (!item) return this;
65032               var node = this.data;
65033               var bbox = this.toBBox(item);
65034               var path = [];
65035               var indexes = [];
65036               var i, parent, goingUp; // depth-first iterative tree traversal
65037
65038               while (node || path.length) {
65039                 if (!node) {
65040                   // go up
65041                   node = path.pop();
65042                   parent = path[path.length - 1];
65043                   i = indexes.pop();
65044                   goingUp = true;
65045                 }
65046
65047                 if (node.leaf) {
65048                   // check current node
65049                   var index = findItem(item, node.children, equalsFn);
65050
65051                   if (index !== -1) {
65052                     // item found, remove the item and condense tree upwards
65053                     node.children.splice(index, 1);
65054                     path.push(node);
65055
65056                     this._condense(path);
65057
65058                     return this;
65059                   }
65060                 }
65061
65062                 if (!goingUp && !node.leaf && contains(node, bbox)) {
65063                   // go down
65064                   path.push(node);
65065                   indexes.push(i);
65066                   i = 0;
65067                   parent = node;
65068                   node = node.children[0];
65069                 } else if (parent) {
65070                   // go right
65071                   i++;
65072                   node = parent.children[i];
65073                   goingUp = false;
65074                 } else node = null; // nothing found
65075
65076               }
65077
65078               return this;
65079             }
65080           }, {
65081             key: "toBBox",
65082             value: function toBBox(item) {
65083               return item;
65084             }
65085           }, {
65086             key: "compareMinX",
65087             value: function compareMinX(a, b) {
65088               return a.minX - b.minX;
65089             }
65090           }, {
65091             key: "compareMinY",
65092             value: function compareMinY(a, b) {
65093               return a.minY - b.minY;
65094             }
65095           }, {
65096             key: "toJSON",
65097             value: function toJSON() {
65098               return this.data;
65099             }
65100           }, {
65101             key: "fromJSON",
65102             value: function fromJSON(data) {
65103               this.data = data;
65104               return this;
65105             }
65106           }, {
65107             key: "_all",
65108             value: function _all(node, result) {
65109               var nodesToSearch = [];
65110
65111               while (node) {
65112                 if (node.leaf) result.push.apply(result, _toConsumableArray(node.children));else nodesToSearch.push.apply(nodesToSearch, _toConsumableArray(node.children));
65113                 node = nodesToSearch.pop();
65114               }
65115
65116               return result;
65117             }
65118           }, {
65119             key: "_build",
65120             value: function _build(items, left, right, height) {
65121               var N = right - left + 1;
65122               var M = this._maxEntries;
65123               var node;
65124
65125               if (N <= M) {
65126                 // reached leaf level; return leaf
65127                 node = createNode(items.slice(left, right + 1));
65128                 calcBBox(node, this.toBBox);
65129                 return node;
65130               }
65131
65132               if (!height) {
65133                 // target height of the bulk-loaded tree
65134                 height = Math.ceil(Math.log(N) / Math.log(M)); // target number of root entries to maximize storage utilization
65135
65136                 M = Math.ceil(N / Math.pow(M, height - 1));
65137               }
65138
65139               node = createNode([]);
65140               node.leaf = false;
65141               node.height = height; // split the items into M mostly square tiles
65142
65143               var N2 = Math.ceil(N / M);
65144               var N1 = N2 * Math.ceil(Math.sqrt(M));
65145               multiSelect(items, left, right, N1, this.compareMinX);
65146
65147               for (var i = left; i <= right; i += N1) {
65148                 var right2 = Math.min(i + N1 - 1, right);
65149                 multiSelect(items, i, right2, N2, this.compareMinY);
65150
65151                 for (var j = i; j <= right2; j += N2) {
65152                   var right3 = Math.min(j + N2 - 1, right2); // pack each entry recursively
65153
65154                   node.children.push(this._build(items, j, right3, height - 1));
65155                 }
65156               }
65157
65158               calcBBox(node, this.toBBox);
65159               return node;
65160             }
65161           }, {
65162             key: "_chooseSubtree",
65163             value: function _chooseSubtree(bbox, node, level, path) {
65164               while (true) {
65165                 path.push(node);
65166                 if (node.leaf || path.length - 1 === level) break;
65167                 var minArea = Infinity;
65168                 var minEnlargement = Infinity;
65169                 var targetNode = void 0;
65170
65171                 for (var i = 0; i < node.children.length; i++) {
65172                   var child = node.children[i];
65173                   var area = bboxArea(child);
65174                   var enlargement = enlargedArea(bbox, child) - area; // choose entry with the least area enlargement
65175
65176                   if (enlargement < minEnlargement) {
65177                     minEnlargement = enlargement;
65178                     minArea = area < minArea ? area : minArea;
65179                     targetNode = child;
65180                   } else if (enlargement === minEnlargement) {
65181                     // otherwise choose one with the smallest area
65182                     if (area < minArea) {
65183                       minArea = area;
65184                       targetNode = child;
65185                     }
65186                   }
65187                 }
65188
65189                 node = targetNode || node.children[0];
65190               }
65191
65192               return node;
65193             }
65194           }, {
65195             key: "_insert",
65196             value: function _insert(item, level, isNode) {
65197               var bbox = isNode ? item : this.toBBox(item);
65198               var insertPath = []; // find the best node for accommodating the item, saving all nodes along the path too
65199
65200               var node = this._chooseSubtree(bbox, this.data, level, insertPath); // put the item into the node
65201
65202
65203               node.children.push(item);
65204               extend$1(node, bbox); // split on node overflow; propagate upwards if necessary
65205
65206               while (level >= 0) {
65207                 if (insertPath[level].children.length > this._maxEntries) {
65208                   this._split(insertPath, level);
65209
65210                   level--;
65211                 } else break;
65212               } // adjust bboxes along the insertion path
65213
65214
65215               this._adjustParentBBoxes(bbox, insertPath, level);
65216             } // split overflowed node into two
65217
65218           }, {
65219             key: "_split",
65220             value: function _split(insertPath, level) {
65221               var node = insertPath[level];
65222               var M = node.children.length;
65223               var m = this._minEntries;
65224
65225               this._chooseSplitAxis(node, m, M);
65226
65227               var splitIndex = this._chooseSplitIndex(node, m, M);
65228
65229               var newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
65230               newNode.height = node.height;
65231               newNode.leaf = node.leaf;
65232               calcBBox(node, this.toBBox);
65233               calcBBox(newNode, this.toBBox);
65234               if (level) insertPath[level - 1].children.push(newNode);else this._splitRoot(node, newNode);
65235             }
65236           }, {
65237             key: "_splitRoot",
65238             value: function _splitRoot(node, newNode) {
65239               // split root node
65240               this.data = createNode([node, newNode]);
65241               this.data.height = node.height + 1;
65242               this.data.leaf = false;
65243               calcBBox(this.data, this.toBBox);
65244             }
65245           }, {
65246             key: "_chooseSplitIndex",
65247             value: function _chooseSplitIndex(node, m, M) {
65248               var index;
65249               var minOverlap = Infinity;
65250               var minArea = Infinity;
65251
65252               for (var i = m; i <= M - m; i++) {
65253                 var bbox1 = distBBox(node, 0, i, this.toBBox);
65254                 var bbox2 = distBBox(node, i, M, this.toBBox);
65255                 var overlap = intersectionArea(bbox1, bbox2);
65256                 var area = bboxArea(bbox1) + bboxArea(bbox2); // choose distribution with minimum overlap
65257
65258                 if (overlap < minOverlap) {
65259                   minOverlap = overlap;
65260                   index = i;
65261                   minArea = area < minArea ? area : minArea;
65262                 } else if (overlap === minOverlap) {
65263                   // otherwise choose distribution with minimum area
65264                   if (area < minArea) {
65265                     minArea = area;
65266                     index = i;
65267                   }
65268                 }
65269               }
65270
65271               return index || M - m;
65272             } // sorts node children by the best axis for split
65273
65274           }, {
65275             key: "_chooseSplitAxis",
65276             value: function _chooseSplitAxis(node, m, M) {
65277               var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX;
65278               var compareMinY = node.leaf ? this.compareMinY : compareNodeMinY;
65279
65280               var xMargin = this._allDistMargin(node, m, M, compareMinX);
65281
65282               var yMargin = this._allDistMargin(node, m, M, compareMinY); // if total distributions margin value is minimal for x, sort by minX,
65283               // otherwise it's already sorted by minY
65284
65285
65286               if (xMargin < yMargin) node.children.sort(compareMinX);
65287             } // total margin of all possible split distributions where each node is at least m full
65288
65289           }, {
65290             key: "_allDistMargin",
65291             value: function _allDistMargin(node, m, M, compare) {
65292               node.children.sort(compare);
65293               var toBBox = this.toBBox;
65294               var leftBBox = distBBox(node, 0, m, toBBox);
65295               var rightBBox = distBBox(node, M - m, M, toBBox);
65296               var margin = bboxMargin(leftBBox) + bboxMargin(rightBBox);
65297
65298               for (var i = m; i < M - m; i++) {
65299                 var child = node.children[i];
65300                 extend$1(leftBBox, node.leaf ? toBBox(child) : child);
65301                 margin += bboxMargin(leftBBox);
65302               }
65303
65304               for (var _i = M - m - 1; _i >= m; _i--) {
65305                 var _child = node.children[_i];
65306                 extend$1(rightBBox, node.leaf ? toBBox(_child) : _child);
65307                 margin += bboxMargin(rightBBox);
65308               }
65309
65310               return margin;
65311             }
65312           }, {
65313             key: "_adjustParentBBoxes",
65314             value: function _adjustParentBBoxes(bbox, path, level) {
65315               // adjust bboxes along the given tree path
65316               for (var i = level; i >= 0; i--) {
65317                 extend$1(path[i], bbox);
65318               }
65319             }
65320           }, {
65321             key: "_condense",
65322             value: function _condense(path) {
65323               // go through the path, removing empty nodes and updating bboxes
65324               for (var i = path.length - 1, siblings; i >= 0; i--) {
65325                 if (path[i].children.length === 0) {
65326                   if (i > 0) {
65327                     siblings = path[i - 1].children;
65328                     siblings.splice(siblings.indexOf(path[i]), 1);
65329                   } else this.clear();
65330                 } else calcBBox(path[i], this.toBBox);
65331               }
65332             }
65333           }]);
65334
65335           return RBush;
65336         }();
65337
65338         function findItem(item, items, equalsFn) {
65339           if (!equalsFn) return items.indexOf(item);
65340
65341           for (var i = 0; i < items.length; i++) {
65342             if (equalsFn(item, items[i])) return i;
65343           }
65344
65345           return -1;
65346         } // calculate node's bbox from bboxes of its children
65347
65348
65349         function calcBBox(node, toBBox) {
65350           distBBox(node, 0, node.children.length, toBBox, node);
65351         } // min bounding rectangle of node children from k to p-1
65352
65353
65354         function distBBox(node, k, p, toBBox, destNode) {
65355           if (!destNode) destNode = createNode(null);
65356           destNode.minX = Infinity;
65357           destNode.minY = Infinity;
65358           destNode.maxX = -Infinity;
65359           destNode.maxY = -Infinity;
65360
65361           for (var i = k; i < p; i++) {
65362             var child = node.children[i];
65363             extend$1(destNode, node.leaf ? toBBox(child) : child);
65364           }
65365
65366           return destNode;
65367         }
65368
65369         function extend$1(a, b) {
65370           a.minX = Math.min(a.minX, b.minX);
65371           a.minY = Math.min(a.minY, b.minY);
65372           a.maxX = Math.max(a.maxX, b.maxX);
65373           a.maxY = Math.max(a.maxY, b.maxY);
65374           return a;
65375         }
65376
65377         function compareNodeMinX(a, b) {
65378           return a.minX - b.minX;
65379         }
65380
65381         function compareNodeMinY(a, b) {
65382           return a.minY - b.minY;
65383         }
65384
65385         function bboxArea(a) {
65386           return (a.maxX - a.minX) * (a.maxY - a.minY);
65387         }
65388
65389         function bboxMargin(a) {
65390           return a.maxX - a.minX + (a.maxY - a.minY);
65391         }
65392
65393         function enlargedArea(a, b) {
65394           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));
65395         }
65396
65397         function intersectionArea(a, b) {
65398           var minX = Math.max(a.minX, b.minX);
65399           var minY = Math.max(a.minY, b.minY);
65400           var maxX = Math.min(a.maxX, b.maxX);
65401           var maxY = Math.min(a.maxY, b.maxY);
65402           return Math.max(0, maxX - minX) * Math.max(0, maxY - minY);
65403         }
65404
65405         function contains(a, b) {
65406           return a.minX <= b.minX && a.minY <= b.minY && b.maxX <= a.maxX && b.maxY <= a.maxY;
65407         }
65408
65409         function intersects(a, b) {
65410           return b.minX <= a.maxX && b.minY <= a.maxY && b.maxX >= a.minX && b.maxY >= a.minY;
65411         }
65412
65413         function createNode(children) {
65414           return {
65415             children: children,
65416             height: 1,
65417             leaf: true,
65418             minX: Infinity,
65419             minY: Infinity,
65420             maxX: -Infinity,
65421             maxY: -Infinity
65422           };
65423         } // sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
65424         // combines selection algorithm with binary divide & conquer approach
65425
65426
65427         function multiSelect(arr, left, right, n, compare) {
65428           var stack = [left, right];
65429
65430           while (stack.length) {
65431             right = stack.pop();
65432             left = stack.pop();
65433             if (right - left <= n) continue;
65434             var mid = left + Math.ceil((right - left) / n / 2) * n;
65435             quickselect(arr, mid, left, right, compare);
65436             stack.push(left, mid, mid, right);
65437           }
65438         }
65439
65440         function responseText(response) {
65441           if (!response.ok) throw new Error(response.status + " " + response.statusText);
65442           return response.text();
65443         }
65444
65445         function d3_text (input, init) {
65446           return fetch(input, init).then(responseText);
65447         }
65448
65449         function responseJson(response) {
65450           if (!response.ok) throw new Error(response.status + " " + response.statusText);
65451           if (response.status === 204 || response.status === 205) return;
65452           return response.json();
65453         }
65454
65455         function d3_json (input, init) {
65456           return fetch(input, init).then(responseJson);
65457         }
65458
65459         function parser(type) {
65460           return function (input, init) {
65461             return d3_text(input, init).then(function (text) {
65462               return new DOMParser().parseFromString(text, type);
65463             });
65464           };
65465         }
65466
65467         var d3_xml = parser("application/xml");
65468         var svg = parser("image/svg+xml");
65469
65470         var tiler$6 = utilTiler();
65471         var dispatch$7 = dispatch$8('loaded');
65472         var _tileZoom$3 = 14;
65473         var _krUrlRoot = 'https://www.keepright.at';
65474         var _krData = {
65475           errorTypes: {},
65476           localizeStrings: {}
65477         }; // This gets reassigned if reset
65478
65479         var _cache$2;
65480
65481         var _krRuleset = [// no 20 - multiple node on same spot - these are mostly boundaries overlapping roads
65482         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];
65483
65484         function abortRequest$6(controller) {
65485           if (controller) {
65486             controller.abort();
65487           }
65488         }
65489
65490         function abortUnwantedRequests$3(cache, tiles) {
65491           Object.keys(cache.inflightTile).forEach(function (k) {
65492             var wanted = tiles.find(function (tile) {
65493               return k === tile.id;
65494             });
65495
65496             if (!wanted) {
65497               abortRequest$6(cache.inflightTile[k]);
65498               delete cache.inflightTile[k];
65499             }
65500           });
65501         }
65502
65503         function encodeIssueRtree$2(d) {
65504           return {
65505             minX: d.loc[0],
65506             minY: d.loc[1],
65507             maxX: d.loc[0],
65508             maxY: d.loc[1],
65509             data: d
65510           };
65511         } // Replace or remove QAItem from rtree
65512
65513
65514         function updateRtree$3(item, replace) {
65515           _cache$2.rtree.remove(item, function (a, b) {
65516             return a.data.id === b.data.id;
65517           });
65518
65519           if (replace) {
65520             _cache$2.rtree.insert(item);
65521           }
65522         }
65523
65524         function tokenReplacements(d) {
65525           if (!(d instanceof QAItem)) return;
65526           var htmlRegex = new RegExp(/<\/[a-z][\s\S]*>/);
65527           var replacements = {};
65528           var issueTemplate = _krData.errorTypes[d.whichType];
65529
65530           if (!issueTemplate) {
65531             /* eslint-disable no-console */
65532             console.log('No Template: ', d.whichType);
65533             console.log('  ', d.description);
65534             /* eslint-enable no-console */
65535
65536             return;
65537           } // some descriptions are just fixed text
65538
65539
65540           if (!issueTemplate.regex) return; // regex pattern should match description with variable details captured
65541
65542           var errorRegex = new RegExp(issueTemplate.regex, 'i');
65543           var errorMatch = errorRegex.exec(d.description);
65544
65545           if (!errorMatch) {
65546             /* eslint-disable no-console */
65547             console.log('Unmatched: ', d.whichType);
65548             console.log('  ', d.description);
65549             console.log('  ', errorRegex);
65550             /* eslint-enable no-console */
65551
65552             return;
65553           }
65554
65555           for (var i = 1; i < errorMatch.length; i++) {
65556             // skip first
65557             var capture = errorMatch[i];
65558             var idType = void 0;
65559             idType = 'IDs' in issueTemplate ? issueTemplate.IDs[i - 1] : '';
65560
65561             if (idType && capture) {
65562               // link IDs if present in the capture
65563               capture = parseError(capture, idType);
65564             } else if (htmlRegex.test(capture)) {
65565               // escape any html in non-IDs
65566               capture = '\\' + capture + '\\';
65567             } else {
65568               var compare = capture.toLowerCase();
65569
65570               if (_krData.localizeStrings[compare]) {
65571                 // some replacement strings can be localized
65572                 capture = _t('QA.keepRight.error_parts.' + _krData.localizeStrings[compare]);
65573               }
65574             }
65575
65576             replacements['var' + i] = capture;
65577           }
65578
65579           return replacements;
65580         }
65581
65582         function parseError(capture, idType) {
65583           var compare = capture.toLowerCase();
65584
65585           if (_krData.localizeStrings[compare]) {
65586             // some replacement strings can be localized
65587             capture = _t('QA.keepRight.error_parts.' + _krData.localizeStrings[compare]);
65588           }
65589
65590           switch (idType) {
65591             // link a string like "this node"
65592             case 'this':
65593               capture = linkErrorObject(capture);
65594               break;
65595
65596             case 'url':
65597               capture = linkURL(capture);
65598               break;
65599             // link an entity ID
65600
65601             case 'n':
65602             case 'w':
65603             case 'r':
65604               capture = linkEntity(idType + capture);
65605               break;
65606             // some errors have more complex ID lists/variance
65607
65608             case '20':
65609               capture = parse20(capture);
65610               break;
65611
65612             case '211':
65613               capture = parse211(capture);
65614               break;
65615
65616             case '231':
65617               capture = parse231(capture);
65618               break;
65619
65620             case '294':
65621               capture = parse294(capture);
65622               break;
65623
65624             case '370':
65625               capture = parse370(capture);
65626               break;
65627           }
65628
65629           return capture;
65630
65631           function linkErrorObject(d) {
65632             return "<a class=\"error_object_link\">".concat(d, "</a>");
65633           }
65634
65635           function linkEntity(d) {
65636             return "<a class=\"error_entity_link\">".concat(d, "</a>");
65637           }
65638
65639           function linkURL(d) {
65640             return "<a class=\"kr_external_link\" target=\"_blank\" href=\"".concat(d, "\">").concat(d, "</a>");
65641           } // arbitrary node list of form: #ID, #ID, #ID...
65642
65643
65644           function parse211(capture) {
65645             var newList = [];
65646             var items = capture.split(', ');
65647             items.forEach(function (item) {
65648               // ID has # at the front
65649               var id = linkEntity('n' + item.slice(1));
65650               newList.push(id);
65651             });
65652             return newList.join(', ');
65653           } // arbitrary way list of form: #ID(layer),#ID(layer),#ID(layer)...
65654
65655
65656           function parse231(capture) {
65657             var newList = []; // unfortunately 'layer' can itself contain commas, so we split on '),'
65658
65659             var items = capture.split('),');
65660             items.forEach(function (item) {
65661               var match = item.match(/\#(\d+)\((.+)\)?/);
65662
65663               if (match !== null && match.length > 2) {
65664                 newList.push(linkEntity('w' + match[1]) + ' ' + _t('QA.keepRight.errorTypes.231.layer', {
65665                   layer: match[2]
65666                 }));
65667               }
65668             });
65669             return newList.join(', ');
65670           } // arbitrary node/relation list of form: from node #ID,to relation #ID,to node #ID...
65671
65672
65673           function parse294(capture) {
65674             var newList = [];
65675             var items = capture.split(',');
65676             items.forEach(function (item) {
65677               // item of form "from/to node/relation #ID"
65678               item = item.split(' '); // to/from role is more clear in quotes
65679
65680               var role = "\"".concat(item[0], "\""); // first letter of node/relation provides the type
65681
65682               var idType = item[1].slice(0, 1); // ID has # at the front
65683
65684               var id = item[2].slice(1);
65685               id = linkEntity(idType + id);
65686               newList.push("".concat(role, " ").concat(item[1], " ").concat(id));
65687             });
65688             return newList.join(', ');
65689           } // may or may not include the string "(including the name 'name')"
65690
65691
65692           function parse370(capture) {
65693             if (!capture) return '';
65694             var match = capture.match(/\(including the name (\'.+\')\)/);
65695
65696             if (match && match.length) {
65697               return _t('QA.keepRight.errorTypes.370.including_the_name', {
65698                 name: match[1]
65699               });
65700             }
65701
65702             return '';
65703           } // arbitrary node list of form: #ID,#ID,#ID...
65704
65705
65706           function parse20(capture) {
65707             var newList = [];
65708             var items = capture.split(',');
65709             items.forEach(function (item) {
65710               // ID has # at the front
65711               var id = linkEntity('n' + item.slice(1));
65712               newList.push(id);
65713             });
65714             return newList.join(', ');
65715           }
65716         }
65717
65718         var serviceKeepRight = {
65719           title: 'keepRight',
65720           init: function init() {
65721             _mainFileFetcher.get('keepRight').then(function (d) {
65722               return _krData = d;
65723             });
65724
65725             if (!_cache$2) {
65726               this.reset();
65727             }
65728
65729             this.event = utilRebind(this, dispatch$7, 'on');
65730           },
65731           reset: function reset() {
65732             if (_cache$2) {
65733               Object.values(_cache$2.inflightTile).forEach(abortRequest$6);
65734             }
65735
65736             _cache$2 = {
65737               data: {},
65738               loadedTile: {},
65739               inflightTile: {},
65740               inflightPost: {},
65741               closed: {},
65742               rtree: new RBush()
65743             };
65744           },
65745           // KeepRight API:  http://osm.mueschelsoft.de/keepright/interfacing.php
65746           loadIssues: function loadIssues(projection) {
65747             var _this = this;
65748
65749             var options = {
65750               format: 'geojson',
65751               ch: _krRuleset
65752             }; // determine the needed tiles to cover the view
65753
65754             var tiles = tiler$6.zoomExtent([_tileZoom$3, _tileZoom$3]).getTiles(projection); // abort inflight requests that are no longer needed
65755
65756             abortUnwantedRequests$3(_cache$2, tiles); // issue new requests..
65757
65758             tiles.forEach(function (tile) {
65759               if (_cache$2.loadedTile[tile.id] || _cache$2.inflightTile[tile.id]) return;
65760
65761               var _tile$extent$rectangl = tile.extent.rectangle(),
65762                   _tile$extent$rectangl2 = _slicedToArray(_tile$extent$rectangl, 4),
65763                   left = _tile$extent$rectangl2[0],
65764                   top = _tile$extent$rectangl2[1],
65765                   right = _tile$extent$rectangl2[2],
65766                   bottom = _tile$extent$rectangl2[3];
65767
65768               var params = Object.assign({}, options, {
65769                 left: left,
65770                 bottom: bottom,
65771                 right: right,
65772                 top: top
65773               });
65774               var url = "".concat(_krUrlRoot, "/export.php?") + utilQsString(params);
65775               var controller = new AbortController();
65776               _cache$2.inflightTile[tile.id] = controller;
65777               d3_json(url, {
65778                 signal: controller.signal
65779               }).then(function (data) {
65780                 delete _cache$2.inflightTile[tile.id];
65781                 _cache$2.loadedTile[tile.id] = true;
65782
65783                 if (!data || !data.features || !data.features.length) {
65784                   throw new Error('No Data');
65785                 }
65786
65787                 data.features.forEach(function (feature) {
65788                   var _feature$properties = feature.properties,
65789                       itemType = _feature$properties.error_type,
65790                       id = _feature$properties.error_id,
65791                       _feature$properties$c = _feature$properties.comment,
65792                       comment = _feature$properties$c === void 0 ? null : _feature$properties$c,
65793                       objectId = _feature$properties.object_id,
65794                       objectType = _feature$properties.object_type,
65795                       schema = _feature$properties.schema,
65796                       title = _feature$properties.title;
65797                   var loc = feature.geometry.coordinates,
65798                       _feature$properties$d = feature.properties.description,
65799                       description = _feature$properties$d === void 0 ? '' : _feature$properties$d; // if there is a parent, save its error type e.g.:
65800                   //  Error 191 = "highway-highway"
65801                   //  Error 190 = "intersections without junctions"  (parent)
65802
65803                   var issueTemplate = _krData.errorTypes[itemType];
65804                   var parentIssueType = (Math.floor(itemType / 10) * 10).toString(); // try to handle error type directly, fallback to parent error type.
65805
65806                   var whichType = issueTemplate ? itemType : parentIssueType;
65807                   var whichTemplate = _krData.errorTypes[whichType]; // Rewrite a few of the errors at this point..
65808                   // This is done to make them easier to linkify and translate.
65809
65810                   switch (whichType) {
65811                     case '170':
65812                       description = "This feature has a FIXME tag: ".concat(description);
65813                       break;
65814
65815                     case '292':
65816                     case '293':
65817                       description = description.replace('A turn-', 'This turn-');
65818                       break;
65819
65820                     case '294':
65821                     case '295':
65822                     case '296':
65823                     case '297':
65824                     case '298':
65825                       description = "This turn-restriction~".concat(description);
65826                       break;
65827
65828                     case '300':
65829                       description = 'This highway is missing a maxspeed tag';
65830                       break;
65831
65832                     case '411':
65833                     case '412':
65834                     case '413':
65835                       description = "This feature~".concat(description);
65836                       break;
65837                   } // move markers slightly so it doesn't obscure the geometry,
65838                   // then move markers away from other coincident markers
65839
65840
65841                   var coincident = false;
65842
65843                   do {
65844                     // first time, move marker up. after that, move marker right.
65845                     var delta = coincident ? [0.00001, 0] : [0, 0.00001];
65846                     loc = geoVecAdd(loc, delta);
65847                     var bbox = geoExtent(loc).bbox();
65848                     coincident = _cache$2.rtree.search(bbox).length;
65849                   } while (coincident);
65850
65851                   var d = new QAItem(loc, _this, itemType, id, {
65852                     comment: comment,
65853                     description: description,
65854                     whichType: whichType,
65855                     parentIssueType: parentIssueType,
65856                     severity: whichTemplate.severity || 'error',
65857                     objectId: objectId,
65858                     objectType: objectType,
65859                     schema: schema,
65860                     title: title
65861                   });
65862                   d.replacements = tokenReplacements(d);
65863                   _cache$2.data[id] = d;
65864
65865                   _cache$2.rtree.insert(encodeIssueRtree$2(d));
65866                 });
65867                 dispatch$7.call('loaded');
65868               })["catch"](function () {
65869                 delete _cache$2.inflightTile[tile.id];
65870                 _cache$2.loadedTile[tile.id] = true;
65871               });
65872             });
65873           },
65874           postUpdate: function postUpdate(d, callback) {
65875             var _this2 = this;
65876
65877             if (_cache$2.inflightPost[d.id]) {
65878               return callback({
65879                 message: 'Error update already inflight',
65880                 status: -2
65881               }, d);
65882             }
65883
65884             var params = {
65885               schema: d.schema,
65886               id: d.id
65887             };
65888
65889             if (d.newStatus) {
65890               params.st = d.newStatus;
65891             }
65892
65893             if (d.newComment !== undefined) {
65894               params.co = d.newComment;
65895             } // NOTE: This throws a CORS err, but it seems successful.
65896             // We don't care too much about the response, so this is fine.
65897
65898
65899             var url = "".concat(_krUrlRoot, "/comment.php?") + utilQsString(params);
65900             var controller = new AbortController();
65901             _cache$2.inflightPost[d.id] = controller; // Since this is expected to throw an error just continue as if it worked
65902             // (worst case scenario the request truly fails and issue will show up if iD restarts)
65903
65904             d3_json(url, {
65905               signal: controller.signal
65906             })["finally"](function () {
65907               delete _cache$2.inflightPost[d.id];
65908
65909               if (d.newStatus === 'ignore') {
65910                 // ignore permanently (false positive)
65911                 _this2.removeItem(d);
65912               } else if (d.newStatus === 'ignore_t') {
65913                 // ignore temporarily (error fixed)
65914                 _this2.removeItem(d);
65915
65916                 _cache$2.closed["".concat(d.schema, ":").concat(d.id)] = true;
65917               } else {
65918                 d = _this2.replaceItem(d.update({
65919                   comment: d.newComment,
65920                   newComment: undefined,
65921                   newState: undefined
65922                 }));
65923               }
65924
65925               if (callback) callback(null, d);
65926             });
65927           },
65928           // Get all cached QAItems covering the viewport
65929           getItems: function getItems(projection) {
65930             var viewport = projection.clipExtent();
65931             var min = [viewport[0][0], viewport[1][1]];
65932             var max = [viewport[1][0], viewport[0][1]];
65933             var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();
65934             return _cache$2.rtree.search(bbox).map(function (d) {
65935               return d.data;
65936             });
65937           },
65938           // Get a QAItem from cache
65939           // NOTE: Don't change method name until UI v3 is merged
65940           getError: function getError(id) {
65941             return _cache$2.data[id];
65942           },
65943           // Replace a single QAItem in the cache
65944           replaceItem: function replaceItem(item) {
65945             if (!(item instanceof QAItem) || !item.id) return;
65946             _cache$2.data[item.id] = item;
65947             updateRtree$3(encodeIssueRtree$2(item), true); // true = replace
65948
65949             return item;
65950           },
65951           // Remove a single QAItem from the cache
65952           removeItem: function removeItem(item) {
65953             if (!(item instanceof QAItem) || !item.id) return;
65954             delete _cache$2.data[item.id];
65955             updateRtree$3(encodeIssueRtree$2(item), false); // false = remove
65956           },
65957           issueURL: function issueURL(item) {
65958             return "".concat(_krUrlRoot, "/report_map.php?schema=").concat(item.schema, "&error=").concat(item.id);
65959           },
65960           // Get an array of issues closed during this session.
65961           // Used to populate `closed:keepright` changeset tag
65962           getClosedIDs: function getClosedIDs() {
65963             return Object.keys(_cache$2.closed).sort();
65964           }
65965         };
65966
65967         var tiler$5 = utilTiler();
65968         var dispatch$6 = dispatch$8('loaded');
65969         var _tileZoom$2 = 14;
65970         var _impOsmUrls = {
65971           ow: 'https://grab.community.improve-osm.org/directionOfFlowService',
65972           mr: 'https://grab.community.improve-osm.org/missingGeoService',
65973           tr: 'https://grab.community.improve-osm.org/turnRestrictionService'
65974         };
65975         var _impOsmData = {
65976           icons: {}
65977         }; // This gets reassigned if reset
65978
65979         var _cache$1;
65980
65981         function abortRequest$5(i) {
65982           Object.values(i).forEach(function (controller) {
65983             if (controller) {
65984               controller.abort();
65985             }
65986           });
65987         }
65988
65989         function abortUnwantedRequests$2(cache, tiles) {
65990           Object.keys(cache.inflightTile).forEach(function (k) {
65991             var wanted = tiles.find(function (tile) {
65992               return k === tile.id;
65993             });
65994
65995             if (!wanted) {
65996               abortRequest$5(cache.inflightTile[k]);
65997               delete cache.inflightTile[k];
65998             }
65999           });
66000         }
66001
66002         function encodeIssueRtree$1(d) {
66003           return {
66004             minX: d.loc[0],
66005             minY: d.loc[1],
66006             maxX: d.loc[0],
66007             maxY: d.loc[1],
66008             data: d
66009           };
66010         } // Replace or remove QAItem from rtree
66011
66012
66013         function updateRtree$2(item, replace) {
66014           _cache$1.rtree.remove(item, function (a, b) {
66015             return a.data.id === b.data.id;
66016           });
66017
66018           if (replace) {
66019             _cache$1.rtree.insert(item);
66020           }
66021         }
66022
66023         function linkErrorObject(d) {
66024           return "<a class=\"error_object_link\">".concat(d, "</a>");
66025         }
66026
66027         function linkEntity(d) {
66028           return "<a class=\"error_entity_link\">".concat(d, "</a>");
66029         }
66030
66031         function pointAverage(points) {
66032           if (points.length) {
66033             var sum = points.reduce(function (acc, point) {
66034               return geoVecAdd(acc, [point.lon, point.lat]);
66035             }, [0, 0]);
66036             return geoVecScale(sum, 1 / points.length);
66037           } else {
66038             return [0, 0];
66039           }
66040         }
66041
66042         function relativeBearing(p1, p2) {
66043           var angle = Math.atan2(p2.lon - p1.lon, p2.lat - p1.lat);
66044
66045           if (angle < 0) {
66046             angle += 2 * Math.PI;
66047           } // Return degrees
66048
66049
66050           return angle * 180 / Math.PI;
66051         } // Assuming range [0,360)
66052
66053
66054         function cardinalDirection(bearing) {
66055           var dir = 45 * Math.round(bearing / 45);
66056           var compass = {
66057             0: 'north',
66058             45: 'northeast',
66059             90: 'east',
66060             135: 'southeast',
66061             180: 'south',
66062             225: 'southwest',
66063             270: 'west',
66064             315: 'northwest',
66065             360: 'north'
66066           };
66067           return _t("QA.improveOSM.directions.".concat(compass[dir]));
66068         } // Errors shouldn't obscure each other
66069
66070
66071         function preventCoincident$1(loc, bumpUp) {
66072           var coincident = false;
66073
66074           do {
66075             // first time, move marker up. after that, move marker right.
66076             var delta = coincident ? [0.00001, 0] : bumpUp ? [0, 0.00001] : [0, 0];
66077             loc = geoVecAdd(loc, delta);
66078             var bbox = geoExtent(loc).bbox();
66079             coincident = _cache$1.rtree.search(bbox).length;
66080           } while (coincident);
66081
66082           return loc;
66083         }
66084
66085         var serviceImproveOSM = {
66086           title: 'improveOSM',
66087           init: function init() {
66088             _mainFileFetcher.get('qa_data').then(function (d) {
66089               return _impOsmData = d.improveOSM;
66090             });
66091
66092             if (!_cache$1) {
66093               this.reset();
66094             }
66095
66096             this.event = utilRebind(this, dispatch$6, 'on');
66097           },
66098           reset: function reset() {
66099             if (_cache$1) {
66100               Object.values(_cache$1.inflightTile).forEach(abortRequest$5);
66101             }
66102
66103             _cache$1 = {
66104               data: {},
66105               loadedTile: {},
66106               inflightTile: {},
66107               inflightPost: {},
66108               closed: {},
66109               rtree: new RBush()
66110             };
66111           },
66112           loadIssues: function loadIssues(projection) {
66113             var _this = this;
66114
66115             var options = {
66116               client: 'iD',
66117               status: 'OPEN',
66118               zoom: '19' // Use a high zoom so that clusters aren't returned
66119
66120             }; // determine the needed tiles to cover the view
66121
66122             var tiles = tiler$5.zoomExtent([_tileZoom$2, _tileZoom$2]).getTiles(projection); // abort inflight requests that are no longer needed
66123
66124             abortUnwantedRequests$2(_cache$1, tiles); // issue new requests..
66125
66126             tiles.forEach(function (tile) {
66127               if (_cache$1.loadedTile[tile.id] || _cache$1.inflightTile[tile.id]) return;
66128
66129               var _tile$extent$rectangl = tile.extent.rectangle(),
66130                   _tile$extent$rectangl2 = _slicedToArray(_tile$extent$rectangl, 4),
66131                   east = _tile$extent$rectangl2[0],
66132                   north = _tile$extent$rectangl2[1],
66133                   west = _tile$extent$rectangl2[2],
66134                   south = _tile$extent$rectangl2[3];
66135
66136               var params = Object.assign({}, options, {
66137                 east: east,
66138                 south: south,
66139                 west: west,
66140                 north: north
66141               }); // 3 separate requests to store for each tile
66142
66143               var requests = {};
66144               Object.keys(_impOsmUrls).forEach(function (k) {
66145                 // We exclude WATER from missing geometry as it doesn't seem useful
66146                 // We use most confident one-way and turn restrictions only, still have false positives
66147                 var kParams = Object.assign({}, params, k === 'mr' ? {
66148                   type: 'PARKING,ROAD,BOTH,PATH'
66149                 } : {
66150                   confidenceLevel: 'C1'
66151                 });
66152                 var url = "".concat(_impOsmUrls[k], "/search?") + utilQsString(kParams);
66153                 var controller = new AbortController();
66154                 requests[k] = controller;
66155                 d3_json(url, {
66156                   signal: controller.signal
66157                 }).then(function (data) {
66158                   delete _cache$1.inflightTile[tile.id][k];
66159
66160                   if (!Object.keys(_cache$1.inflightTile[tile.id]).length) {
66161                     delete _cache$1.inflightTile[tile.id];
66162                     _cache$1.loadedTile[tile.id] = true;
66163                   } // Road segments at high zoom == oneways
66164
66165
66166                   if (data.roadSegments) {
66167                     data.roadSegments.forEach(function (feature) {
66168                       // Position error at the approximate middle of the segment
66169                       var points = feature.points,
66170                           wayId = feature.wayId,
66171                           fromNodeId = feature.fromNodeId,
66172                           toNodeId = feature.toNodeId;
66173                       var itemId = "".concat(wayId).concat(fromNodeId).concat(toNodeId);
66174                       var mid = points.length / 2;
66175                       var loc; // Even number of points, find midpoint of the middle two
66176                       // Odd number of points, use position of very middle point
66177
66178                       if (mid % 1 === 0) {
66179                         loc = pointAverage([points[mid - 1], points[mid]]);
66180                       } else {
66181                         mid = points[Math.floor(mid)];
66182                         loc = [mid.lon, mid.lat];
66183                       } // One-ways can land on same segment in opposite direction
66184
66185
66186                       loc = preventCoincident$1(loc, false);
66187                       var d = new QAItem(loc, _this, k, itemId, {
66188                         issueKey: k,
66189                         // used as a category
66190                         identifier: {
66191                           // used to post changes
66192                           wayId: wayId,
66193                           fromNodeId: fromNodeId,
66194                           toNodeId: toNodeId
66195                         },
66196                         objectId: wayId,
66197                         objectType: 'way'
66198                       }); // Variables used in the description
66199
66200                       d.replacements = {
66201                         percentage: feature.percentOfTrips,
66202                         num_trips: feature.numberOfTrips,
66203                         highway: linkErrorObject(_t('QA.keepRight.error_parts.highway')),
66204                         from_node: linkEntity('n' + feature.fromNodeId),
66205                         to_node: linkEntity('n' + feature.toNodeId)
66206                       };
66207                       _cache$1.data[d.id] = d;
66208
66209                       _cache$1.rtree.insert(encodeIssueRtree$1(d));
66210                     });
66211                   } // Tiles at high zoom == missing roads
66212
66213
66214                   if (data.tiles) {
66215                     data.tiles.forEach(function (feature) {
66216                       var type = feature.type,
66217                           x = feature.x,
66218                           y = feature.y,
66219                           numberOfTrips = feature.numberOfTrips;
66220                       var geoType = type.toLowerCase();
66221                       var itemId = "".concat(geoType).concat(x).concat(y).concat(numberOfTrips); // Average of recorded points should land on the missing geometry
66222                       // Missing geometry could happen to land on another error
66223
66224                       var loc = pointAverage(feature.points);
66225                       loc = preventCoincident$1(loc, false);
66226                       var d = new QAItem(loc, _this, "".concat(k, "-").concat(geoType), itemId, {
66227                         issueKey: k,
66228                         identifier: {
66229                           x: x,
66230                           y: y
66231                         }
66232                       });
66233                       d.replacements = {
66234                         num_trips: numberOfTrips,
66235                         geometry_type: _t("QA.improveOSM.geometry_types.".concat(geoType))
66236                       }; // -1 trips indicates data came from a 3rd party
66237
66238                       if (numberOfTrips === -1) {
66239                         d.desc = _t('QA.improveOSM.error_types.mr.description_alt', d.replacements);
66240                       }
66241
66242                       _cache$1.data[d.id] = d;
66243
66244                       _cache$1.rtree.insert(encodeIssueRtree$1(d));
66245                     });
66246                   } // Entities at high zoom == turn restrictions
66247
66248
66249                   if (data.entities) {
66250                     data.entities.forEach(function (feature) {
66251                       var point = feature.point,
66252                           id = feature.id,
66253                           segments = feature.segments,
66254                           numberOfPasses = feature.numberOfPasses,
66255                           turnType = feature.turnType;
66256                       var itemId = "".concat(id.replace(/[,:+#]/g, '_')); // Turn restrictions could be missing at same junction
66257                       // We also want to bump the error up so node is accessible
66258
66259                       var loc = preventCoincident$1([point.lon, point.lat], true); // Elements are presented in a strange way
66260
66261                       var ids = id.split(',');
66262                       var from_way = ids[0];
66263                       var via_node = ids[3];
66264                       var to_way = ids[2].split(':')[1];
66265                       var d = new QAItem(loc, _this, k, itemId, {
66266                         issueKey: k,
66267                         identifier: id,
66268                         objectId: via_node,
66269                         objectType: 'node'
66270                       }); // Travel direction along from_way clarifies the turn restriction
66271
66272                       var _segments$0$points = _slicedToArray(segments[0].points, 2),
66273                           p1 = _segments$0$points[0],
66274                           p2 = _segments$0$points[1];
66275
66276                       var dir_of_travel = cardinalDirection(relativeBearing(p1, p2)); // Variables used in the description
66277
66278                       d.replacements = {
66279                         num_passed: numberOfPasses,
66280                         num_trips: segments[0].numberOfTrips,
66281                         turn_restriction: turnType.toLowerCase(),
66282                         from_way: linkEntity('w' + from_way),
66283                         to_way: linkEntity('w' + to_way),
66284                         travel_direction: dir_of_travel,
66285                         junction: linkErrorObject(_t('QA.keepRight.error_parts.this_node'))
66286                       };
66287                       _cache$1.data[d.id] = d;
66288
66289                       _cache$1.rtree.insert(encodeIssueRtree$1(d));
66290
66291                       dispatch$6.call('loaded');
66292                     });
66293                   }
66294                 })["catch"](function () {
66295                   delete _cache$1.inflightTile[tile.id][k];
66296
66297                   if (!Object.keys(_cache$1.inflightTile[tile.id]).length) {
66298                     delete _cache$1.inflightTile[tile.id];
66299                     _cache$1.loadedTile[tile.id] = true;
66300                   }
66301                 });
66302               });
66303               _cache$1.inflightTile[tile.id] = requests;
66304             });
66305           },
66306           getComments: function getComments(item) {
66307             var _this2 = this;
66308
66309             // If comments already retrieved no need to do so again
66310             if (item.comments) {
66311               return Promise.resolve(item);
66312             }
66313
66314             var key = item.issueKey;
66315             var qParams = {};
66316
66317             if (key === 'ow') {
66318               qParams = item.identifier;
66319             } else if (key === 'mr') {
66320               qParams.tileX = item.identifier.x;
66321               qParams.tileY = item.identifier.y;
66322             } else if (key === 'tr') {
66323               qParams.targetId = item.identifier;
66324             }
66325
66326             var url = "".concat(_impOsmUrls[key], "/retrieveComments?") + utilQsString(qParams);
66327
66328             var cacheComments = function cacheComments(data) {
66329               // Assign directly for immediate use afterwards
66330               // comments are served newest to oldest
66331               item.comments = data.comments ? data.comments.reverse() : [];
66332
66333               _this2.replaceItem(item);
66334             };
66335
66336             return d3_json(url).then(cacheComments).then(function () {
66337               return item;
66338             });
66339           },
66340           postUpdate: function postUpdate(d, callback) {
66341             if (!serviceOsm.authenticated()) {
66342               // Username required in payload
66343               return callback({
66344                 message: 'Not Authenticated',
66345                 status: -3
66346               }, d);
66347             }
66348
66349             if (_cache$1.inflightPost[d.id]) {
66350               return callback({
66351                 message: 'Error update already inflight',
66352                 status: -2
66353               }, d);
66354             } // Payload can only be sent once username is established
66355
66356
66357             serviceOsm.userDetails(sendPayload.bind(this));
66358
66359             function sendPayload(err, user) {
66360               var _this3 = this;
66361
66362               if (err) {
66363                 return callback(err, d);
66364               }
66365
66366               var key = d.issueKey;
66367               var url = "".concat(_impOsmUrls[key], "/comment");
66368               var payload = {
66369                 username: user.display_name,
66370                 targetIds: [d.identifier]
66371               };
66372
66373               if (d.newStatus) {
66374                 payload.status = d.newStatus;
66375                 payload.text = 'status changed';
66376               } // Comment take place of default text
66377
66378
66379               if (d.newComment) {
66380                 payload.text = d.newComment;
66381               }
66382
66383               var controller = new AbortController();
66384               _cache$1.inflightPost[d.id] = controller;
66385               var options = {
66386                 method: 'POST',
66387                 signal: controller.signal,
66388                 body: JSON.stringify(payload)
66389               };
66390               d3_json(url, options).then(function () {
66391                 delete _cache$1.inflightPost[d.id]; // Just a comment, update error in cache
66392
66393                 if (!d.newStatus) {
66394                   var now = new Date();
66395                   var comments = d.comments ? d.comments : [];
66396                   comments.push({
66397                     username: payload.username,
66398                     text: payload.text,
66399                     timestamp: now.getTime() / 1000
66400                   });
66401
66402                   _this3.replaceItem(d.update({
66403                     comments: comments,
66404                     newComment: undefined
66405                   }));
66406                 } else {
66407                   _this3.removeItem(d);
66408
66409                   if (d.newStatus === 'SOLVED') {
66410                     // Keep track of the number of issues closed per type to tag the changeset
66411                     if (!(d.issueKey in _cache$1.closed)) {
66412                       _cache$1.closed[d.issueKey] = 0;
66413                     }
66414
66415                     _cache$1.closed[d.issueKey] += 1;
66416                   }
66417                 }
66418
66419                 if (callback) callback(null, d);
66420               })["catch"](function (err) {
66421                 delete _cache$1.inflightPost[d.id];
66422                 if (callback) callback(err.message);
66423               });
66424             }
66425           },
66426           // Get all cached QAItems covering the viewport
66427           getItems: function getItems(projection) {
66428             var viewport = projection.clipExtent();
66429             var min = [viewport[0][0], viewport[1][1]];
66430             var max = [viewport[1][0], viewport[0][1]];
66431             var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();
66432             return _cache$1.rtree.search(bbox).map(function (d) {
66433               return d.data;
66434             });
66435           },
66436           // Get a QAItem from cache
66437           // NOTE: Don't change method name until UI v3 is merged
66438           getError: function getError(id) {
66439             return _cache$1.data[id];
66440           },
66441           // get the name of the icon to display for this item
66442           getIcon: function getIcon(itemType) {
66443             return _impOsmData.icons[itemType];
66444           },
66445           // Replace a single QAItem in the cache
66446           replaceItem: function replaceItem(issue) {
66447             if (!(issue instanceof QAItem) || !issue.id) return;
66448             _cache$1.data[issue.id] = issue;
66449             updateRtree$2(encodeIssueRtree$1(issue), true); // true = replace
66450
66451             return issue;
66452           },
66453           // Remove a single QAItem from the cache
66454           removeItem: function removeItem(issue) {
66455             if (!(issue instanceof QAItem) || !issue.id) return;
66456             delete _cache$1.data[issue.id];
66457             updateRtree$2(encodeIssueRtree$1(issue), false); // false = remove
66458           },
66459           // Used to populate `closed:improveosm:*` changeset tags
66460           getClosedCounts: function getClosedCounts() {
66461             return _cache$1.closed;
66462           }
66463         };
66464
66465         var defaults$5 = {exports: {}};
66466
66467         function getDefaults$1() {
66468           return {
66469             baseUrl: null,
66470             breaks: false,
66471             gfm: true,
66472             headerIds: true,
66473             headerPrefix: '',
66474             highlight: null,
66475             langPrefix: 'language-',
66476             mangle: true,
66477             pedantic: false,
66478             renderer: null,
66479             sanitize: false,
66480             sanitizer: null,
66481             silent: false,
66482             smartLists: false,
66483             smartypants: false,
66484             tokenizer: null,
66485             walkTokens: null,
66486             xhtml: false
66487           };
66488         }
66489
66490         function changeDefaults$1(newDefaults) {
66491           defaults$5.exports.defaults = newDefaults;
66492         }
66493
66494         defaults$5.exports = {
66495           defaults: getDefaults$1(),
66496           getDefaults: getDefaults$1,
66497           changeDefaults: changeDefaults$1
66498         };
66499
66500         var escapeTest = /[&<>"']/;
66501         var escapeReplace = /[&<>"']/g;
66502         var escapeTestNoEncode = /[<>"']|&(?!#?\w+;)/;
66503         var escapeReplaceNoEncode = /[<>"']|&(?!#?\w+;)/g;
66504         var escapeReplacements = {
66505           '&': '&amp;',
66506           '<': '&lt;',
66507           '>': '&gt;',
66508           '"': '&quot;',
66509           "'": '&#39;'
66510         };
66511
66512         var getEscapeReplacement = function getEscapeReplacement(ch) {
66513           return escapeReplacements[ch];
66514         };
66515
66516         function escape$3(html, encode) {
66517           if (encode) {
66518             if (escapeTest.test(html)) {
66519               return html.replace(escapeReplace, getEscapeReplacement);
66520             }
66521           } else {
66522             if (escapeTestNoEncode.test(html)) {
66523               return html.replace(escapeReplaceNoEncode, getEscapeReplacement);
66524             }
66525           }
66526
66527           return html;
66528         }
66529
66530         var unescapeTest = /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig;
66531
66532         function unescape$2(html) {
66533           // explicitly match decimal, hex, and named HTML entities
66534           return html.replace(unescapeTest, function (_, n) {
66535             n = n.toLowerCase();
66536             if (n === 'colon') return ':';
66537
66538             if (n.charAt(0) === '#') {
66539               return n.charAt(1) === 'x' ? String.fromCharCode(parseInt(n.substring(2), 16)) : String.fromCharCode(+n.substring(1));
66540             }
66541
66542             return '';
66543           });
66544         }
66545
66546         var caret = /(^|[^\[])\^/g;
66547
66548         function edit$1(regex, opt) {
66549           regex = regex.source || regex;
66550           opt = opt || '';
66551           var obj = {
66552             replace: function replace(name, val) {
66553               val = val.source || val;
66554               val = val.replace(caret, '$1');
66555               regex = regex.replace(name, val);
66556               return obj;
66557             },
66558             getRegex: function getRegex() {
66559               return new RegExp(regex, opt);
66560             }
66561           };
66562           return obj;
66563         }
66564
66565         var nonWordAndColonTest = /[^\w:]/g;
66566         var originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;
66567
66568         function cleanUrl$1(sanitize, base, href) {
66569           if (sanitize) {
66570             var prot;
66571
66572             try {
66573               prot = decodeURIComponent(unescape$2(href)).replace(nonWordAndColonTest, '').toLowerCase();
66574             } catch (e) {
66575               return null;
66576             }
66577
66578             if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) {
66579               return null;
66580             }
66581           }
66582
66583           if (base && !originIndependentUrl.test(href)) {
66584             href = resolveUrl$2(base, href);
66585           }
66586
66587           try {
66588             href = encodeURI(href).replace(/%25/g, '%');
66589           } catch (e) {
66590             return null;
66591           }
66592
66593           return href;
66594         }
66595
66596         var baseUrls = {};
66597         var justDomain = /^[^:]+:\/*[^/]*$/;
66598         var protocol = /^([^:]+:)[\s\S]*$/;
66599         var domain = /^([^:]+:\/*[^/]*)[\s\S]*$/;
66600
66601         function resolveUrl$2(base, href) {
66602           if (!baseUrls[' ' + base]) {
66603             // we can ignore everything in base after the last slash of its path component,
66604             // but we might need to add _that_
66605             // https://tools.ietf.org/html/rfc3986#section-3
66606             if (justDomain.test(base)) {
66607               baseUrls[' ' + base] = base + '/';
66608             } else {
66609               baseUrls[' ' + base] = rtrim$1(base, '/', true);
66610             }
66611           }
66612
66613           base = baseUrls[' ' + base];
66614           var relativeBase = base.indexOf(':') === -1;
66615
66616           if (href.substring(0, 2) === '//') {
66617             if (relativeBase) {
66618               return href;
66619             }
66620
66621             return base.replace(protocol, '$1') + href;
66622           } else if (href.charAt(0) === '/') {
66623             if (relativeBase) {
66624               return href;
66625             }
66626
66627             return base.replace(domain, '$1') + href;
66628           } else {
66629             return base + href;
66630           }
66631         }
66632
66633         var noopTest$1 = {
66634           exec: function noopTest() {}
66635         };
66636
66637         function merge$2(obj) {
66638           var i = 1,
66639               target,
66640               key;
66641
66642           for (; i < arguments.length; i++) {
66643             target = arguments[i];
66644
66645             for (key in target) {
66646               if (Object.prototype.hasOwnProperty.call(target, key)) {
66647                 obj[key] = target[key];
66648               }
66649             }
66650           }
66651
66652           return obj;
66653         }
66654
66655         function splitCells$1(tableRow, count) {
66656           // ensure that every cell-delimiting pipe has a space
66657           // before it to distinguish it from an escaped pipe
66658           var row = tableRow.replace(/\|/g, function (match, offset, str) {
66659             var escaped = false,
66660                 curr = offset;
66661
66662             while (--curr >= 0 && str[curr] === '\\') {
66663               escaped = !escaped;
66664             }
66665
66666             if (escaped) {
66667               // odd number of slashes means | is escaped
66668               // so we leave it alone
66669               return '|';
66670             } else {
66671               // add space before unescaped |
66672               return ' |';
66673             }
66674           }),
66675               cells = row.split(/ \|/);
66676           var i = 0;
66677
66678           if (cells.length > count) {
66679             cells.splice(count);
66680           } else {
66681             while (cells.length < count) {
66682               cells.push('');
66683             }
66684           }
66685
66686           for (; i < cells.length; i++) {
66687             // leading or trailing whitespace is ignored per the gfm spec
66688             cells[i] = cells[i].trim().replace(/\\\|/g, '|');
66689           }
66690
66691           return cells;
66692         } // Remove trailing 'c's. Equivalent to str.replace(/c*$/, '').
66693         // /c*$/ is vulnerable to REDOS.
66694         // invert: Remove suffix of non-c chars instead. Default falsey.
66695
66696
66697         function rtrim$1(str, c, invert) {
66698           var l = str.length;
66699
66700           if (l === 0) {
66701             return '';
66702           } // Length of suffix matching the invert condition.
66703
66704
66705           var suffLen = 0; // Step left until we fail to match the invert condition.
66706
66707           while (suffLen < l) {
66708             var currChar = str.charAt(l - suffLen - 1);
66709
66710             if (currChar === c && !invert) {
66711               suffLen++;
66712             } else if (currChar !== c && invert) {
66713               suffLen++;
66714             } else {
66715               break;
66716             }
66717           }
66718
66719           return str.substr(0, l - suffLen);
66720         }
66721
66722         function findClosingBracket$1(str, b) {
66723           if (str.indexOf(b[1]) === -1) {
66724             return -1;
66725           }
66726
66727           var l = str.length;
66728           var level = 0,
66729               i = 0;
66730
66731           for (; i < l; i++) {
66732             if (str[i] === '\\') {
66733               i++;
66734             } else if (str[i] === b[0]) {
66735               level++;
66736             } else if (str[i] === b[1]) {
66737               level--;
66738
66739               if (level < 0) {
66740                 return i;
66741               }
66742             }
66743           }
66744
66745           return -1;
66746         }
66747
66748         function checkSanitizeDeprecation$1(opt) {
66749           if (opt && opt.sanitize && !opt.silent) {
66750             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');
66751           }
66752         } // copied from https://stackoverflow.com/a/5450113/806777
66753
66754
66755         function repeatString$1(pattern, count) {
66756           if (count < 1) {
66757             return '';
66758           }
66759
66760           var result = '';
66761
66762           while (count > 1) {
66763             if (count & 1) {
66764               result += pattern;
66765             }
66766
66767             count >>= 1;
66768             pattern += pattern;
66769           }
66770
66771           return result + pattern;
66772         }
66773
66774         var helpers = {
66775           escape: escape$3,
66776           unescape: unescape$2,
66777           edit: edit$1,
66778           cleanUrl: cleanUrl$1,
66779           resolveUrl: resolveUrl$2,
66780           noopTest: noopTest$1,
66781           merge: merge$2,
66782           splitCells: splitCells$1,
66783           rtrim: rtrim$1,
66784           findClosingBracket: findClosingBracket$1,
66785           checkSanitizeDeprecation: checkSanitizeDeprecation$1,
66786           repeatString: repeatString$1
66787         };
66788
66789         var defaults$4 = defaults$5.exports.defaults;
66790         var rtrim = helpers.rtrim,
66791             splitCells = helpers.splitCells,
66792             _escape = helpers.escape,
66793             findClosingBracket = helpers.findClosingBracket;
66794
66795         function outputLink(cap, link, raw) {
66796           var href = link.href;
66797           var title = link.title ? _escape(link.title) : null;
66798           var text = cap[1].replace(/\\([\[\]])/g, '$1');
66799
66800           if (cap[0].charAt(0) !== '!') {
66801             return {
66802               type: 'link',
66803               raw: raw,
66804               href: href,
66805               title: title,
66806               text: text
66807             };
66808           } else {
66809             return {
66810               type: 'image',
66811               raw: raw,
66812               href: href,
66813               title: title,
66814               text: _escape(text)
66815             };
66816           }
66817         }
66818
66819         function indentCodeCompensation(raw, text) {
66820           var matchIndentToCode = raw.match(/^(\s+)(?:```)/);
66821
66822           if (matchIndentToCode === null) {
66823             return text;
66824           }
66825
66826           var indentToCode = matchIndentToCode[1];
66827           return text.split('\n').map(function (node) {
66828             var matchIndentInNode = node.match(/^\s+/);
66829
66830             if (matchIndentInNode === null) {
66831               return node;
66832             }
66833
66834             var _matchIndentInNode = _slicedToArray(matchIndentInNode, 1),
66835                 indentInNode = _matchIndentInNode[0];
66836
66837             if (indentInNode.length >= indentToCode.length) {
66838               return node.slice(indentToCode.length);
66839             }
66840
66841             return node;
66842           }).join('\n');
66843         }
66844         /**
66845          * Tokenizer
66846          */
66847
66848
66849         var Tokenizer_1 = /*#__PURE__*/function () {
66850           function Tokenizer(options) {
66851             _classCallCheck$1(this, Tokenizer);
66852
66853             this.options = options || defaults$4;
66854           }
66855
66856           _createClass$1(Tokenizer, [{
66857             key: "space",
66858             value: function space(src) {
66859               var cap = this.rules.block.newline.exec(src);
66860
66861               if (cap) {
66862                 if (cap[0].length > 1) {
66863                   return {
66864                     type: 'space',
66865                     raw: cap[0]
66866                   };
66867                 }
66868
66869                 return {
66870                   raw: '\n'
66871                 };
66872               }
66873             }
66874           }, {
66875             key: "code",
66876             value: function code(src) {
66877               var cap = this.rules.block.code.exec(src);
66878
66879               if (cap) {
66880                 var text = cap[0].replace(/^ {1,4}/gm, '');
66881                 return {
66882                   type: 'code',
66883                   raw: cap[0],
66884                   codeBlockStyle: 'indented',
66885                   text: !this.options.pedantic ? rtrim(text, '\n') : text
66886                 };
66887               }
66888             }
66889           }, {
66890             key: "fences",
66891             value: function fences(src) {
66892               var cap = this.rules.block.fences.exec(src);
66893
66894               if (cap) {
66895                 var raw = cap[0];
66896                 var text = indentCodeCompensation(raw, cap[3] || '');
66897                 return {
66898                   type: 'code',
66899                   raw: raw,
66900                   lang: cap[2] ? cap[2].trim() : cap[2],
66901                   text: text
66902                 };
66903               }
66904             }
66905           }, {
66906             key: "heading",
66907             value: function heading(src) {
66908               var cap = this.rules.block.heading.exec(src);
66909
66910               if (cap) {
66911                 var text = cap[2].trim(); // remove trailing #s
66912
66913                 if (/#$/.test(text)) {
66914                   var trimmed = rtrim(text, '#');
66915
66916                   if (this.options.pedantic) {
66917                     text = trimmed.trim();
66918                   } else if (!trimmed || / $/.test(trimmed)) {
66919                     // CommonMark requires space before trailing #s
66920                     text = trimmed.trim();
66921                   }
66922                 }
66923
66924                 return {
66925                   type: 'heading',
66926                   raw: cap[0],
66927                   depth: cap[1].length,
66928                   text: text
66929                 };
66930               }
66931             }
66932           }, {
66933             key: "nptable",
66934             value: function nptable(src) {
66935               var cap = this.rules.block.nptable.exec(src);
66936
66937               if (cap) {
66938                 var item = {
66939                   type: 'table',
66940                   header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')),
66941                   align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
66942                   cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : [],
66943                   raw: cap[0]
66944                 };
66945
66946                 if (item.header.length === item.align.length) {
66947                   var l = item.align.length;
66948                   var i;
66949
66950                   for (i = 0; i < l; i++) {
66951                     if (/^ *-+: *$/.test(item.align[i])) {
66952                       item.align[i] = 'right';
66953                     } else if (/^ *:-+: *$/.test(item.align[i])) {
66954                       item.align[i] = 'center';
66955                     } else if (/^ *:-+ *$/.test(item.align[i])) {
66956                       item.align[i] = 'left';
66957                     } else {
66958                       item.align[i] = null;
66959                     }
66960                   }
66961
66962                   l = item.cells.length;
66963
66964                   for (i = 0; i < l; i++) {
66965                     item.cells[i] = splitCells(item.cells[i], item.header.length);
66966                   }
66967
66968                   return item;
66969                 }
66970               }
66971             }
66972           }, {
66973             key: "hr",
66974             value: function hr(src) {
66975               var cap = this.rules.block.hr.exec(src);
66976
66977               if (cap) {
66978                 return {
66979                   type: 'hr',
66980                   raw: cap[0]
66981                 };
66982               }
66983             }
66984           }, {
66985             key: "blockquote",
66986             value: function blockquote(src) {
66987               var cap = this.rules.block.blockquote.exec(src);
66988
66989               if (cap) {
66990                 var text = cap[0].replace(/^ *> ?/gm, '');
66991                 return {
66992                   type: 'blockquote',
66993                   raw: cap[0],
66994                   text: text
66995                 };
66996               }
66997             }
66998           }, {
66999             key: "list",
67000             value: function list(src) {
67001               var cap = this.rules.block.list.exec(src);
67002
67003               if (cap) {
67004                 var raw = cap[0];
67005                 var bull = cap[2];
67006                 var isordered = bull.length > 1;
67007                 var list = {
67008                   type: 'list',
67009                   raw: raw,
67010                   ordered: isordered,
67011                   start: isordered ? +bull.slice(0, -1) : '',
67012                   loose: false,
67013                   items: []
67014                 }; // Get each top-level item.
67015
67016                 var itemMatch = cap[0].match(this.rules.block.item);
67017                 var next = false,
67018                     item,
67019                     space,
67020                     bcurr,
67021                     bnext,
67022                     addBack,
67023                     loose,
67024                     istask,
67025                     ischecked,
67026                     endMatch;
67027                 var l = itemMatch.length;
67028                 bcurr = this.rules.block.listItemStart.exec(itemMatch[0]);
67029
67030                 for (var i = 0; i < l; i++) {
67031                   item = itemMatch[i];
67032                   raw = item;
67033
67034                   if (!this.options.pedantic) {
67035                     // Determine if current item contains the end of the list
67036                     endMatch = item.match(new RegExp('\\n\\s*\\n {0,' + (bcurr[0].length - 1) + '}\\S'));
67037
67038                     if (endMatch) {
67039                       addBack = item.length - endMatch.index + itemMatch.slice(i + 1).join('\n').length;
67040                       list.raw = list.raw.substring(0, list.raw.length - addBack);
67041                       item = item.substring(0, endMatch.index);
67042                       raw = item;
67043                       l = i + 1;
67044                     }
67045                   } // Determine whether the next list item belongs here.
67046                   // Backpedal if it does not belong in this list.
67047
67048
67049                   if (i !== l - 1) {
67050                     bnext = this.rules.block.listItemStart.exec(itemMatch[i + 1]);
67051
67052                     if (!this.options.pedantic ? bnext[1].length >= bcurr[0].length || bnext[1].length > 3 : bnext[1].length > bcurr[1].length) {
67053                       // nested list or continuation
67054                       itemMatch.splice(i, 2, itemMatch[i] + (!this.options.pedantic && bnext[1].length < bcurr[0].length && !itemMatch[i].match(/\n$/) ? '' : '\n') + itemMatch[i + 1]);
67055                       i--;
67056                       l--;
67057                       continue;
67058                     } else if ( // different bullet style
67059                     !this.options.pedantic || this.options.smartLists ? bnext[2][bnext[2].length - 1] !== bull[bull.length - 1] : isordered === (bnext[2].length === 1)) {
67060                       addBack = itemMatch.slice(i + 1).join('\n').length;
67061                       list.raw = list.raw.substring(0, list.raw.length - addBack);
67062                       i = l - 1;
67063                     }
67064
67065                     bcurr = bnext;
67066                   } // Remove the list item's bullet
67067                   // so it is seen as the next token.
67068
67069
67070                   space = item.length;
67071                   item = item.replace(/^ *([*+-]|\d+[.)]) ?/, ''); // Outdent whatever the
67072                   // list item contains. Hacky.
67073
67074                   if (~item.indexOf('\n ')) {
67075                     space -= item.length;
67076                     item = !this.options.pedantic ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '') : item.replace(/^ {1,4}/gm, '');
67077                   } // trim item newlines at end
67078
67079
67080                   item = rtrim(item, '\n');
67081
67082                   if (i !== l - 1) {
67083                     raw = raw + '\n';
67084                   } // Determine whether item is loose or not.
67085                   // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
67086                   // for discount behavior.
67087
67088
67089                   loose = next || /\n\n(?!\s*$)/.test(raw);
67090
67091                   if (i !== l - 1) {
67092                     next = raw.slice(-2) === '\n\n';
67093                     if (!loose) loose = next;
67094                   }
67095
67096                   if (loose) {
67097                     list.loose = true;
67098                   } // Check for task list items
67099
67100
67101                   if (this.options.gfm) {
67102                     istask = /^\[[ xX]\] /.test(item);
67103                     ischecked = undefined;
67104
67105                     if (istask) {
67106                       ischecked = item[1] !== ' ';
67107                       item = item.replace(/^\[[ xX]\] +/, '');
67108                     }
67109                   }
67110
67111                   list.items.push({
67112                     type: 'list_item',
67113                     raw: raw,
67114                     task: istask,
67115                     checked: ischecked,
67116                     loose: loose,
67117                     text: item
67118                   });
67119                 }
67120
67121                 return list;
67122               }
67123             }
67124           }, {
67125             key: "html",
67126             value: function html(src) {
67127               var cap = this.rules.block.html.exec(src);
67128
67129               if (cap) {
67130                 return {
67131                   type: this.options.sanitize ? 'paragraph' : 'html',
67132                   raw: cap[0],
67133                   pre: !this.options.sanitizer && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
67134                   text: this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : _escape(cap[0]) : cap[0]
67135                 };
67136               }
67137             }
67138           }, {
67139             key: "def",
67140             value: function def(src) {
67141               var cap = this.rules.block.def.exec(src);
67142
67143               if (cap) {
67144                 if (cap[3]) cap[3] = cap[3].substring(1, cap[3].length - 1);
67145                 var tag = cap[1].toLowerCase().replace(/\s+/g, ' ');
67146                 return {
67147                   type: 'def',
67148                   tag: tag,
67149                   raw: cap[0],
67150                   href: cap[2],
67151                   title: cap[3]
67152                 };
67153               }
67154             }
67155           }, {
67156             key: "table",
67157             value: function table(src) {
67158               var cap = this.rules.block.table.exec(src);
67159
67160               if (cap) {
67161                 var item = {
67162                   type: 'table',
67163                   header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')),
67164                   align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
67165                   cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : []
67166                 };
67167
67168                 if (item.header.length === item.align.length) {
67169                   item.raw = cap[0];
67170                   var l = item.align.length;
67171                   var i;
67172
67173                   for (i = 0; i < l; i++) {
67174                     if (/^ *-+: *$/.test(item.align[i])) {
67175                       item.align[i] = 'right';
67176                     } else if (/^ *:-+: *$/.test(item.align[i])) {
67177                       item.align[i] = 'center';
67178                     } else if (/^ *:-+ *$/.test(item.align[i])) {
67179                       item.align[i] = 'left';
67180                     } else {
67181                       item.align[i] = null;
67182                     }
67183                   }
67184
67185                   l = item.cells.length;
67186
67187                   for (i = 0; i < l; i++) {
67188                     item.cells[i] = splitCells(item.cells[i].replace(/^ *\| *| *\| *$/g, ''), item.header.length);
67189                   }
67190
67191                   return item;
67192                 }
67193               }
67194             }
67195           }, {
67196             key: "lheading",
67197             value: function lheading(src) {
67198               var cap = this.rules.block.lheading.exec(src);
67199
67200               if (cap) {
67201                 return {
67202                   type: 'heading',
67203                   raw: cap[0],
67204                   depth: cap[2].charAt(0) === '=' ? 1 : 2,
67205                   text: cap[1]
67206                 };
67207               }
67208             }
67209           }, {
67210             key: "paragraph",
67211             value: function paragraph(src) {
67212               var cap = this.rules.block.paragraph.exec(src);
67213
67214               if (cap) {
67215                 return {
67216                   type: 'paragraph',
67217                   raw: cap[0],
67218                   text: cap[1].charAt(cap[1].length - 1) === '\n' ? cap[1].slice(0, -1) : cap[1]
67219                 };
67220               }
67221             }
67222           }, {
67223             key: "text",
67224             value: function text(src) {
67225               var cap = this.rules.block.text.exec(src);
67226
67227               if (cap) {
67228                 return {
67229                   type: 'text',
67230                   raw: cap[0],
67231                   text: cap[0]
67232                 };
67233               }
67234             }
67235           }, {
67236             key: "escape",
67237             value: function escape(src) {
67238               var cap = this.rules.inline.escape.exec(src);
67239
67240               if (cap) {
67241                 return {
67242                   type: 'escape',
67243                   raw: cap[0],
67244                   text: _escape(cap[1])
67245                 };
67246               }
67247             }
67248           }, {
67249             key: "tag",
67250             value: function tag(src, inLink, inRawBlock) {
67251               var cap = this.rules.inline.tag.exec(src);
67252
67253               if (cap) {
67254                 if (!inLink && /^<a /i.test(cap[0])) {
67255                   inLink = true;
67256                 } else if (inLink && /^<\/a>/i.test(cap[0])) {
67257                   inLink = false;
67258                 }
67259
67260                 if (!inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
67261                   inRawBlock = true;
67262                 } else if (inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
67263                   inRawBlock = false;
67264                 }
67265
67266                 return {
67267                   type: this.options.sanitize ? 'text' : 'html',
67268                   raw: cap[0],
67269                   inLink: inLink,
67270                   inRawBlock: inRawBlock,
67271                   text: this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : _escape(cap[0]) : cap[0]
67272                 };
67273               }
67274             }
67275           }, {
67276             key: "link",
67277             value: function link(src) {
67278               var cap = this.rules.inline.link.exec(src);
67279
67280               if (cap) {
67281                 var trimmedUrl = cap[2].trim();
67282
67283                 if (!this.options.pedantic && /^</.test(trimmedUrl)) {
67284                   // commonmark requires matching angle brackets
67285                   if (!/>$/.test(trimmedUrl)) {
67286                     return;
67287                   } // ending angle bracket cannot be escaped
67288
67289
67290                   var rtrimSlash = rtrim(trimmedUrl.slice(0, -1), '\\');
67291
67292                   if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) {
67293                     return;
67294                   }
67295                 } else {
67296                   // find closing parenthesis
67297                   var lastParenIndex = findClosingBracket(cap[2], '()');
67298
67299                   if (lastParenIndex > -1) {
67300                     var start = cap[0].indexOf('!') === 0 ? 5 : 4;
67301                     var linkLen = start + cap[1].length + lastParenIndex;
67302                     cap[2] = cap[2].substring(0, lastParenIndex);
67303                     cap[0] = cap[0].substring(0, linkLen).trim();
67304                     cap[3] = '';
67305                   }
67306                 }
67307
67308                 var href = cap[2];
67309                 var title = '';
67310
67311                 if (this.options.pedantic) {
67312                   // split pedantic href and title
67313                   var link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href);
67314
67315                   if (link) {
67316                     href = link[1];
67317                     title = link[3];
67318                   }
67319                 } else {
67320                   title = cap[3] ? cap[3].slice(1, -1) : '';
67321                 }
67322
67323                 href = href.trim();
67324
67325                 if (/^</.test(href)) {
67326                   if (this.options.pedantic && !/>$/.test(trimmedUrl)) {
67327                     // pedantic allows starting angle bracket without ending angle bracket
67328                     href = href.slice(1);
67329                   } else {
67330                     href = href.slice(1, -1);
67331                   }
67332                 }
67333
67334                 return outputLink(cap, {
67335                   href: href ? href.replace(this.rules.inline._escapes, '$1') : href,
67336                   title: title ? title.replace(this.rules.inline._escapes, '$1') : title
67337                 }, cap[0]);
67338               }
67339             }
67340           }, {
67341             key: "reflink",
67342             value: function reflink(src, links) {
67343               var cap;
67344
67345               if ((cap = this.rules.inline.reflink.exec(src)) || (cap = this.rules.inline.nolink.exec(src))) {
67346                 var link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
67347                 link = links[link.toLowerCase()];
67348
67349                 if (!link || !link.href) {
67350                   var text = cap[0].charAt(0);
67351                   return {
67352                     type: 'text',
67353                     raw: text,
67354                     text: text
67355                   };
67356                 }
67357
67358                 return outputLink(cap, link, cap[0]);
67359               }
67360             }
67361           }, {
67362             key: "emStrong",
67363             value: function emStrong(src, maskedSrc) {
67364               var prevChar = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
67365               var match = this.rules.inline.emStrong.lDelim.exec(src);
67366               if (!match) return; // _ can't be between two alphanumerics. \p{L}\p{N} includes non-english alphabet/numbers as well
67367
67368               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;
67369               var nextChar = match[1] || match[2] || '';
67370
67371               if (!nextChar || nextChar && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar))) {
67372                 var lLength = match[0].length - 1;
67373                 var rDelim,
67374                     rLength,
67375                     delimTotal = lLength,
67376                     midDelimTotal = 0;
67377                 var endReg = match[0][0] === '*' ? this.rules.inline.emStrong.rDelimAst : this.rules.inline.emStrong.rDelimUnd;
67378                 endReg.lastIndex = 0; // Clip maskedSrc to same section of string as src (move to lexer?)
67379
67380                 maskedSrc = maskedSrc.slice(-1 * src.length + lLength);
67381
67382                 while ((match = endReg.exec(maskedSrc)) != null) {
67383                   rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6];
67384                   if (!rDelim) continue; // skip single * in __abc*abc__
67385
67386                   rLength = rDelim.length;
67387
67388                   if (match[3] || match[4]) {
67389                     // found another Left Delim
67390                     delimTotal += rLength;
67391                     continue;
67392                   } else if (match[5] || match[6]) {
67393                     // either Left or Right Delim
67394                     if (lLength % 3 && !((lLength + rLength) % 3)) {
67395                       midDelimTotal += rLength;
67396                       continue; // CommonMark Emphasis Rules 9-10
67397                     }
67398                   }
67399
67400                   delimTotal -= rLength;
67401                   if (delimTotal > 0) continue; // Haven't found enough closing delimiters
67402                   // Remove extra characters. *a*** -> *a*
67403
67404                   rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal); // Create `em` if smallest delimiter has odd char count. *a***
67405
67406                   if (Math.min(lLength, rLength) % 2) {
67407                     return {
67408                       type: 'em',
67409                       raw: src.slice(0, lLength + match.index + rLength + 1),
67410                       text: src.slice(1, lLength + match.index + rLength)
67411                     };
67412                   } // Create 'strong' if smallest delimiter has even char count. **a***
67413
67414
67415                   return {
67416                     type: 'strong',
67417                     raw: src.slice(0, lLength + match.index + rLength + 1),
67418                     text: src.slice(2, lLength + match.index + rLength - 1)
67419                   };
67420                 }
67421               }
67422             }
67423           }, {
67424             key: "codespan",
67425             value: function codespan(src) {
67426               var cap = this.rules.inline.code.exec(src);
67427
67428               if (cap) {
67429                 var text = cap[2].replace(/\n/g, ' ');
67430                 var hasNonSpaceChars = /[^ ]/.test(text);
67431                 var hasSpaceCharsOnBothEnds = /^ /.test(text) && / $/.test(text);
67432
67433                 if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {
67434                   text = text.substring(1, text.length - 1);
67435                 }
67436
67437                 text = _escape(text, true);
67438                 return {
67439                   type: 'codespan',
67440                   raw: cap[0],
67441                   text: text
67442                 };
67443               }
67444             }
67445           }, {
67446             key: "br",
67447             value: function br(src) {
67448               var cap = this.rules.inline.br.exec(src);
67449
67450               if (cap) {
67451                 return {
67452                   type: 'br',
67453                   raw: cap[0]
67454                 };
67455               }
67456             }
67457           }, {
67458             key: "del",
67459             value: function del(src) {
67460               var cap = this.rules.inline.del.exec(src);
67461
67462               if (cap) {
67463                 return {
67464                   type: 'del',
67465                   raw: cap[0],
67466                   text: cap[2]
67467                 };
67468               }
67469             }
67470           }, {
67471             key: "autolink",
67472             value: function autolink(src, mangle) {
67473               var cap = this.rules.inline.autolink.exec(src);
67474
67475               if (cap) {
67476                 var text, href;
67477
67478                 if (cap[2] === '@') {
67479                   text = _escape(this.options.mangle ? mangle(cap[1]) : cap[1]);
67480                   href = 'mailto:' + text;
67481                 } else {
67482                   text = _escape(cap[1]);
67483                   href = text;
67484                 }
67485
67486                 return {
67487                   type: 'link',
67488                   raw: cap[0],
67489                   text: text,
67490                   href: href,
67491                   tokens: [{
67492                     type: 'text',
67493                     raw: text,
67494                     text: text
67495                   }]
67496                 };
67497               }
67498             }
67499           }, {
67500             key: "url",
67501             value: function url(src, mangle) {
67502               var cap;
67503
67504               if (cap = this.rules.inline.url.exec(src)) {
67505                 var text, href;
67506
67507                 if (cap[2] === '@') {
67508                   text = _escape(this.options.mangle ? mangle(cap[0]) : cap[0]);
67509                   href = 'mailto:' + text;
67510                 } else {
67511                   // do extended autolink path validation
67512                   var prevCapZero;
67513
67514                   do {
67515                     prevCapZero = cap[0];
67516                     cap[0] = this.rules.inline._backpedal.exec(cap[0])[0];
67517                   } while (prevCapZero !== cap[0]);
67518
67519                   text = _escape(cap[0]);
67520
67521                   if (cap[1] === 'www.') {
67522                     href = 'http://' + text;
67523                   } else {
67524                     href = text;
67525                   }
67526                 }
67527
67528                 return {
67529                   type: 'link',
67530                   raw: cap[0],
67531                   text: text,
67532                   href: href,
67533                   tokens: [{
67534                     type: 'text',
67535                     raw: text,
67536                     text: text
67537                   }]
67538                 };
67539               }
67540             }
67541           }, {
67542             key: "inlineText",
67543             value: function inlineText(src, inRawBlock, smartypants) {
67544               var cap = this.rules.inline.text.exec(src);
67545
67546               if (cap) {
67547                 var text;
67548
67549                 if (inRawBlock) {
67550                   text = this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : _escape(cap[0]) : cap[0];
67551                 } else {
67552                   text = _escape(this.options.smartypants ? smartypants(cap[0]) : cap[0]);
67553                 }
67554
67555                 return {
67556                   type: 'text',
67557                   raw: cap[0],
67558                   text: text
67559                 };
67560               }
67561             }
67562           }]);
67563
67564           return Tokenizer;
67565         }();
67566
67567         var noopTest = helpers.noopTest,
67568             edit = helpers.edit,
67569             merge$1 = helpers.merge;
67570         /**
67571          * Block-Level Grammar
67572          */
67573
67574         var block$1 = {
67575           newline: /^(?: *(?:\n|$))+/,
67576           code: /^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,
67577           fences: /^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/,
67578           hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,
67579           heading: /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,
67580           blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,
67581           list: /^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?! {0,3}bull )\n*|\s*$)/,
67582           html: '^ {0,3}(?:' // optional indentation
67583           + '<(script|pre|style)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)' // (1)
67584           + '|comment[^\\n]*(\\n+|$)' // (2)
67585           + '|<\\?[\\s\\S]*?(?:\\?>\\n*|$)' // (3)
67586           + '|<![A-Z][\\s\\S]*?(?:>\\n*|$)' // (4)
67587           + '|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)' // (5)
67588           + '|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (6)
67589           + '|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (7) open tag
67590           + '|</(?!script|pre|style)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (7) closing tag
67591           + ')',
67592           def: /^ {0,3}\[(label)\]: *\n? *<?([^\s>]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,
67593           nptable: noopTest,
67594           table: noopTest,
67595           lheading: /^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,
67596           // regex template, placeholders will be replaced according to different paragraph
67597           // interruption rules of commonmark and the original markdown spec:
67598           _paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html| +\n)[^\n]+)*)/,
67599           text: /^[^\n]+/
67600         };
67601         block$1._label = /(?!\s*\])(?:\\[\[\]]|[^\[\]])+/;
67602         block$1._title = /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/;
67603         block$1.def = edit(block$1.def).replace('label', block$1._label).replace('title', block$1._title).getRegex();
67604         block$1.bullet = /(?:[*+-]|\d{1,9}[.)])/;
67605         block$1.item = /^( *)(bull) ?[^\n]*(?:\n(?! *bull ?)[^\n]*)*/;
67606         block$1.item = edit(block$1.item, 'gm').replace(/bull/g, block$1.bullet).getRegex();
67607         block$1.listItemStart = edit(/^( *)(bull) */).replace('bull', block$1.bullet).getRegex();
67608         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();
67609         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';
67610         block$1._comment = /<!--(?!-?>)[\s\S]*?(?:-->|$)/;
67611         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();
67612         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
67613         .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
67614         .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)').replace('tag', block$1._tag) // pars can be interrupted by type (6) html blocks
67615         .getRegex();
67616         block$1.blockquote = edit(block$1.blockquote).replace('paragraph', block$1.paragraph).getRegex();
67617         /**
67618          * Normal Block Grammar
67619          */
67620
67621         block$1.normal = merge$1({}, block$1);
67622         /**
67623          * GFM Block Grammar
67624          */
67625
67626         block$1.gfm = merge$1({}, block$1.normal, {
67627           nptable: '^ *([^|\\n ].*\\|.*)\\n' // Header
67628           + ' {0,3}([-:]+ *\\|[-| :]*)' // Align
67629           + '(?:\\n((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)',
67630           // Cells
67631           table: '^ *\\|(.+)\\n' // Header
67632           + ' {0,3}\\|?( *[-:]+[-| :]*)' // Align
67633           + '(?:\\n *((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)' // Cells
67634
67635         });
67636         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
67637         .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)').replace('tag', block$1._tag) // tables can be interrupted by type (6) html blocks
67638         .getRegex();
67639         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
67640         .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)').replace('tag', block$1._tag) // tables can be interrupted by type (6) html blocks
67641         .getRegex();
67642         /**
67643          * Pedantic grammar (original John Gruber's loose markdown specification)
67644          */
67645
67646         block$1.pedantic = merge$1({}, block$1.normal, {
67647           html: edit('^ *(?:comment *(?:\\n|\\s*$)' + '|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)' // closed tag
67648           + '|<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(),
67649           def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,
67650           heading: /^(#{1,6})(.*)(?:\n+|$)/,
67651           fences: noopTest,
67652           // fences not supported
67653           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()
67654         });
67655         /**
67656          * Inline-Level Grammar
67657          */
67658
67659         var inline$1 = {
67660           escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,
67661           autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/,
67662           url: noopTest,
67663           tag: '^comment' + '|^</[a-zA-Z][\\w:-]*\\s*>' // self-closing tag
67664           + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag
67665           + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. <?php ?>
67666           + '|^<![a-zA-Z]+\\s[\\s\\S]*?>' // declaration, e.g. <!DOCTYPE html>
67667           + '|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>',
67668           // CDATA section
67669           link: /^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,
67670           reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,
67671           nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,
67672           reflinkSearch: 'reflink|nolink(?!\\()',
67673           emStrong: {
67674             lDelim: /^(?:\*+(?:([punct_])|[^\s*]))|^_+(?:([punct*])|([^\s_]))/,
67675             //        (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.
67676             //        () Skip other delimiter (1) #***                   (2) a***#, a***                   (3) #***a, ***a                 (4) ***#              (5) #***#                 (6) a***a
67677             rDelimAst: /\_\_[^_*]*?\*[^_*]*?\_\_|[punct_](\*+)(?=[\s]|$)|[^punct*_\s](\*+)(?=[punct_\s]|$)|[punct_\s](\*+)(?=[^punct*_\s])|[\s](\*+)(?=[punct_])|[punct_](\*+)(?=[punct_])|[^punct*_\s](\*+)(?=[^punct*_\s])/,
67678             rDelimUnd: /\*\*[^_*]*?\_[^_*]*?\*\*|[punct*](\_+)(?=[\s]|$)|[^punct*_\s](\_+)(?=[punct*\s]|$)|[punct*\s](\_+)(?=[^punct*_\s])|[\s](\_+)(?=[punct*])|[punct*](\_+)(?=[punct*])/ // ^- Not allowed for _
67679
67680           },
67681           code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,
67682           br: /^( {2,}|\\)\n(?!\s*$)/,
67683           del: noopTest,
67684           text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,
67685           punctuation: /^([\spunctuation])/
67686         }; // list of punctuation marks from CommonMark spec
67687         // without * and _ to handle the different emphasis markers * and _
67688
67689         inline$1._punctuation = '!"#$%&\'()+\\-.,/:;<=>?@\\[\\]`^{|}~';
67690         inline$1.punctuation = edit(inline$1.punctuation).replace(/punctuation/g, inline$1._punctuation).getRegex(); // sequences em should skip over [title](link), `code`, <html>
67691
67692         inline$1.blockSkip = /\[[^\]]*?\]\([^\)]*?\)|`[^`]*?`|<[^>]*?>/g;
67693         inline$1.escapedEmSt = /\\\*|\\_/g;
67694         inline$1._comment = edit(block$1._comment).replace('(?:-->|$)', '-->').getRegex();
67695         inline$1.emStrong.lDelim = edit(inline$1.emStrong.lDelim).replace(/punct/g, inline$1._punctuation).getRegex();
67696         inline$1.emStrong.rDelimAst = edit(inline$1.emStrong.rDelimAst, 'g').replace(/punct/g, inline$1._punctuation).getRegex();
67697         inline$1.emStrong.rDelimUnd = edit(inline$1.emStrong.rDelimUnd, 'g').replace(/punct/g, inline$1._punctuation).getRegex();
67698         inline$1._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;
67699         inline$1._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/;
67700         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])?)+(?![-_])/;
67701         inline$1.autolink = edit(inline$1.autolink).replace('scheme', inline$1._scheme).replace('email', inline$1._email).getRegex();
67702         inline$1._attribute = /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/;
67703         inline$1.tag = edit(inline$1.tag).replace('comment', inline$1._comment).replace('attribute', inline$1._attribute).getRegex();
67704         inline$1._label = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
67705         inline$1._href = /<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/;
67706         inline$1._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/;
67707         inline$1.link = edit(inline$1.link).replace('label', inline$1._label).replace('href', inline$1._href).replace('title', inline$1._title).getRegex();
67708         inline$1.reflink = edit(inline$1.reflink).replace('label', inline$1._label).getRegex();
67709         inline$1.reflinkSearch = edit(inline$1.reflinkSearch, 'g').replace('reflink', inline$1.reflink).replace('nolink', inline$1.nolink).getRegex();
67710         /**
67711          * Normal Inline Grammar
67712          */
67713
67714         inline$1.normal = merge$1({}, inline$1);
67715         /**
67716          * Pedantic Inline Grammar
67717          */
67718
67719         inline$1.pedantic = merge$1({}, inline$1.normal, {
67720           strong: {
67721             start: /^__|\*\*/,
67722             middle: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
67723             endAst: /\*\*(?!\*)/g,
67724             endUnd: /__(?!_)/g
67725           },
67726           em: {
67727             start: /^_|\*/,
67728             middle: /^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/,
67729             endAst: /\*(?!\*)/g,
67730             endUnd: /_(?!_)/g
67731           },
67732           link: edit(/^!?\[(label)\]\((.*?)\)/).replace('label', inline$1._label).getRegex(),
67733           reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace('label', inline$1._label).getRegex()
67734         });
67735         /**
67736          * GFM Inline Grammar
67737          */
67738
67739         inline$1.gfm = merge$1({}, inline$1.normal, {
67740           escape: edit(inline$1.escape).replace('])', '~|])').getRegex(),
67741           _extended_email: /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,
67742           url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,
67743           _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,
67744           del: /^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/,
67745           text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/
67746         });
67747         inline$1.gfm.url = edit(inline$1.gfm.url, 'i').replace('email', inline$1.gfm._extended_email).getRegex();
67748         /**
67749          * GFM + Line Breaks Inline Grammar
67750          */
67751
67752         inline$1.breaks = merge$1({}, inline$1.gfm, {
67753           br: edit(inline$1.br).replace('{2,}', '*').getRegex(),
67754           text: edit(inline$1.gfm.text).replace('\\b_', '\\b_| {2,}\\n').replace(/\{2,\}/g, '*').getRegex()
67755         });
67756         var rules = {
67757           block: block$1,
67758           inline: inline$1
67759         };
67760
67761         var Tokenizer$1 = Tokenizer_1;
67762         var defaults$3 = defaults$5.exports.defaults;
67763         var block = rules.block,
67764             inline = rules.inline;
67765         var repeatString = helpers.repeatString;
67766         /**
67767          * smartypants text replacement
67768          */
67769
67770         function smartypants(text) {
67771           return text // em-dashes
67772           .replace(/---/g, "\u2014") // en-dashes
67773           .replace(/--/g, "\u2013") // opening singles
67774           .replace(/(^|[-\u2014/(\[{"\s])'/g, "$1\u2018") // closing singles & apostrophes
67775           .replace(/'/g, "\u2019") // opening doubles
67776           .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, "$1\u201C") // closing doubles
67777           .replace(/"/g, "\u201D") // ellipses
67778           .replace(/\.{3}/g, "\u2026");
67779         }
67780         /**
67781          * mangle email addresses
67782          */
67783
67784
67785         function mangle(text) {
67786           var out = '',
67787               i,
67788               ch;
67789           var l = text.length;
67790
67791           for (i = 0; i < l; i++) {
67792             ch = text.charCodeAt(i);
67793
67794             if (Math.random() > 0.5) {
67795               ch = 'x' + ch.toString(16);
67796             }
67797
67798             out += '&#' + ch + ';';
67799           }
67800
67801           return out;
67802         }
67803         /**
67804          * Block Lexer
67805          */
67806
67807
67808         var Lexer_1 = /*#__PURE__*/function () {
67809           function Lexer(options) {
67810             _classCallCheck$1(this, Lexer);
67811
67812             this.tokens = [];
67813             this.tokens.links = Object.create(null);
67814             this.options = options || defaults$3;
67815             this.options.tokenizer = this.options.tokenizer || new Tokenizer$1();
67816             this.tokenizer = this.options.tokenizer;
67817             this.tokenizer.options = this.options;
67818             var rules = {
67819               block: block.normal,
67820               inline: inline.normal
67821             };
67822
67823             if (this.options.pedantic) {
67824               rules.block = block.pedantic;
67825               rules.inline = inline.pedantic;
67826             } else if (this.options.gfm) {
67827               rules.block = block.gfm;
67828
67829               if (this.options.breaks) {
67830                 rules.inline = inline.breaks;
67831               } else {
67832                 rules.inline = inline.gfm;
67833               }
67834             }
67835
67836             this.tokenizer.rules = rules;
67837           }
67838           /**
67839            * Expose Rules
67840            */
67841
67842
67843           _createClass$1(Lexer, [{
67844             key: "lex",
67845             value:
67846             /**
67847              * Preprocessing
67848              */
67849             function lex(src) {
67850               src = src.replace(/\r\n|\r/g, '\n').replace(/\t/g, '    ');
67851               this.blockTokens(src, this.tokens, true);
67852               this.inline(this.tokens);
67853               return this.tokens;
67854             }
67855             /**
67856              * Lexing
67857              */
67858
67859           }, {
67860             key: "blockTokens",
67861             value: function blockTokens(src) {
67862               var tokens = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
67863               var top = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
67864
67865               if (this.options.pedantic) {
67866                 src = src.replace(/^ +$/gm, '');
67867               }
67868
67869               var token, i, l, lastToken;
67870
67871               while (src) {
67872                 // newline
67873                 if (token = this.tokenizer.space(src)) {
67874                   src = src.substring(token.raw.length);
67875
67876                   if (token.type) {
67877                     tokens.push(token);
67878                   }
67879
67880                   continue;
67881                 } // code
67882
67883
67884                 if (token = this.tokenizer.code(src)) {
67885                   src = src.substring(token.raw.length);
67886                   lastToken = tokens[tokens.length - 1]; // An indented code block cannot interrupt a paragraph.
67887
67888                   if (lastToken && lastToken.type === 'paragraph') {
67889                     lastToken.raw += '\n' + token.raw;
67890                     lastToken.text += '\n' + token.text;
67891                   } else {
67892                     tokens.push(token);
67893                   }
67894
67895                   continue;
67896                 } // fences
67897
67898
67899                 if (token = this.tokenizer.fences(src)) {
67900                   src = src.substring(token.raw.length);
67901                   tokens.push(token);
67902                   continue;
67903                 } // heading
67904
67905
67906                 if (token = this.tokenizer.heading(src)) {
67907                   src = src.substring(token.raw.length);
67908                   tokens.push(token);
67909                   continue;
67910                 } // table no leading pipe (gfm)
67911
67912
67913                 if (token = this.tokenizer.nptable(src)) {
67914                   src = src.substring(token.raw.length);
67915                   tokens.push(token);
67916                   continue;
67917                 } // hr
67918
67919
67920                 if (token = this.tokenizer.hr(src)) {
67921                   src = src.substring(token.raw.length);
67922                   tokens.push(token);
67923                   continue;
67924                 } // blockquote
67925
67926
67927                 if (token = this.tokenizer.blockquote(src)) {
67928                   src = src.substring(token.raw.length);
67929                   token.tokens = this.blockTokens(token.text, [], top);
67930                   tokens.push(token);
67931                   continue;
67932                 } // list
67933
67934
67935                 if (token = this.tokenizer.list(src)) {
67936                   src = src.substring(token.raw.length);
67937                   l = token.items.length;
67938
67939                   for (i = 0; i < l; i++) {
67940                     token.items[i].tokens = this.blockTokens(token.items[i].text, [], false);
67941                   }
67942
67943                   tokens.push(token);
67944                   continue;
67945                 } // html
67946
67947
67948                 if (token = this.tokenizer.html(src)) {
67949                   src = src.substring(token.raw.length);
67950                   tokens.push(token);
67951                   continue;
67952                 } // def
67953
67954
67955                 if (top && (token = this.tokenizer.def(src))) {
67956                   src = src.substring(token.raw.length);
67957
67958                   if (!this.tokens.links[token.tag]) {
67959                     this.tokens.links[token.tag] = {
67960                       href: token.href,
67961                       title: token.title
67962                     };
67963                   }
67964
67965                   continue;
67966                 } // table (gfm)
67967
67968
67969                 if (token = this.tokenizer.table(src)) {
67970                   src = src.substring(token.raw.length);
67971                   tokens.push(token);
67972                   continue;
67973                 } // lheading
67974
67975
67976                 if (token = this.tokenizer.lheading(src)) {
67977                   src = src.substring(token.raw.length);
67978                   tokens.push(token);
67979                   continue;
67980                 } // top-level paragraph
67981
67982
67983                 if (top && (token = this.tokenizer.paragraph(src))) {
67984                   src = src.substring(token.raw.length);
67985                   tokens.push(token);
67986                   continue;
67987                 } // text
67988
67989
67990                 if (token = this.tokenizer.text(src)) {
67991                   src = src.substring(token.raw.length);
67992                   lastToken = tokens[tokens.length - 1];
67993
67994                   if (lastToken && lastToken.type === 'text') {
67995                     lastToken.raw += '\n' + token.raw;
67996                     lastToken.text += '\n' + token.text;
67997                   } else {
67998                     tokens.push(token);
67999                   }
68000
68001                   continue;
68002                 }
68003
68004                 if (src) {
68005                   var errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
68006
68007                   if (this.options.silent) {
68008                     console.error(errMsg);
68009                     break;
68010                   } else {
68011                     throw new Error(errMsg);
68012                   }
68013                 }
68014               }
68015
68016               return tokens;
68017             }
68018           }, {
68019             key: "inline",
68020             value: function inline(tokens) {
68021               var i, j, k, l2, row, token;
68022               var l = tokens.length;
68023
68024               for (i = 0; i < l; i++) {
68025                 token = tokens[i];
68026
68027                 switch (token.type) {
68028                   case 'paragraph':
68029                   case 'text':
68030                   case 'heading':
68031                     {
68032                       token.tokens = [];
68033                       this.inlineTokens(token.text, token.tokens);
68034                       break;
68035                     }
68036
68037                   case 'table':
68038                     {
68039                       token.tokens = {
68040                         header: [],
68041                         cells: []
68042                       }; // header
68043
68044                       l2 = token.header.length;
68045
68046                       for (j = 0; j < l2; j++) {
68047                         token.tokens.header[j] = [];
68048                         this.inlineTokens(token.header[j], token.tokens.header[j]);
68049                       } // cells
68050
68051
68052                       l2 = token.cells.length;
68053
68054                       for (j = 0; j < l2; j++) {
68055                         row = token.cells[j];
68056                         token.tokens.cells[j] = [];
68057
68058                         for (k = 0; k < row.length; k++) {
68059                           token.tokens.cells[j][k] = [];
68060                           this.inlineTokens(row[k], token.tokens.cells[j][k]);
68061                         }
68062                       }
68063
68064                       break;
68065                     }
68066
68067                   case 'blockquote':
68068                     {
68069                       this.inline(token.tokens);
68070                       break;
68071                     }
68072
68073                   case 'list':
68074                     {
68075                       l2 = token.items.length;
68076
68077                       for (j = 0; j < l2; j++) {
68078                         this.inline(token.items[j].tokens);
68079                       }
68080
68081                       break;
68082                     }
68083                 }
68084               }
68085
68086               return tokens;
68087             }
68088             /**
68089              * Lexing/Compiling
68090              */
68091
68092           }, {
68093             key: "inlineTokens",
68094             value: function inlineTokens(src) {
68095               var tokens = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
68096               var inLink = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
68097               var inRawBlock = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
68098               var token, lastToken; // String with links masked to avoid interference with em and strong
68099
68100               var maskedSrc = src;
68101               var match;
68102               var keepPrevChar, prevChar; // Mask out reflinks
68103
68104               if (this.tokens.links) {
68105                 var links = Object.keys(this.tokens.links);
68106
68107                 if (links.length > 0) {
68108                   while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {
68109                     if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) {
68110                       maskedSrc = maskedSrc.slice(0, match.index) + '[' + repeatString('a', match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);
68111                     }
68112                   }
68113                 }
68114               } // Mask out other blocks
68115
68116
68117               while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {
68118                 maskedSrc = maskedSrc.slice(0, match.index) + '[' + repeatString('a', match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
68119               } // Mask out escaped em & strong delimiters
68120
68121
68122               while ((match = this.tokenizer.rules.inline.escapedEmSt.exec(maskedSrc)) != null) {
68123                 maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.escapedEmSt.lastIndex);
68124               }
68125
68126               while (src) {
68127                 if (!keepPrevChar) {
68128                   prevChar = '';
68129                 }
68130
68131                 keepPrevChar = false; // escape
68132
68133                 if (token = this.tokenizer.escape(src)) {
68134                   src = src.substring(token.raw.length);
68135                   tokens.push(token);
68136                   continue;
68137                 } // tag
68138
68139
68140                 if (token = this.tokenizer.tag(src, inLink, inRawBlock)) {
68141                   src = src.substring(token.raw.length);
68142                   inLink = token.inLink;
68143                   inRawBlock = token.inRawBlock;
68144                   var _lastToken = tokens[tokens.length - 1];
68145
68146                   if (_lastToken && token.type === 'text' && _lastToken.type === 'text') {
68147                     _lastToken.raw += token.raw;
68148                     _lastToken.text += token.text;
68149                   } else {
68150                     tokens.push(token);
68151                   }
68152
68153                   continue;
68154                 } // link
68155
68156
68157                 if (token = this.tokenizer.link(src)) {
68158                   src = src.substring(token.raw.length);
68159
68160                   if (token.type === 'link') {
68161                     token.tokens = this.inlineTokens(token.text, [], true, inRawBlock);
68162                   }
68163
68164                   tokens.push(token);
68165                   continue;
68166                 } // reflink, nolink
68167
68168
68169                 if (token = this.tokenizer.reflink(src, this.tokens.links)) {
68170                   src = src.substring(token.raw.length);
68171                   var _lastToken2 = tokens[tokens.length - 1];
68172
68173                   if (token.type === 'link') {
68174                     token.tokens = this.inlineTokens(token.text, [], true, inRawBlock);
68175                     tokens.push(token);
68176                   } else if (_lastToken2 && token.type === 'text' && _lastToken2.type === 'text') {
68177                     _lastToken2.raw += token.raw;
68178                     _lastToken2.text += token.text;
68179                   } else {
68180                     tokens.push(token);
68181                   }
68182
68183                   continue;
68184                 } // em & strong
68185
68186
68187                 if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) {
68188                   src = src.substring(token.raw.length);
68189                   token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock);
68190                   tokens.push(token);
68191                   continue;
68192                 } // code
68193
68194
68195                 if (token = this.tokenizer.codespan(src)) {
68196                   src = src.substring(token.raw.length);
68197                   tokens.push(token);
68198                   continue;
68199                 } // br
68200
68201
68202                 if (token = this.tokenizer.br(src)) {
68203                   src = src.substring(token.raw.length);
68204                   tokens.push(token);
68205                   continue;
68206                 } // del (gfm)
68207
68208
68209                 if (token = this.tokenizer.del(src)) {
68210                   src = src.substring(token.raw.length);
68211                   token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock);
68212                   tokens.push(token);
68213                   continue;
68214                 } // autolink
68215
68216
68217                 if (token = this.tokenizer.autolink(src, mangle)) {
68218                   src = src.substring(token.raw.length);
68219                   tokens.push(token);
68220                   continue;
68221                 } // url (gfm)
68222
68223
68224                 if (!inLink && (token = this.tokenizer.url(src, mangle))) {
68225                   src = src.substring(token.raw.length);
68226                   tokens.push(token);
68227                   continue;
68228                 } // text
68229
68230
68231                 if (token = this.tokenizer.inlineText(src, inRawBlock, smartypants)) {
68232                   src = src.substring(token.raw.length);
68233
68234                   if (token.raw.slice(-1) !== '_') {
68235                     // Track prevChar before string of ____ started
68236                     prevChar = token.raw.slice(-1);
68237                   }
68238
68239                   keepPrevChar = true;
68240                   lastToken = tokens[tokens.length - 1];
68241
68242                   if (lastToken && lastToken.type === 'text') {
68243                     lastToken.raw += token.raw;
68244                     lastToken.text += token.text;
68245                   } else {
68246                     tokens.push(token);
68247                   }
68248
68249                   continue;
68250                 }
68251
68252                 if (src) {
68253                   var errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
68254
68255                   if (this.options.silent) {
68256                     console.error(errMsg);
68257                     break;
68258                   } else {
68259                     throw new Error(errMsg);
68260                   }
68261                 }
68262               }
68263
68264               return tokens;
68265             }
68266           }], [{
68267             key: "rules",
68268             get: function get() {
68269               return {
68270                 block: block,
68271                 inline: inline
68272               };
68273             }
68274             /**
68275              * Static Lex Method
68276              */
68277
68278           }, {
68279             key: "lex",
68280             value: function lex(src, options) {
68281               var lexer = new Lexer(options);
68282               return lexer.lex(src);
68283             }
68284             /**
68285              * Static Lex Inline Method
68286              */
68287
68288           }, {
68289             key: "lexInline",
68290             value: function lexInline(src, options) {
68291               var lexer = new Lexer(options);
68292               return lexer.inlineTokens(src);
68293             }
68294           }]);
68295
68296           return Lexer;
68297         }();
68298
68299         var defaults$2 = defaults$5.exports.defaults;
68300         var cleanUrl = helpers.cleanUrl,
68301             escape$2 = helpers.escape;
68302         /**
68303          * Renderer
68304          */
68305
68306         var Renderer_1 = /*#__PURE__*/function () {
68307           function Renderer(options) {
68308             _classCallCheck$1(this, Renderer);
68309
68310             this.options = options || defaults$2;
68311           }
68312
68313           _createClass$1(Renderer, [{
68314             key: "code",
68315             value: function code(_code, infostring, escaped) {
68316               var lang = (infostring || '').match(/\S*/)[0];
68317
68318               if (this.options.highlight) {
68319                 var out = this.options.highlight(_code, lang);
68320
68321                 if (out != null && out !== _code) {
68322                   escaped = true;
68323                   _code = out;
68324                 }
68325               }
68326
68327               _code = _code.replace(/\n$/, '') + '\n';
68328
68329               if (!lang) {
68330                 return '<pre><code>' + (escaped ? _code : escape$2(_code, true)) + '</code></pre>\n';
68331               }
68332
68333               return '<pre><code class="' + this.options.langPrefix + escape$2(lang, true) + '">' + (escaped ? _code : escape$2(_code, true)) + '</code></pre>\n';
68334             }
68335           }, {
68336             key: "blockquote",
68337             value: function blockquote(quote) {
68338               return '<blockquote>\n' + quote + '</blockquote>\n';
68339             }
68340           }, {
68341             key: "html",
68342             value: function html(_html) {
68343               return _html;
68344             }
68345           }, {
68346             key: "heading",
68347             value: function heading(text, level, raw, slugger) {
68348               if (this.options.headerIds) {
68349                 return '<h' + level + ' id="' + this.options.headerPrefix + slugger.slug(raw) + '">' + text + '</h' + level + '>\n';
68350               } // ignore IDs
68351
68352
68353               return '<h' + level + '>' + text + '</h' + level + '>\n';
68354             }
68355           }, {
68356             key: "hr",
68357             value: function hr() {
68358               return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
68359             }
68360           }, {
68361             key: "list",
68362             value: function list(body, ordered, start) {
68363               var type = ordered ? 'ol' : 'ul',
68364                   startatt = ordered && start !== 1 ? ' start="' + start + '"' : '';
68365               return '<' + type + startatt + '>\n' + body + '</' + type + '>\n';
68366             }
68367           }, {
68368             key: "listitem",
68369             value: function listitem(text) {
68370               return '<li>' + text + '</li>\n';
68371             }
68372           }, {
68373             key: "checkbox",
68374             value: function checkbox(checked) {
68375               return '<input ' + (checked ? 'checked="" ' : '') + 'disabled="" type="checkbox"' + (this.options.xhtml ? ' /' : '') + '> ';
68376             }
68377           }, {
68378             key: "paragraph",
68379             value: function paragraph(text) {
68380               return '<p>' + text + '</p>\n';
68381             }
68382           }, {
68383             key: "table",
68384             value: function table(header, body) {
68385               if (body) body = '<tbody>' + body + '</tbody>';
68386               return '<table>\n' + '<thead>\n' + header + '</thead>\n' + body + '</table>\n';
68387             }
68388           }, {
68389             key: "tablerow",
68390             value: function tablerow(content) {
68391               return '<tr>\n' + content + '</tr>\n';
68392             }
68393           }, {
68394             key: "tablecell",
68395             value: function tablecell(content, flags) {
68396               var type = flags.header ? 'th' : 'td';
68397               var tag = flags.align ? '<' + type + ' align="' + flags.align + '">' : '<' + type + '>';
68398               return tag + content + '</' + type + '>\n';
68399             } // span level renderer
68400
68401           }, {
68402             key: "strong",
68403             value: function strong(text) {
68404               return '<strong>' + text + '</strong>';
68405             }
68406           }, {
68407             key: "em",
68408             value: function em(text) {
68409               return '<em>' + text + '</em>';
68410             }
68411           }, {
68412             key: "codespan",
68413             value: function codespan(text) {
68414               return '<code>' + text + '</code>';
68415             }
68416           }, {
68417             key: "br",
68418             value: function br() {
68419               return this.options.xhtml ? '<br/>' : '<br>';
68420             }
68421           }, {
68422             key: "del",
68423             value: function del(text) {
68424               return '<del>' + text + '</del>';
68425             }
68426           }, {
68427             key: "link",
68428             value: function link(href, title, text) {
68429               href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
68430
68431               if (href === null) {
68432                 return text;
68433               }
68434
68435               var out = '<a href="' + escape$2(href) + '"';
68436
68437               if (title) {
68438                 out += ' title="' + title + '"';
68439               }
68440
68441               out += '>' + text + '</a>';
68442               return out;
68443             }
68444           }, {
68445             key: "image",
68446             value: function image(href, title, text) {
68447               href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
68448
68449               if (href === null) {
68450                 return text;
68451               }
68452
68453               var out = '<img src="' + href + '" alt="' + text + '"';
68454
68455               if (title) {
68456                 out += ' title="' + title + '"';
68457               }
68458
68459               out += this.options.xhtml ? '/>' : '>';
68460               return out;
68461             }
68462           }, {
68463             key: "text",
68464             value: function text(_text) {
68465               return _text;
68466             }
68467           }]);
68468
68469           return Renderer;
68470         }();
68471
68472         var TextRenderer_1 = /*#__PURE__*/function () {
68473           function TextRenderer() {
68474             _classCallCheck$1(this, TextRenderer);
68475           }
68476
68477           _createClass$1(TextRenderer, [{
68478             key: "strong",
68479             value: // no need for block level renderers
68480             function strong(text) {
68481               return text;
68482             }
68483           }, {
68484             key: "em",
68485             value: function em(text) {
68486               return text;
68487             }
68488           }, {
68489             key: "codespan",
68490             value: function codespan(text) {
68491               return text;
68492             }
68493           }, {
68494             key: "del",
68495             value: function del(text) {
68496               return text;
68497             }
68498           }, {
68499             key: "html",
68500             value: function html(text) {
68501               return text;
68502             }
68503           }, {
68504             key: "text",
68505             value: function text(_text) {
68506               return _text;
68507             }
68508           }, {
68509             key: "link",
68510             value: function link(href, title, text) {
68511               return '' + text;
68512             }
68513           }, {
68514             key: "image",
68515             value: function image(href, title, text) {
68516               return '' + text;
68517             }
68518           }, {
68519             key: "br",
68520             value: function br() {
68521               return '';
68522             }
68523           }]);
68524
68525           return TextRenderer;
68526         }();
68527
68528         var Slugger_1 = /*#__PURE__*/function () {
68529           function Slugger() {
68530             _classCallCheck$1(this, Slugger);
68531
68532             this.seen = {};
68533           }
68534
68535           _createClass$1(Slugger, [{
68536             key: "serialize",
68537             value: function serialize(value) {
68538               return value.toLowerCase().trim() // remove html tags
68539               .replace(/<[!\/a-z].*?>/ig, '') // remove unwanted chars
68540               .replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '').replace(/\s/g, '-');
68541             }
68542             /**
68543              * Finds the next safe (unique) slug to use
68544              */
68545
68546           }, {
68547             key: "getNextSafeSlug",
68548             value: function getNextSafeSlug(originalSlug, isDryRun) {
68549               var slug = originalSlug;
68550               var occurenceAccumulator = 0;
68551
68552               if (this.seen.hasOwnProperty(slug)) {
68553                 occurenceAccumulator = this.seen[originalSlug];
68554
68555                 do {
68556                   occurenceAccumulator++;
68557                   slug = originalSlug + '-' + occurenceAccumulator;
68558                 } while (this.seen.hasOwnProperty(slug));
68559               }
68560
68561               if (!isDryRun) {
68562                 this.seen[originalSlug] = occurenceAccumulator;
68563                 this.seen[slug] = 0;
68564               }
68565
68566               return slug;
68567             }
68568             /**
68569              * Convert string to unique id
68570              * @param {object} options
68571              * @param {boolean} options.dryrun Generates the next unique slug without updating the internal accumulator.
68572              */
68573
68574           }, {
68575             key: "slug",
68576             value: function slug(value) {
68577               var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
68578               var slug = this.serialize(value);
68579               return this.getNextSafeSlug(slug, options.dryrun);
68580             }
68581           }]);
68582
68583           return Slugger;
68584         }();
68585
68586         var Renderer$1 = Renderer_1;
68587         var TextRenderer$1 = TextRenderer_1;
68588         var Slugger$1 = Slugger_1;
68589         var defaults$1 = defaults$5.exports.defaults;
68590         var unescape$1 = helpers.unescape;
68591         /**
68592          * Parsing & Compiling
68593          */
68594
68595         var Parser_1 = /*#__PURE__*/function () {
68596           function Parser(options) {
68597             _classCallCheck$1(this, Parser);
68598
68599             this.options = options || defaults$1;
68600             this.options.renderer = this.options.renderer || new Renderer$1();
68601             this.renderer = this.options.renderer;
68602             this.renderer.options = this.options;
68603             this.textRenderer = new TextRenderer$1();
68604             this.slugger = new Slugger$1();
68605           }
68606           /**
68607            * Static Parse Method
68608            */
68609
68610
68611           _createClass$1(Parser, [{
68612             key: "parse",
68613             value:
68614             /**
68615              * Parse Loop
68616              */
68617             function parse(tokens) {
68618               var top = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
68619               var out = '',
68620                   i,
68621                   j,
68622                   k,
68623                   l2,
68624                   l3,
68625                   row,
68626                   cell,
68627                   header,
68628                   body,
68629                   token,
68630                   ordered,
68631                   start,
68632                   loose,
68633                   itemBody,
68634                   item,
68635                   checked,
68636                   task,
68637                   checkbox;
68638               var l = tokens.length;
68639
68640               for (i = 0; i < l; i++) {
68641                 token = tokens[i];
68642
68643                 switch (token.type) {
68644                   case 'space':
68645                     {
68646                       continue;
68647                     }
68648
68649                   case 'hr':
68650                     {
68651                       out += this.renderer.hr();
68652                       continue;
68653                     }
68654
68655                   case 'heading':
68656                     {
68657                       out += this.renderer.heading(this.parseInline(token.tokens), token.depth, unescape$1(this.parseInline(token.tokens, this.textRenderer)), this.slugger);
68658                       continue;
68659                     }
68660
68661                   case 'code':
68662                     {
68663                       out += this.renderer.code(token.text, token.lang, token.escaped);
68664                       continue;
68665                     }
68666
68667                   case 'table':
68668                     {
68669                       header = ''; // header
68670
68671                       cell = '';
68672                       l2 = token.header.length;
68673
68674                       for (j = 0; j < l2; j++) {
68675                         cell += this.renderer.tablecell(this.parseInline(token.tokens.header[j]), {
68676                           header: true,
68677                           align: token.align[j]
68678                         });
68679                       }
68680
68681                       header += this.renderer.tablerow(cell);
68682                       body = '';
68683                       l2 = token.cells.length;
68684
68685                       for (j = 0; j < l2; j++) {
68686                         row = token.tokens.cells[j];
68687                         cell = '';
68688                         l3 = row.length;
68689
68690                         for (k = 0; k < l3; k++) {
68691                           cell += this.renderer.tablecell(this.parseInline(row[k]), {
68692                             header: false,
68693                             align: token.align[k]
68694                           });
68695                         }
68696
68697                         body += this.renderer.tablerow(cell);
68698                       }
68699
68700                       out += this.renderer.table(header, body);
68701                       continue;
68702                     }
68703
68704                   case 'blockquote':
68705                     {
68706                       body = this.parse(token.tokens);
68707                       out += this.renderer.blockquote(body);
68708                       continue;
68709                     }
68710
68711                   case 'list':
68712                     {
68713                       ordered = token.ordered;
68714                       start = token.start;
68715                       loose = token.loose;
68716                       l2 = token.items.length;
68717                       body = '';
68718
68719                       for (j = 0; j < l2; j++) {
68720                         item = token.items[j];
68721                         checked = item.checked;
68722                         task = item.task;
68723                         itemBody = '';
68724
68725                         if (item.task) {
68726                           checkbox = this.renderer.checkbox(checked);
68727
68728                           if (loose) {
68729                             if (item.tokens.length > 0 && item.tokens[0].type === 'text') {
68730                               item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
68731
68732                               if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {
68733                                 item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text;
68734                               }
68735                             } else {
68736                               item.tokens.unshift({
68737                                 type: 'text',
68738                                 text: checkbox
68739                               });
68740                             }
68741                           } else {
68742                             itemBody += checkbox;
68743                           }
68744                         }
68745
68746                         itemBody += this.parse(item.tokens, loose);
68747                         body += this.renderer.listitem(itemBody, task, checked);
68748                       }
68749
68750                       out += this.renderer.list(body, ordered, start);
68751                       continue;
68752                     }
68753
68754                   case 'html':
68755                     {
68756                       // TODO parse inline content if parameter markdown=1
68757                       out += this.renderer.html(token.text);
68758                       continue;
68759                     }
68760
68761                   case 'paragraph':
68762                     {
68763                       out += this.renderer.paragraph(this.parseInline(token.tokens));
68764                       continue;
68765                     }
68766
68767                   case 'text':
68768                     {
68769                       body = token.tokens ? this.parseInline(token.tokens) : token.text;
68770
68771                       while (i + 1 < l && tokens[i + 1].type === 'text') {
68772                         token = tokens[++i];
68773                         body += '\n' + (token.tokens ? this.parseInline(token.tokens) : token.text);
68774                       }
68775
68776                       out += top ? this.renderer.paragraph(body) : body;
68777                       continue;
68778                     }
68779
68780                   default:
68781                     {
68782                       var errMsg = 'Token with "' + token.type + '" type was not found.';
68783
68784                       if (this.options.silent) {
68785                         console.error(errMsg);
68786                         return;
68787                       } else {
68788                         throw new Error(errMsg);
68789                       }
68790                     }
68791                 }
68792               }
68793
68794               return out;
68795             }
68796             /**
68797              * Parse Inline Tokens
68798              */
68799
68800           }, {
68801             key: "parseInline",
68802             value: function parseInline(tokens, renderer) {
68803               renderer = renderer || this.renderer;
68804               var out = '',
68805                   i,
68806                   token;
68807               var l = tokens.length;
68808
68809               for (i = 0; i < l; i++) {
68810                 token = tokens[i];
68811
68812                 switch (token.type) {
68813                   case 'escape':
68814                     {
68815                       out += renderer.text(token.text);
68816                       break;
68817                     }
68818
68819                   case 'html':
68820                     {
68821                       out += renderer.html(token.text);
68822                       break;
68823                     }
68824
68825                   case 'link':
68826                     {
68827                       out += renderer.link(token.href, token.title, this.parseInline(token.tokens, renderer));
68828                       break;
68829                     }
68830
68831                   case 'image':
68832                     {
68833                       out += renderer.image(token.href, token.title, token.text);
68834                       break;
68835                     }
68836
68837                   case 'strong':
68838                     {
68839                       out += renderer.strong(this.parseInline(token.tokens, renderer));
68840                       break;
68841                     }
68842
68843                   case 'em':
68844                     {
68845                       out += renderer.em(this.parseInline(token.tokens, renderer));
68846                       break;
68847                     }
68848
68849                   case 'codespan':
68850                     {
68851                       out += renderer.codespan(token.text);
68852                       break;
68853                     }
68854
68855                   case 'br':
68856                     {
68857                       out += renderer.br();
68858                       break;
68859                     }
68860
68861                   case 'del':
68862                     {
68863                       out += renderer.del(this.parseInline(token.tokens, renderer));
68864                       break;
68865                     }
68866
68867                   case 'text':
68868                     {
68869                       out += renderer.text(token.text);
68870                       break;
68871                     }
68872
68873                   default:
68874                     {
68875                       var errMsg = 'Token with "' + token.type + '" type was not found.';
68876
68877                       if (this.options.silent) {
68878                         console.error(errMsg);
68879                         return;
68880                       } else {
68881                         throw new Error(errMsg);
68882                       }
68883                     }
68884                 }
68885               }
68886
68887               return out;
68888             }
68889           }], [{
68890             key: "parse",
68891             value: function parse(tokens, options) {
68892               var parser = new Parser(options);
68893               return parser.parse(tokens);
68894             }
68895             /**
68896              * Static Parse Inline Method
68897              */
68898
68899           }, {
68900             key: "parseInline",
68901             value: function parseInline(tokens, options) {
68902               var parser = new Parser(options);
68903               return parser.parseInline(tokens);
68904             }
68905           }]);
68906
68907           return Parser;
68908         }();
68909
68910         var Lexer = Lexer_1;
68911         var Parser = Parser_1;
68912         var Tokenizer = Tokenizer_1;
68913         var Renderer = Renderer_1;
68914         var TextRenderer = TextRenderer_1;
68915         var Slugger = Slugger_1;
68916         var merge = helpers.merge,
68917             checkSanitizeDeprecation = helpers.checkSanitizeDeprecation,
68918             escape$1 = helpers.escape;
68919         var getDefaults = defaults$5.exports.getDefaults,
68920             changeDefaults = defaults$5.exports.changeDefaults,
68921             defaults = defaults$5.exports.defaults;
68922         /**
68923          * Marked
68924          */
68925
68926         function marked(src, opt, callback) {
68927           // throw error in case of non string input
68928           if (typeof src === 'undefined' || src === null) {
68929             throw new Error('marked(): input parameter is undefined or null');
68930           }
68931
68932           if (typeof src !== 'string') {
68933             throw new Error('marked(): input parameter is of type ' + Object.prototype.toString.call(src) + ', string expected');
68934           }
68935
68936           if (typeof opt === 'function') {
68937             callback = opt;
68938             opt = null;
68939           }
68940
68941           opt = merge({}, marked.defaults, opt || {});
68942           checkSanitizeDeprecation(opt);
68943
68944           if (callback) {
68945             var highlight = opt.highlight;
68946             var tokens;
68947
68948             try {
68949               tokens = Lexer.lex(src, opt);
68950             } catch (e) {
68951               return callback(e);
68952             }
68953
68954             var done = function done(err) {
68955               var out;
68956
68957               if (!err) {
68958                 try {
68959                   if (opt.walkTokens) {
68960                     marked.walkTokens(tokens, opt.walkTokens);
68961                   }
68962
68963                   out = Parser.parse(tokens, opt);
68964                 } catch (e) {
68965                   err = e;
68966                 }
68967               }
68968
68969               opt.highlight = highlight;
68970               return err ? callback(err) : callback(null, out);
68971             };
68972
68973             if (!highlight || highlight.length < 3) {
68974               return done();
68975             }
68976
68977             delete opt.highlight;
68978             if (!tokens.length) return done();
68979             var pending = 0;
68980             marked.walkTokens(tokens, function (token) {
68981               if (token.type === 'code') {
68982                 pending++;
68983                 setTimeout(function () {
68984                   highlight(token.text, token.lang, function (err, code) {
68985                     if (err) {
68986                       return done(err);
68987                     }
68988
68989                     if (code != null && code !== token.text) {
68990                       token.text = code;
68991                       token.escaped = true;
68992                     }
68993
68994                     pending--;
68995
68996                     if (pending === 0) {
68997                       done();
68998                     }
68999                   });
69000                 }, 0);
69001               }
69002             });
69003
69004             if (pending === 0) {
69005               done();
69006             }
69007
69008             return;
69009           }
69010
69011           try {
69012             var _tokens = Lexer.lex(src, opt);
69013
69014             if (opt.walkTokens) {
69015               marked.walkTokens(_tokens, opt.walkTokens);
69016             }
69017
69018             return Parser.parse(_tokens, opt);
69019           } catch (e) {
69020             e.message += '\nPlease report this to https://github.com/markedjs/marked.';
69021
69022             if (opt.silent) {
69023               return '<p>An error occurred:</p><pre>' + escape$1(e.message + '', true) + '</pre>';
69024             }
69025
69026             throw e;
69027           }
69028         }
69029         /**
69030          * Options
69031          */
69032
69033
69034         marked.options = marked.setOptions = function (opt) {
69035           merge(marked.defaults, opt);
69036           changeDefaults(marked.defaults);
69037           return marked;
69038         };
69039
69040         marked.getDefaults = getDefaults;
69041         marked.defaults = defaults;
69042         /**
69043          * Use Extension
69044          */
69045
69046         marked.use = function (extension) {
69047           var opts = merge({}, extension);
69048
69049           if (extension.renderer) {
69050             (function () {
69051               var renderer = marked.defaults.renderer || new Renderer();
69052
69053               var _loop = function _loop(prop) {
69054                 var prevRenderer = renderer[prop];
69055
69056                 renderer[prop] = function () {
69057                   for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
69058                     args[_key] = arguments[_key];
69059                   }
69060
69061                   var ret = extension.renderer[prop].apply(renderer, args);
69062
69063                   if (ret === false) {
69064                     ret = prevRenderer.apply(renderer, args);
69065                   }
69066
69067                   return ret;
69068                 };
69069               };
69070
69071               for (var prop in extension.renderer) {
69072                 _loop(prop);
69073               }
69074
69075               opts.renderer = renderer;
69076             })();
69077           }
69078
69079           if (extension.tokenizer) {
69080             (function () {
69081               var tokenizer = marked.defaults.tokenizer || new Tokenizer();
69082
69083               var _loop2 = function _loop2(prop) {
69084                 var prevTokenizer = tokenizer[prop];
69085
69086                 tokenizer[prop] = function () {
69087                   for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
69088                     args[_key2] = arguments[_key2];
69089                   }
69090
69091                   var ret = extension.tokenizer[prop].apply(tokenizer, args);
69092
69093                   if (ret === false) {
69094                     ret = prevTokenizer.apply(tokenizer, args);
69095                   }
69096
69097                   return ret;
69098                 };
69099               };
69100
69101               for (var prop in extension.tokenizer) {
69102                 _loop2(prop);
69103               }
69104
69105               opts.tokenizer = tokenizer;
69106             })();
69107           }
69108
69109           if (extension.walkTokens) {
69110             var walkTokens = marked.defaults.walkTokens;
69111
69112             opts.walkTokens = function (token) {
69113               extension.walkTokens(token);
69114
69115               if (walkTokens) {
69116                 walkTokens(token);
69117               }
69118             };
69119           }
69120
69121           marked.setOptions(opts);
69122         };
69123         /**
69124          * Run callback for every token
69125          */
69126
69127
69128         marked.walkTokens = function (tokens, callback) {
69129           var _iterator = _createForOfIteratorHelper(tokens),
69130               _step;
69131
69132           try {
69133             for (_iterator.s(); !(_step = _iterator.n()).done;) {
69134               var token = _step.value;
69135               callback(token);
69136
69137               switch (token.type) {
69138                 case 'table':
69139                   {
69140                     var _iterator2 = _createForOfIteratorHelper(token.tokens.header),
69141                         _step2;
69142
69143                     try {
69144                       for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
69145                         var cell = _step2.value;
69146                         marked.walkTokens(cell, callback);
69147                       }
69148                     } catch (err) {
69149                       _iterator2.e(err);
69150                     } finally {
69151                       _iterator2.f();
69152                     }
69153
69154                     var _iterator3 = _createForOfIteratorHelper(token.tokens.cells),
69155                         _step3;
69156
69157                     try {
69158                       for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
69159                         var row = _step3.value;
69160
69161                         var _iterator4 = _createForOfIteratorHelper(row),
69162                             _step4;
69163
69164                         try {
69165                           for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
69166                             var _cell = _step4.value;
69167                             marked.walkTokens(_cell, callback);
69168                           }
69169                         } catch (err) {
69170                           _iterator4.e(err);
69171                         } finally {
69172                           _iterator4.f();
69173                         }
69174                       }
69175                     } catch (err) {
69176                       _iterator3.e(err);
69177                     } finally {
69178                       _iterator3.f();
69179                     }
69180
69181                     break;
69182                   }
69183
69184                 case 'list':
69185                   {
69186                     marked.walkTokens(token.items, callback);
69187                     break;
69188                   }
69189
69190                 default:
69191                   {
69192                     if (token.tokens) {
69193                       marked.walkTokens(token.tokens, callback);
69194                     }
69195                   }
69196               }
69197             }
69198           } catch (err) {
69199             _iterator.e(err);
69200           } finally {
69201             _iterator.f();
69202           }
69203         };
69204         /**
69205          * Parse Inline
69206          */
69207
69208
69209         marked.parseInline = function (src, opt) {
69210           // throw error in case of non string input
69211           if (typeof src === 'undefined' || src === null) {
69212             throw new Error('marked.parseInline(): input parameter is undefined or null');
69213           }
69214
69215           if (typeof src !== 'string') {
69216             throw new Error('marked.parseInline(): input parameter is of type ' + Object.prototype.toString.call(src) + ', string expected');
69217           }
69218
69219           opt = merge({}, marked.defaults, opt || {});
69220           checkSanitizeDeprecation(opt);
69221
69222           try {
69223             var tokens = Lexer.lexInline(src, opt);
69224
69225             if (opt.walkTokens) {
69226               marked.walkTokens(tokens, opt.walkTokens);
69227             }
69228
69229             return Parser.parseInline(tokens, opt);
69230           } catch (e) {
69231             e.message += '\nPlease report this to https://github.com/markedjs/marked.';
69232
69233             if (opt.silent) {
69234               return '<p>An error occurred:</p><pre>' + escape$1(e.message + '', true) + '</pre>';
69235             }
69236
69237             throw e;
69238           }
69239         };
69240         /**
69241          * Expose
69242          */
69243
69244
69245         marked.Parser = Parser;
69246         marked.parser = Parser.parse;
69247         marked.Renderer = Renderer;
69248         marked.TextRenderer = TextRenderer;
69249         marked.Lexer = Lexer;
69250         marked.lexer = Lexer.lex;
69251         marked.Tokenizer = Tokenizer;
69252         marked.Slugger = Slugger;
69253         marked.parse = marked;
69254         var marked_1 = marked;
69255
69256         var tiler$4 = utilTiler();
69257         var dispatch$5 = dispatch$8('loaded');
69258         var _tileZoom$1 = 14;
69259         var _osmoseUrlRoot = 'https://osmose.openstreetmap.fr/api/0.3';
69260         var _osmoseData = {
69261           icons: {},
69262           items: []
69263         }; // This gets reassigned if reset
69264
69265         var _cache;
69266
69267         function abortRequest$4(controller) {
69268           if (controller) {
69269             controller.abort();
69270           }
69271         }
69272
69273         function abortUnwantedRequests$1(cache, tiles) {
69274           Object.keys(cache.inflightTile).forEach(function (k) {
69275             var wanted = tiles.find(function (tile) {
69276               return k === tile.id;
69277             });
69278
69279             if (!wanted) {
69280               abortRequest$4(cache.inflightTile[k]);
69281               delete cache.inflightTile[k];
69282             }
69283           });
69284         }
69285
69286         function encodeIssueRtree(d) {
69287           return {
69288             minX: d.loc[0],
69289             minY: d.loc[1],
69290             maxX: d.loc[0],
69291             maxY: d.loc[1],
69292             data: d
69293           };
69294         } // Replace or remove QAItem from rtree
69295
69296
69297         function updateRtree$1(item, replace) {
69298           _cache.rtree.remove(item, function (a, b) {
69299             return a.data.id === b.data.id;
69300           });
69301
69302           if (replace) {
69303             _cache.rtree.insert(item);
69304           }
69305         } // Issues shouldn't obscure each other
69306
69307
69308         function preventCoincident(loc) {
69309           var coincident = false;
69310
69311           do {
69312             // first time, move marker up. after that, move marker right.
69313             var delta = coincident ? [0.00001, 0] : [0, 0.00001];
69314             loc = geoVecAdd(loc, delta);
69315             var bbox = geoExtent(loc).bbox();
69316             coincident = _cache.rtree.search(bbox).length;
69317           } while (coincident);
69318
69319           return loc;
69320         }
69321
69322         var serviceOsmose = {
69323           title: 'osmose',
69324           init: function init() {
69325             _mainFileFetcher.get('qa_data').then(function (d) {
69326               _osmoseData = d.osmose;
69327               _osmoseData.items = Object.keys(d.osmose.icons).map(function (s) {
69328                 return s.split('-')[0];
69329               }).reduce(function (unique, item) {
69330                 return unique.indexOf(item) !== -1 ? unique : [].concat(_toConsumableArray(unique), [item]);
69331               }, []);
69332             });
69333
69334             if (!_cache) {
69335               this.reset();
69336             }
69337
69338             this.event = utilRebind(this, dispatch$5, 'on');
69339           },
69340           reset: function reset() {
69341             var _strings = {};
69342             var _colors = {};
69343
69344             if (_cache) {
69345               Object.values(_cache.inflightTile).forEach(abortRequest$4); // Strings and colors are static and should not be re-populated
69346
69347               _strings = _cache.strings;
69348               _colors = _cache.colors;
69349             }
69350
69351             _cache = {
69352               data: {},
69353               loadedTile: {},
69354               inflightTile: {},
69355               inflightPost: {},
69356               closed: {},
69357               rtree: new RBush(),
69358               strings: _strings,
69359               colors: _colors
69360             };
69361           },
69362           loadIssues: function loadIssues(projection) {
69363             var _this = this;
69364
69365             var params = {
69366               // Tiles return a maximum # of issues
69367               // So we want to filter our request for only types iD supports
69368               item: _osmoseData.items
69369             }; // determine the needed tiles to cover the view
69370
69371             var tiles = tiler$4.zoomExtent([_tileZoom$1, _tileZoom$1]).getTiles(projection); // abort inflight requests that are no longer needed
69372
69373             abortUnwantedRequests$1(_cache, tiles); // issue new requests..
69374
69375             tiles.forEach(function (tile) {
69376               if (_cache.loadedTile[tile.id] || _cache.inflightTile[tile.id]) return;
69377
69378               var _tile$xyz = _slicedToArray(tile.xyz, 3),
69379                   x = _tile$xyz[0],
69380                   y = _tile$xyz[1],
69381                   z = _tile$xyz[2];
69382
69383               var url = "".concat(_osmoseUrlRoot, "/issues/").concat(z, "/").concat(x, "/").concat(y, ".json?") + utilQsString(params);
69384               var controller = new AbortController();
69385               _cache.inflightTile[tile.id] = controller;
69386               d3_json(url, {
69387                 signal: controller.signal
69388               }).then(function (data) {
69389                 delete _cache.inflightTile[tile.id];
69390                 _cache.loadedTile[tile.id] = true;
69391
69392                 if (data.features) {
69393                   data.features.forEach(function (issue) {
69394                     var _issue$properties = issue.properties,
69395                         item = _issue$properties.item,
69396                         cl = _issue$properties["class"],
69397                         id = _issue$properties.uuid;
69398                     /* Osmose issues are uniquely identified by a unique
69399                       `item` and `class` combination (both integer values) */
69400
69401                     var itemType = "".concat(item, "-").concat(cl); // Filter out unsupported issue types (some are too specific or advanced)
69402
69403                     if (itemType in _osmoseData.icons) {
69404                       var loc = issue.geometry.coordinates; // lon, lat
69405
69406                       loc = preventCoincident(loc);
69407                       var d = new QAItem(loc, _this, itemType, id, {
69408                         item: item
69409                       }); // Setting elems here prevents UI detail requests
69410
69411                       if (item === 8300 || item === 8360) {
69412                         d.elems = [];
69413                       }
69414
69415                       _cache.data[d.id] = d;
69416
69417                       _cache.rtree.insert(encodeIssueRtree(d));
69418                     }
69419                   });
69420                 }
69421
69422                 dispatch$5.call('loaded');
69423               })["catch"](function () {
69424                 delete _cache.inflightTile[tile.id];
69425                 _cache.loadedTile[tile.id] = true;
69426               });
69427             });
69428           },
69429           loadIssueDetail: function loadIssueDetail(issue) {
69430             var _this2 = this;
69431
69432             // Issue details only need to be fetched once
69433             if (issue.elems !== undefined) {
69434               return Promise.resolve(issue);
69435             }
69436
69437             var url = "".concat(_osmoseUrlRoot, "/issue/").concat(issue.id, "?langs=").concat(_mainLocalizer.localeCode());
69438
69439             var cacheDetails = function cacheDetails(data) {
69440               // Associated elements used for highlighting
69441               // Assign directly for immediate use in the callback
69442               issue.elems = data.elems.map(function (e) {
69443                 return e.type.substring(0, 1) + e.id;
69444               }); // Some issues have instance specific detail in a subtitle
69445
69446               issue.detail = data.subtitle ? marked_1(data.subtitle.auto) : '';
69447
69448               _this2.replaceItem(issue);
69449             };
69450
69451             return d3_json(url).then(cacheDetails).then(function () {
69452               return issue;
69453             });
69454           },
69455           loadStrings: function loadStrings() {
69456             var locale = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _mainLocalizer.localeCode();
69457             var items = Object.keys(_osmoseData.icons);
69458
69459             if (locale in _cache.strings && Object.keys(_cache.strings[locale]).length === items.length) {
69460               return Promise.resolve(_cache.strings[locale]);
69461             } // May be partially populated already if some requests were successful
69462
69463
69464             if (!(locale in _cache.strings)) {
69465               _cache.strings[locale] = {};
69466             } // Only need to cache strings for supported issue types
69467             // Using multiple individual item + class requests to reduce fetched data size
69468
69469
69470             var allRequests = items.map(function (itemType) {
69471               // No need to request data we already have
69472               if (itemType in _cache.strings[locale]) return null;
69473
69474               var cacheData = function cacheData(data) {
69475                 // Bunch of nested single value arrays of objects
69476                 var _data$categories = _slicedToArray(data.categories, 1),
69477                     _data$categories$ = _data$categories[0],
69478                     cat = _data$categories$ === void 0 ? {
69479                   items: []
69480                 } : _data$categories$;
69481
69482                 var _cat$items = _slicedToArray(cat.items, 1),
69483                     _cat$items$ = _cat$items[0],
69484                     item = _cat$items$ === void 0 ? {
69485                   "class": []
69486                 } : _cat$items$;
69487
69488                 var _item$class = _slicedToArray(item["class"], 1),
69489                     _item$class$ = _item$class[0],
69490                     cl = _item$class$ === void 0 ? null : _item$class$; // If null default value is reached, data wasn't as expected (or was empty)
69491
69492
69493                 if (!cl) {
69494                   /* eslint-disable no-console */
69495                   console.log("Osmose strings request (".concat(itemType, ") had unexpected data"));
69496                   /* eslint-enable no-console */
69497
69498                   return;
69499                 } // Cache served item colors to automatically style issue markers later
69500
69501
69502                 var itemInt = item.item,
69503                     color = item.color;
69504
69505                 if (/^#[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}/.test(color)) {
69506                   _cache.colors[itemInt] = color;
69507                 } // Value of root key will be null if no string exists
69508                 // If string exists, value is an object with key 'auto' for string
69509
69510
69511                 var title = cl.title,
69512                     detail = cl.detail,
69513                     fix = cl.fix,
69514                     trap = cl.trap; // Osmose titles shouldn't contain markdown
69515
69516                 var issueStrings = {};
69517                 if (title) issueStrings.title = title.auto;
69518                 if (detail) issueStrings.detail = marked_1(detail.auto);
69519                 if (trap) issueStrings.trap = marked_1(trap.auto);
69520                 if (fix) issueStrings.fix = marked_1(fix.auto);
69521                 _cache.strings[locale][itemType] = issueStrings;
69522               };
69523
69524               var _itemType$split = itemType.split('-'),
69525                   _itemType$split2 = _slicedToArray(_itemType$split, 2),
69526                   item = _itemType$split2[0],
69527                   cl = _itemType$split2[1]; // Osmose API falls back to English strings where untranslated or if locale doesn't exist
69528
69529
69530               var url = "".concat(_osmoseUrlRoot, "/items/").concat(item, "/class/").concat(cl, "?langs=").concat(locale);
69531               return d3_json(url).then(cacheData);
69532             }).filter(Boolean);
69533             return Promise.all(allRequests).then(function () {
69534               return _cache.strings[locale];
69535             });
69536           },
69537           getStrings: function getStrings(itemType) {
69538             var locale = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _mainLocalizer.localeCode();
69539             // No need to fallback to English, Osmose API handles this for us
69540             return locale in _cache.strings ? _cache.strings[locale][itemType] : {};
69541           },
69542           getColor: function getColor(itemType) {
69543             return itemType in _cache.colors ? _cache.colors[itemType] : '#FFFFFF';
69544           },
69545           postUpdate: function postUpdate(issue, callback) {
69546             var _this3 = this;
69547
69548             if (_cache.inflightPost[issue.id]) {
69549               return callback({
69550                 message: 'Issue update already inflight',
69551                 status: -2
69552               }, issue);
69553             } // UI sets the status to either 'done' or 'false'
69554
69555
69556             var url = "".concat(_osmoseUrlRoot, "/issue/").concat(issue.id, "/").concat(issue.newStatus);
69557             var controller = new AbortController();
69558
69559             var after = function after() {
69560               delete _cache.inflightPost[issue.id];
69561
69562               _this3.removeItem(issue);
69563
69564               if (issue.newStatus === 'done') {
69565                 // Keep track of the number of issues closed per `item` to tag the changeset
69566                 if (!(issue.item in _cache.closed)) {
69567                   _cache.closed[issue.item] = 0;
69568                 }
69569
69570                 _cache.closed[issue.item] += 1;
69571               }
69572
69573               if (callback) callback(null, issue);
69574             };
69575
69576             _cache.inflightPost[issue.id] = controller;
69577             fetch(url, {
69578               signal: controller.signal
69579             }).then(after)["catch"](function (err) {
69580               delete _cache.inflightPost[issue.id];
69581               if (callback) callback(err.message);
69582             });
69583           },
69584           // Get all cached QAItems covering the viewport
69585           getItems: function getItems(projection) {
69586             var viewport = projection.clipExtent();
69587             var min = [viewport[0][0], viewport[1][1]];
69588             var max = [viewport[1][0], viewport[0][1]];
69589             var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();
69590             return _cache.rtree.search(bbox).map(function (d) {
69591               return d.data;
69592             });
69593           },
69594           // Get a QAItem from cache
69595           // NOTE: Don't change method name until UI v3 is merged
69596           getError: function getError(id) {
69597             return _cache.data[id];
69598           },
69599           // get the name of the icon to display for this item
69600           getIcon: function getIcon(itemType) {
69601             return _osmoseData.icons[itemType];
69602           },
69603           // Replace a single QAItem in the cache
69604           replaceItem: function replaceItem(item) {
69605             if (!(item instanceof QAItem) || !item.id) return;
69606             _cache.data[item.id] = item;
69607             updateRtree$1(encodeIssueRtree(item), true); // true = replace
69608
69609             return item;
69610           },
69611           // Remove a single QAItem from the cache
69612           removeItem: function removeItem(item) {
69613             if (!(item instanceof QAItem) || !item.id) return;
69614             delete _cache.data[item.id];
69615             updateRtree$1(encodeIssueRtree(item), false); // false = remove
69616           },
69617           // Used to populate `closed:osmose:*` changeset tags
69618           getClosedCounts: function getClosedCounts() {
69619             return _cache.closed;
69620           },
69621           itemURL: function itemURL(item) {
69622             return "https://osmose.openstreetmap.fr/en/error/".concat(item.id);
69623           }
69624         };
69625
69626         var ieee754$1 = {};
69627
69628         /*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
69629
69630         ieee754$1.read = function (buffer, offset, isLE, mLen, nBytes) {
69631           var e, m;
69632           var eLen = nBytes * 8 - mLen - 1;
69633           var eMax = (1 << eLen) - 1;
69634           var eBias = eMax >> 1;
69635           var nBits = -7;
69636           var i = isLE ? nBytes - 1 : 0;
69637           var d = isLE ? -1 : 1;
69638           var s = buffer[offset + i];
69639           i += d;
69640           e = s & (1 << -nBits) - 1;
69641           s >>= -nBits;
69642           nBits += eLen;
69643
69644           for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
69645
69646           m = e & (1 << -nBits) - 1;
69647           e >>= -nBits;
69648           nBits += mLen;
69649
69650           for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
69651
69652           if (e === 0) {
69653             e = 1 - eBias;
69654           } else if (e === eMax) {
69655             return m ? NaN : (s ? -1 : 1) * Infinity;
69656           } else {
69657             m = m + Math.pow(2, mLen);
69658             e = e - eBias;
69659           }
69660
69661           return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
69662         };
69663
69664         ieee754$1.write = function (buffer, value, offset, isLE, mLen, nBytes) {
69665           var e, m, c;
69666           var eLen = nBytes * 8 - mLen - 1;
69667           var eMax = (1 << eLen) - 1;
69668           var eBias = eMax >> 1;
69669           var rt = mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0;
69670           var i = isLE ? 0 : nBytes - 1;
69671           var d = isLE ? 1 : -1;
69672           var s = value < 0 || value === 0 && 1 / value < 0 ? 1 : 0;
69673           value = Math.abs(value);
69674
69675           if (isNaN(value) || value === Infinity) {
69676             m = isNaN(value) ? 1 : 0;
69677             e = eMax;
69678           } else {
69679             e = Math.floor(Math.log(value) / Math.LN2);
69680
69681             if (value * (c = Math.pow(2, -e)) < 1) {
69682               e--;
69683               c *= 2;
69684             }
69685
69686             if (e + eBias >= 1) {
69687               value += rt / c;
69688             } else {
69689               value += rt * Math.pow(2, 1 - eBias);
69690             }
69691
69692             if (value * c >= 2) {
69693               e++;
69694               c /= 2;
69695             }
69696
69697             if (e + eBias >= eMax) {
69698               m = 0;
69699               e = eMax;
69700             } else if (e + eBias >= 1) {
69701               m = (value * c - 1) * Math.pow(2, mLen);
69702               e = e + eBias;
69703             } else {
69704               m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
69705               e = 0;
69706             }
69707           }
69708
69709           for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
69710
69711           e = e << mLen | m;
69712           eLen += mLen;
69713
69714           for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
69715
69716           buffer[offset + i - d] |= s * 128;
69717         };
69718
69719         var pbf = Pbf;
69720         var ieee754 = ieee754$1;
69721
69722         function Pbf(buf) {
69723           this.buf = ArrayBuffer.isView && ArrayBuffer.isView(buf) ? buf : new Uint8Array(buf || 0);
69724           this.pos = 0;
69725           this.type = 0;
69726           this.length = this.buf.length;
69727         }
69728
69729         Pbf.Varint = 0; // varint: int32, int64, uint32, uint64, sint32, sint64, bool, enum
69730
69731         Pbf.Fixed64 = 1; // 64-bit: double, fixed64, sfixed64
69732
69733         Pbf.Bytes = 2; // length-delimited: string, bytes, embedded messages, packed repeated fields
69734
69735         Pbf.Fixed32 = 5; // 32-bit: float, fixed32, sfixed32
69736
69737         var SHIFT_LEFT_32 = (1 << 16) * (1 << 16),
69738             SHIFT_RIGHT_32 = 1 / SHIFT_LEFT_32; // Threshold chosen based on both benchmarking and knowledge about browser string
69739         // data structures (which currently switch structure types at 12 bytes or more)
69740
69741         var TEXT_DECODER_MIN_LENGTH = 12;
69742         var utf8TextDecoder = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf8');
69743         Pbf.prototype = {
69744           destroy: function destroy() {
69745             this.buf = null;
69746           },
69747           // === READING =================================================================
69748           readFields: function readFields(readField, result, end) {
69749             end = end || this.length;
69750
69751             while (this.pos < end) {
69752               var val = this.readVarint(),
69753                   tag = val >> 3,
69754                   startPos = this.pos;
69755               this.type = val & 0x7;
69756               readField(tag, result, this);
69757               if (this.pos === startPos) this.skip(val);
69758             }
69759
69760             return result;
69761           },
69762           readMessage: function readMessage(readField, result) {
69763             return this.readFields(readField, result, this.readVarint() + this.pos);
69764           },
69765           readFixed32: function readFixed32() {
69766             var val = readUInt32(this.buf, this.pos);
69767             this.pos += 4;
69768             return val;
69769           },
69770           readSFixed32: function readSFixed32() {
69771             var val = readInt32(this.buf, this.pos);
69772             this.pos += 4;
69773             return val;
69774           },
69775           // 64-bit int handling is based on github.com/dpw/node-buffer-more-ints (MIT-licensed)
69776           readFixed64: function readFixed64() {
69777             var val = readUInt32(this.buf, this.pos) + readUInt32(this.buf, this.pos + 4) * SHIFT_LEFT_32;
69778             this.pos += 8;
69779             return val;
69780           },
69781           readSFixed64: function readSFixed64() {
69782             var val = readUInt32(this.buf, this.pos) + readInt32(this.buf, this.pos + 4) * SHIFT_LEFT_32;
69783             this.pos += 8;
69784             return val;
69785           },
69786           readFloat: function readFloat() {
69787             var val = ieee754.read(this.buf, this.pos, true, 23, 4);
69788             this.pos += 4;
69789             return val;
69790           },
69791           readDouble: function readDouble() {
69792             var val = ieee754.read(this.buf, this.pos, true, 52, 8);
69793             this.pos += 8;
69794             return val;
69795           },
69796           readVarint: function readVarint(isSigned) {
69797             var buf = this.buf,
69798                 val,
69799                 b;
69800             b = buf[this.pos++];
69801             val = b & 0x7f;
69802             if (b < 0x80) return val;
69803             b = buf[this.pos++];
69804             val |= (b & 0x7f) << 7;
69805             if (b < 0x80) return val;
69806             b = buf[this.pos++];
69807             val |= (b & 0x7f) << 14;
69808             if (b < 0x80) return val;
69809             b = buf[this.pos++];
69810             val |= (b & 0x7f) << 21;
69811             if (b < 0x80) return val;
69812             b = buf[this.pos];
69813             val |= (b & 0x0f) << 28;
69814             return readVarintRemainder(val, isSigned, this);
69815           },
69816           readVarint64: function readVarint64() {
69817             // for compatibility with v2.0.1
69818             return this.readVarint(true);
69819           },
69820           readSVarint: function readSVarint() {
69821             var num = this.readVarint();
69822             return num % 2 === 1 ? (num + 1) / -2 : num / 2; // zigzag encoding
69823           },
69824           readBoolean: function readBoolean() {
69825             return Boolean(this.readVarint());
69826           },
69827           readString: function readString() {
69828             var end = this.readVarint() + this.pos;
69829             var pos = this.pos;
69830             this.pos = end;
69831
69832             if (end - pos >= TEXT_DECODER_MIN_LENGTH && utf8TextDecoder) {
69833               // longer strings are fast with the built-in browser TextDecoder API
69834               return readUtf8TextDecoder(this.buf, pos, end);
69835             } // short strings are fast with our custom implementation
69836
69837
69838             return readUtf8(this.buf, pos, end);
69839           },
69840           readBytes: function readBytes() {
69841             var end = this.readVarint() + this.pos,
69842                 buffer = this.buf.subarray(this.pos, end);
69843             this.pos = end;
69844             return buffer;
69845           },
69846           // verbose for performance reasons; doesn't affect gzipped size
69847           readPackedVarint: function readPackedVarint(arr, isSigned) {
69848             if (this.type !== Pbf.Bytes) return arr.push(this.readVarint(isSigned));
69849             var end = readPackedEnd(this);
69850             arr = arr || [];
69851
69852             while (this.pos < end) {
69853               arr.push(this.readVarint(isSigned));
69854             }
69855
69856             return arr;
69857           },
69858           readPackedSVarint: function readPackedSVarint(arr) {
69859             if (this.type !== Pbf.Bytes) return arr.push(this.readSVarint());
69860             var end = readPackedEnd(this);
69861             arr = arr || [];
69862
69863             while (this.pos < end) {
69864               arr.push(this.readSVarint());
69865             }
69866
69867             return arr;
69868           },
69869           readPackedBoolean: function readPackedBoolean(arr) {
69870             if (this.type !== Pbf.Bytes) return arr.push(this.readBoolean());
69871             var end = readPackedEnd(this);
69872             arr = arr || [];
69873
69874             while (this.pos < end) {
69875               arr.push(this.readBoolean());
69876             }
69877
69878             return arr;
69879           },
69880           readPackedFloat: function readPackedFloat(arr) {
69881             if (this.type !== Pbf.Bytes) return arr.push(this.readFloat());
69882             var end = readPackedEnd(this);
69883             arr = arr || [];
69884
69885             while (this.pos < end) {
69886               arr.push(this.readFloat());
69887             }
69888
69889             return arr;
69890           },
69891           readPackedDouble: function readPackedDouble(arr) {
69892             if (this.type !== Pbf.Bytes) return arr.push(this.readDouble());
69893             var end = readPackedEnd(this);
69894             arr = arr || [];
69895
69896             while (this.pos < end) {
69897               arr.push(this.readDouble());
69898             }
69899
69900             return arr;
69901           },
69902           readPackedFixed32: function readPackedFixed32(arr) {
69903             if (this.type !== Pbf.Bytes) return arr.push(this.readFixed32());
69904             var end = readPackedEnd(this);
69905             arr = arr || [];
69906
69907             while (this.pos < end) {
69908               arr.push(this.readFixed32());
69909             }
69910
69911             return arr;
69912           },
69913           readPackedSFixed32: function readPackedSFixed32(arr) {
69914             if (this.type !== Pbf.Bytes) return arr.push(this.readSFixed32());
69915             var end = readPackedEnd(this);
69916             arr = arr || [];
69917
69918             while (this.pos < end) {
69919               arr.push(this.readSFixed32());
69920             }
69921
69922             return arr;
69923           },
69924           readPackedFixed64: function readPackedFixed64(arr) {
69925             if (this.type !== Pbf.Bytes) return arr.push(this.readFixed64());
69926             var end = readPackedEnd(this);
69927             arr = arr || [];
69928
69929             while (this.pos < end) {
69930               arr.push(this.readFixed64());
69931             }
69932
69933             return arr;
69934           },
69935           readPackedSFixed64: function readPackedSFixed64(arr) {
69936             if (this.type !== Pbf.Bytes) return arr.push(this.readSFixed64());
69937             var end = readPackedEnd(this);
69938             arr = arr || [];
69939
69940             while (this.pos < end) {
69941               arr.push(this.readSFixed64());
69942             }
69943
69944             return arr;
69945           },
69946           skip: function skip(val) {
69947             var type = val & 0x7;
69948             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);
69949           },
69950           // === WRITING =================================================================
69951           writeTag: function writeTag(tag, type) {
69952             this.writeVarint(tag << 3 | type);
69953           },
69954           realloc: function realloc(min) {
69955             var length = this.length || 16;
69956
69957             while (length < this.pos + min) {
69958               length *= 2;
69959             }
69960
69961             if (length !== this.length) {
69962               var buf = new Uint8Array(length);
69963               buf.set(this.buf);
69964               this.buf = buf;
69965               this.length = length;
69966             }
69967           },
69968           finish: function finish() {
69969             this.length = this.pos;
69970             this.pos = 0;
69971             return this.buf.subarray(0, this.length);
69972           },
69973           writeFixed32: function writeFixed32(val) {
69974             this.realloc(4);
69975             writeInt32(this.buf, val, this.pos);
69976             this.pos += 4;
69977           },
69978           writeSFixed32: function writeSFixed32(val) {
69979             this.realloc(4);
69980             writeInt32(this.buf, val, this.pos);
69981             this.pos += 4;
69982           },
69983           writeFixed64: function writeFixed64(val) {
69984             this.realloc(8);
69985             writeInt32(this.buf, val & -1, this.pos);
69986             writeInt32(this.buf, Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);
69987             this.pos += 8;
69988           },
69989           writeSFixed64: function writeSFixed64(val) {
69990             this.realloc(8);
69991             writeInt32(this.buf, val & -1, this.pos);
69992             writeInt32(this.buf, Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);
69993             this.pos += 8;
69994           },
69995           writeVarint: function writeVarint(val) {
69996             val = +val || 0;
69997
69998             if (val > 0xfffffff || val < 0) {
69999               writeBigVarint(val, this);
70000               return;
70001             }
70002
70003             this.realloc(4);
70004             this.buf[this.pos++] = val & 0x7f | (val > 0x7f ? 0x80 : 0);
70005             if (val <= 0x7f) return;
70006             this.buf[this.pos++] = (val >>>= 7) & 0x7f | (val > 0x7f ? 0x80 : 0);
70007             if (val <= 0x7f) return;
70008             this.buf[this.pos++] = (val >>>= 7) & 0x7f | (val > 0x7f ? 0x80 : 0);
70009             if (val <= 0x7f) return;
70010             this.buf[this.pos++] = val >>> 7 & 0x7f;
70011           },
70012           writeSVarint: function writeSVarint(val) {
70013             this.writeVarint(val < 0 ? -val * 2 - 1 : val * 2);
70014           },
70015           writeBoolean: function writeBoolean(val) {
70016             this.writeVarint(Boolean(val));
70017           },
70018           writeString: function writeString(str) {
70019             str = String(str);
70020             this.realloc(str.length * 4);
70021             this.pos++; // reserve 1 byte for short string length
70022
70023             var startPos = this.pos; // write the string directly to the buffer and see how much was written
70024
70025             this.pos = writeUtf8(this.buf, str, this.pos);
70026             var len = this.pos - startPos;
70027             if (len >= 0x80) makeRoomForExtraLength(startPos, len, this); // finally, write the message length in the reserved place and restore the position
70028
70029             this.pos = startPos - 1;
70030             this.writeVarint(len);
70031             this.pos += len;
70032           },
70033           writeFloat: function writeFloat(val) {
70034             this.realloc(4);
70035             ieee754.write(this.buf, val, this.pos, true, 23, 4);
70036             this.pos += 4;
70037           },
70038           writeDouble: function writeDouble(val) {
70039             this.realloc(8);
70040             ieee754.write(this.buf, val, this.pos, true, 52, 8);
70041             this.pos += 8;
70042           },
70043           writeBytes: function writeBytes(buffer) {
70044             var len = buffer.length;
70045             this.writeVarint(len);
70046             this.realloc(len);
70047
70048             for (var i = 0; i < len; i++) {
70049               this.buf[this.pos++] = buffer[i];
70050             }
70051           },
70052           writeRawMessage: function writeRawMessage(fn, obj) {
70053             this.pos++; // reserve 1 byte for short message length
70054             // write the message directly to the buffer and see how much was written
70055
70056             var startPos = this.pos;
70057             fn(obj, this);
70058             var len = this.pos - startPos;
70059             if (len >= 0x80) makeRoomForExtraLength(startPos, len, this); // finally, write the message length in the reserved place and restore the position
70060
70061             this.pos = startPos - 1;
70062             this.writeVarint(len);
70063             this.pos += len;
70064           },
70065           writeMessage: function writeMessage(tag, fn, obj) {
70066             this.writeTag(tag, Pbf.Bytes);
70067             this.writeRawMessage(fn, obj);
70068           },
70069           writePackedVarint: function writePackedVarint(tag, arr) {
70070             if (arr.length) this.writeMessage(tag, _writePackedVarint, arr);
70071           },
70072           writePackedSVarint: function writePackedSVarint(tag, arr) {
70073             if (arr.length) this.writeMessage(tag, _writePackedSVarint, arr);
70074           },
70075           writePackedBoolean: function writePackedBoolean(tag, arr) {
70076             if (arr.length) this.writeMessage(tag, _writePackedBoolean, arr);
70077           },
70078           writePackedFloat: function writePackedFloat(tag, arr) {
70079             if (arr.length) this.writeMessage(tag, _writePackedFloat, arr);
70080           },
70081           writePackedDouble: function writePackedDouble(tag, arr) {
70082             if (arr.length) this.writeMessage(tag, _writePackedDouble, arr);
70083           },
70084           writePackedFixed32: function writePackedFixed32(tag, arr) {
70085             if (arr.length) this.writeMessage(tag, _writePackedFixed, arr);
70086           },
70087           writePackedSFixed32: function writePackedSFixed32(tag, arr) {
70088             if (arr.length) this.writeMessage(tag, _writePackedSFixed, arr);
70089           },
70090           writePackedFixed64: function writePackedFixed64(tag, arr) {
70091             if (arr.length) this.writeMessage(tag, _writePackedFixed2, arr);
70092           },
70093           writePackedSFixed64: function writePackedSFixed64(tag, arr) {
70094             if (arr.length) this.writeMessage(tag, _writePackedSFixed2, arr);
70095           },
70096           writeBytesField: function writeBytesField(tag, buffer) {
70097             this.writeTag(tag, Pbf.Bytes);
70098             this.writeBytes(buffer);
70099           },
70100           writeFixed32Field: function writeFixed32Field(tag, val) {
70101             this.writeTag(tag, Pbf.Fixed32);
70102             this.writeFixed32(val);
70103           },
70104           writeSFixed32Field: function writeSFixed32Field(tag, val) {
70105             this.writeTag(tag, Pbf.Fixed32);
70106             this.writeSFixed32(val);
70107           },
70108           writeFixed64Field: function writeFixed64Field(tag, val) {
70109             this.writeTag(tag, Pbf.Fixed64);
70110             this.writeFixed64(val);
70111           },
70112           writeSFixed64Field: function writeSFixed64Field(tag, val) {
70113             this.writeTag(tag, Pbf.Fixed64);
70114             this.writeSFixed64(val);
70115           },
70116           writeVarintField: function writeVarintField(tag, val) {
70117             this.writeTag(tag, Pbf.Varint);
70118             this.writeVarint(val);
70119           },
70120           writeSVarintField: function writeSVarintField(tag, val) {
70121             this.writeTag(tag, Pbf.Varint);
70122             this.writeSVarint(val);
70123           },
70124           writeStringField: function writeStringField(tag, str) {
70125             this.writeTag(tag, Pbf.Bytes);
70126             this.writeString(str);
70127           },
70128           writeFloatField: function writeFloatField(tag, val) {
70129             this.writeTag(tag, Pbf.Fixed32);
70130             this.writeFloat(val);
70131           },
70132           writeDoubleField: function writeDoubleField(tag, val) {
70133             this.writeTag(tag, Pbf.Fixed64);
70134             this.writeDouble(val);
70135           },
70136           writeBooleanField: function writeBooleanField(tag, val) {
70137             this.writeVarintField(tag, Boolean(val));
70138           }
70139         };
70140
70141         function readVarintRemainder(l, s, p) {
70142           var buf = p.buf,
70143               h,
70144               b;
70145           b = buf[p.pos++];
70146           h = (b & 0x70) >> 4;
70147           if (b < 0x80) return toNum(l, h, s);
70148           b = buf[p.pos++];
70149           h |= (b & 0x7f) << 3;
70150           if (b < 0x80) return toNum(l, h, s);
70151           b = buf[p.pos++];
70152           h |= (b & 0x7f) << 10;
70153           if (b < 0x80) return toNum(l, h, s);
70154           b = buf[p.pos++];
70155           h |= (b & 0x7f) << 17;
70156           if (b < 0x80) return toNum(l, h, s);
70157           b = buf[p.pos++];
70158           h |= (b & 0x7f) << 24;
70159           if (b < 0x80) return toNum(l, h, s);
70160           b = buf[p.pos++];
70161           h |= (b & 0x01) << 31;
70162           if (b < 0x80) return toNum(l, h, s);
70163           throw new Error('Expected varint not more than 10 bytes');
70164         }
70165
70166         function readPackedEnd(pbf) {
70167           return pbf.type === Pbf.Bytes ? pbf.readVarint() + pbf.pos : pbf.pos + 1;
70168         }
70169
70170         function toNum(low, high, isSigned) {
70171           if (isSigned) {
70172             return high * 0x100000000 + (low >>> 0);
70173           }
70174
70175           return (high >>> 0) * 0x100000000 + (low >>> 0);
70176         }
70177
70178         function writeBigVarint(val, pbf) {
70179           var low, high;
70180
70181           if (val >= 0) {
70182             low = val % 0x100000000 | 0;
70183             high = val / 0x100000000 | 0;
70184           } else {
70185             low = ~(-val % 0x100000000);
70186             high = ~(-val / 0x100000000);
70187
70188             if (low ^ 0xffffffff) {
70189               low = low + 1 | 0;
70190             } else {
70191               low = 0;
70192               high = high + 1 | 0;
70193             }
70194           }
70195
70196           if (val >= 0x10000000000000000 || val < -0x10000000000000000) {
70197             throw new Error('Given varint doesn\'t fit into 10 bytes');
70198           }
70199
70200           pbf.realloc(10);
70201           writeBigVarintLow(low, high, pbf);
70202           writeBigVarintHigh(high, pbf);
70203         }
70204
70205         function writeBigVarintLow(low, high, pbf) {
70206           pbf.buf[pbf.pos++] = low & 0x7f | 0x80;
70207           low >>>= 7;
70208           pbf.buf[pbf.pos++] = low & 0x7f | 0x80;
70209           low >>>= 7;
70210           pbf.buf[pbf.pos++] = low & 0x7f | 0x80;
70211           low >>>= 7;
70212           pbf.buf[pbf.pos++] = low & 0x7f | 0x80;
70213           low >>>= 7;
70214           pbf.buf[pbf.pos] = low & 0x7f;
70215         }
70216
70217         function writeBigVarintHigh(high, pbf) {
70218           var lsb = (high & 0x07) << 4;
70219           pbf.buf[pbf.pos++] |= lsb | ((high >>>= 3) ? 0x80 : 0);
70220           if (!high) return;
70221           pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0);
70222           if (!high) return;
70223           pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0);
70224           if (!high) return;
70225           pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0);
70226           if (!high) return;
70227           pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0);
70228           if (!high) return;
70229           pbf.buf[pbf.pos++] = high & 0x7f;
70230         }
70231
70232         function makeRoomForExtraLength(startPos, len, pbf) {
70233           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
70234
70235           pbf.realloc(extraLen);
70236
70237           for (var i = pbf.pos - 1; i >= startPos; i--) {
70238             pbf.buf[i + extraLen] = pbf.buf[i];
70239           }
70240         }
70241
70242         function _writePackedVarint(arr, pbf) {
70243           for (var i = 0; i < arr.length; i++) {
70244             pbf.writeVarint(arr[i]);
70245           }
70246         }
70247
70248         function _writePackedSVarint(arr, pbf) {
70249           for (var i = 0; i < arr.length; i++) {
70250             pbf.writeSVarint(arr[i]);
70251           }
70252         }
70253
70254         function _writePackedFloat(arr, pbf) {
70255           for (var i = 0; i < arr.length; i++) {
70256             pbf.writeFloat(arr[i]);
70257           }
70258         }
70259
70260         function _writePackedDouble(arr, pbf) {
70261           for (var i = 0; i < arr.length; i++) {
70262             pbf.writeDouble(arr[i]);
70263           }
70264         }
70265
70266         function _writePackedBoolean(arr, pbf) {
70267           for (var i = 0; i < arr.length; i++) {
70268             pbf.writeBoolean(arr[i]);
70269           }
70270         }
70271
70272         function _writePackedFixed(arr, pbf) {
70273           for (var i = 0; i < arr.length; i++) {
70274             pbf.writeFixed32(arr[i]);
70275           }
70276         }
70277
70278         function _writePackedSFixed(arr, pbf) {
70279           for (var i = 0; i < arr.length; i++) {
70280             pbf.writeSFixed32(arr[i]);
70281           }
70282         }
70283
70284         function _writePackedFixed2(arr, pbf) {
70285           for (var i = 0; i < arr.length; i++) {
70286             pbf.writeFixed64(arr[i]);
70287           }
70288         }
70289
70290         function _writePackedSFixed2(arr, pbf) {
70291           for (var i = 0; i < arr.length; i++) {
70292             pbf.writeSFixed64(arr[i]);
70293           }
70294         } // Buffer code below from https://github.com/feross/buffer, MIT-licensed
70295
70296
70297         function readUInt32(buf, pos) {
70298           return (buf[pos] | buf[pos + 1] << 8 | buf[pos + 2] << 16) + buf[pos + 3] * 0x1000000;
70299         }
70300
70301         function writeInt32(buf, val, pos) {
70302           buf[pos] = val;
70303           buf[pos + 1] = val >>> 8;
70304           buf[pos + 2] = val >>> 16;
70305           buf[pos + 3] = val >>> 24;
70306         }
70307
70308         function readInt32(buf, pos) {
70309           return (buf[pos] | buf[pos + 1] << 8 | buf[pos + 2] << 16) + (buf[pos + 3] << 24);
70310         }
70311
70312         function readUtf8(buf, pos, end) {
70313           var str = '';
70314           var i = pos;
70315
70316           while (i < end) {
70317             var b0 = buf[i];
70318             var c = null; // codepoint
70319
70320             var bytesPerSequence = b0 > 0xEF ? 4 : b0 > 0xDF ? 3 : b0 > 0xBF ? 2 : 1;
70321             if (i + bytesPerSequence > end) break;
70322             var b1, b2, b3;
70323
70324             if (bytesPerSequence === 1) {
70325               if (b0 < 0x80) {
70326                 c = b0;
70327               }
70328             } else if (bytesPerSequence === 2) {
70329               b1 = buf[i + 1];
70330
70331               if ((b1 & 0xC0) === 0x80) {
70332                 c = (b0 & 0x1F) << 0x6 | b1 & 0x3F;
70333
70334                 if (c <= 0x7F) {
70335                   c = null;
70336                 }
70337               }
70338             } else if (bytesPerSequence === 3) {
70339               b1 = buf[i + 1];
70340               b2 = buf[i + 2];
70341
70342               if ((b1 & 0xC0) === 0x80 && (b2 & 0xC0) === 0x80) {
70343                 c = (b0 & 0xF) << 0xC | (b1 & 0x3F) << 0x6 | b2 & 0x3F;
70344
70345                 if (c <= 0x7FF || c >= 0xD800 && c <= 0xDFFF) {
70346                   c = null;
70347                 }
70348               }
70349             } else if (bytesPerSequence === 4) {
70350               b1 = buf[i + 1];
70351               b2 = buf[i + 2];
70352               b3 = buf[i + 3];
70353
70354               if ((b1 & 0xC0) === 0x80 && (b2 & 0xC0) === 0x80 && (b3 & 0xC0) === 0x80) {
70355                 c = (b0 & 0xF) << 0x12 | (b1 & 0x3F) << 0xC | (b2 & 0x3F) << 0x6 | b3 & 0x3F;
70356
70357                 if (c <= 0xFFFF || c >= 0x110000) {
70358                   c = null;
70359                 }
70360               }
70361             }
70362
70363             if (c === null) {
70364               c = 0xFFFD;
70365               bytesPerSequence = 1;
70366             } else if (c > 0xFFFF) {
70367               c -= 0x10000;
70368               str += String.fromCharCode(c >>> 10 & 0x3FF | 0xD800);
70369               c = 0xDC00 | c & 0x3FF;
70370             }
70371
70372             str += String.fromCharCode(c);
70373             i += bytesPerSequence;
70374           }
70375
70376           return str;
70377         }
70378
70379         function readUtf8TextDecoder(buf, pos, end) {
70380           return utf8TextDecoder.decode(buf.subarray(pos, end));
70381         }
70382
70383         function writeUtf8(buf, str, pos) {
70384           for (var i = 0, c, lead; i < str.length; i++) {
70385             c = str.charCodeAt(i); // code point
70386
70387             if (c > 0xD7FF && c < 0xE000) {
70388               if (lead) {
70389                 if (c < 0xDC00) {
70390                   buf[pos++] = 0xEF;
70391                   buf[pos++] = 0xBF;
70392                   buf[pos++] = 0xBD;
70393                   lead = c;
70394                   continue;
70395                 } else {
70396                   c = lead - 0xD800 << 10 | c - 0xDC00 | 0x10000;
70397                   lead = null;
70398                 }
70399               } else {
70400                 if (c > 0xDBFF || i + 1 === str.length) {
70401                   buf[pos++] = 0xEF;
70402                   buf[pos++] = 0xBF;
70403                   buf[pos++] = 0xBD;
70404                 } else {
70405                   lead = c;
70406                 }
70407
70408                 continue;
70409               }
70410             } else if (lead) {
70411               buf[pos++] = 0xEF;
70412               buf[pos++] = 0xBF;
70413               buf[pos++] = 0xBD;
70414               lead = null;
70415             }
70416
70417             if (c < 0x80) {
70418               buf[pos++] = c;
70419             } else {
70420               if (c < 0x800) {
70421                 buf[pos++] = c >> 0x6 | 0xC0;
70422               } else {
70423                 if (c < 0x10000) {
70424                   buf[pos++] = c >> 0xC | 0xE0;
70425                 } else {
70426                   buf[pos++] = c >> 0x12 | 0xF0;
70427                   buf[pos++] = c >> 0xC & 0x3F | 0x80;
70428                 }
70429
70430                 buf[pos++] = c >> 0x6 & 0x3F | 0x80;
70431               }
70432
70433               buf[pos++] = c & 0x3F | 0x80;
70434             }
70435           }
70436
70437           return pos;
70438         }
70439
70440         var vectorTile = {};
70441
70442         var pointGeometry = Point$1;
70443         /**
70444          * A standalone point geometry with useful accessor, comparison, and
70445          * modification methods.
70446          *
70447          * @class Point
70448          * @param {Number} x the x-coordinate. this could be longitude or screen
70449          * pixels, or any other sort of unit.
70450          * @param {Number} y the y-coordinate. this could be latitude or screen
70451          * pixels, or any other sort of unit.
70452          * @example
70453          * var point = new Point(-77, 38);
70454          */
70455
70456         function Point$1(x, y) {
70457           this.x = x;
70458           this.y = y;
70459         }
70460
70461         Point$1.prototype = {
70462           /**
70463            * Clone this point, returning a new point that can be modified
70464            * without affecting the old one.
70465            * @return {Point} the clone
70466            */
70467           clone: function clone() {
70468             return new Point$1(this.x, this.y);
70469           },
70470
70471           /**
70472            * Add this point's x & y coordinates to another point,
70473            * yielding a new point.
70474            * @param {Point} p the other point
70475            * @return {Point} output point
70476            */
70477           add: function add(p) {
70478             return this.clone()._add(p);
70479           },
70480
70481           /**
70482            * Subtract this point's x & y coordinates to from point,
70483            * yielding a new point.
70484            * @param {Point} p the other point
70485            * @return {Point} output point
70486            */
70487           sub: function sub(p) {
70488             return this.clone()._sub(p);
70489           },
70490
70491           /**
70492            * Multiply this point's x & y coordinates by point,
70493            * yielding a new point.
70494            * @param {Point} p the other point
70495            * @return {Point} output point
70496            */
70497           multByPoint: function multByPoint(p) {
70498             return this.clone()._multByPoint(p);
70499           },
70500
70501           /**
70502            * Divide this point's x & y coordinates by point,
70503            * yielding a new point.
70504            * @param {Point} p the other point
70505            * @return {Point} output point
70506            */
70507           divByPoint: function divByPoint(p) {
70508             return this.clone()._divByPoint(p);
70509           },
70510
70511           /**
70512            * Multiply this point's x & y coordinates by a factor,
70513            * yielding a new point.
70514            * @param {Point} k factor
70515            * @return {Point} output point
70516            */
70517           mult: function mult(k) {
70518             return this.clone()._mult(k);
70519           },
70520
70521           /**
70522            * Divide this point's x & y coordinates by a factor,
70523            * yielding a new point.
70524            * @param {Point} k factor
70525            * @return {Point} output point
70526            */
70527           div: function div(k) {
70528             return this.clone()._div(k);
70529           },
70530
70531           /**
70532            * Rotate this point around the 0, 0 origin by an angle a,
70533            * given in radians
70534            * @param {Number} a angle to rotate around, in radians
70535            * @return {Point} output point
70536            */
70537           rotate: function rotate(a) {
70538             return this.clone()._rotate(a);
70539           },
70540
70541           /**
70542            * Rotate this point around p point by an angle a,
70543            * given in radians
70544            * @param {Number} a angle to rotate around, in radians
70545            * @param {Point} p Point to rotate around
70546            * @return {Point} output point
70547            */
70548           rotateAround: function rotateAround(a, p) {
70549             return this.clone()._rotateAround(a, p);
70550           },
70551
70552           /**
70553            * Multiply this point by a 4x1 transformation matrix
70554            * @param {Array<Number>} m transformation matrix
70555            * @return {Point} output point
70556            */
70557           matMult: function matMult(m) {
70558             return this.clone()._matMult(m);
70559           },
70560
70561           /**
70562            * Calculate this point but as a unit vector from 0, 0, meaning
70563            * that the distance from the resulting point to the 0, 0
70564            * coordinate will be equal to 1 and the angle from the resulting
70565            * point to the 0, 0 coordinate will be the same as before.
70566            * @return {Point} unit vector point
70567            */
70568           unit: function unit() {
70569             return this.clone()._unit();
70570           },
70571
70572           /**
70573            * Compute a perpendicular point, where the new y coordinate
70574            * is the old x coordinate and the new x coordinate is the old y
70575            * coordinate multiplied by -1
70576            * @return {Point} perpendicular point
70577            */
70578           perp: function perp() {
70579             return this.clone()._perp();
70580           },
70581
70582           /**
70583            * Return a version of this point with the x & y coordinates
70584            * rounded to integers.
70585            * @return {Point} rounded point
70586            */
70587           round: function round() {
70588             return this.clone()._round();
70589           },
70590
70591           /**
70592            * Return the magitude of this point: this is the Euclidean
70593            * distance from the 0, 0 coordinate to this point's x and y
70594            * coordinates.
70595            * @return {Number} magnitude
70596            */
70597           mag: function mag() {
70598             return Math.sqrt(this.x * this.x + this.y * this.y);
70599           },
70600
70601           /**
70602            * Judge whether this point is equal to another point, returning
70603            * true or false.
70604            * @param {Point} other the other point
70605            * @return {boolean} whether the points are equal
70606            */
70607           equals: function equals(other) {
70608             return this.x === other.x && this.y === other.y;
70609           },
70610
70611           /**
70612            * Calculate the distance from this point to another point
70613            * @param {Point} p the other point
70614            * @return {Number} distance
70615            */
70616           dist: function dist(p) {
70617             return Math.sqrt(this.distSqr(p));
70618           },
70619
70620           /**
70621            * Calculate the distance from this point to another point,
70622            * without the square root step. Useful if you're comparing
70623            * relative distances.
70624            * @param {Point} p the other point
70625            * @return {Number} distance
70626            */
70627           distSqr: function distSqr(p) {
70628             var dx = p.x - this.x,
70629                 dy = p.y - this.y;
70630             return dx * dx + dy * dy;
70631           },
70632
70633           /**
70634            * Get the angle from the 0, 0 coordinate to this point, in radians
70635            * coordinates.
70636            * @return {Number} angle
70637            */
70638           angle: function angle() {
70639             return Math.atan2(this.y, this.x);
70640           },
70641
70642           /**
70643            * Get the angle from this point to another point, in radians
70644            * @param {Point} b the other point
70645            * @return {Number} angle
70646            */
70647           angleTo: function angleTo(b) {
70648             return Math.atan2(this.y - b.y, this.x - b.x);
70649           },
70650
70651           /**
70652            * Get the angle between this point and another point, in radians
70653            * @param {Point} b the other point
70654            * @return {Number} angle
70655            */
70656           angleWith: function angleWith(b) {
70657             return this.angleWithSep(b.x, b.y);
70658           },
70659
70660           /*
70661            * Find the angle of the two vectors, solving the formula for
70662            * the cross product a x b = |a||b|sin(θ) for θ.
70663            * @param {Number} x the x-coordinate
70664            * @param {Number} y the y-coordinate
70665            * @return {Number} the angle in radians
70666            */
70667           angleWithSep: function angleWithSep(x, y) {
70668             return Math.atan2(this.x * y - this.y * x, this.x * x + this.y * y);
70669           },
70670           _matMult: function _matMult(m) {
70671             var x = m[0] * this.x + m[1] * this.y,
70672                 y = m[2] * this.x + m[3] * this.y;
70673             this.x = x;
70674             this.y = y;
70675             return this;
70676           },
70677           _add: function _add(p) {
70678             this.x += p.x;
70679             this.y += p.y;
70680             return this;
70681           },
70682           _sub: function _sub(p) {
70683             this.x -= p.x;
70684             this.y -= p.y;
70685             return this;
70686           },
70687           _mult: function _mult(k) {
70688             this.x *= k;
70689             this.y *= k;
70690             return this;
70691           },
70692           _div: function _div(k) {
70693             this.x /= k;
70694             this.y /= k;
70695             return this;
70696           },
70697           _multByPoint: function _multByPoint(p) {
70698             this.x *= p.x;
70699             this.y *= p.y;
70700             return this;
70701           },
70702           _divByPoint: function _divByPoint(p) {
70703             this.x /= p.x;
70704             this.y /= p.y;
70705             return this;
70706           },
70707           _unit: function _unit() {
70708             this._div(this.mag());
70709
70710             return this;
70711           },
70712           _perp: function _perp() {
70713             var y = this.y;
70714             this.y = this.x;
70715             this.x = -y;
70716             return this;
70717           },
70718           _rotate: function _rotate(angle) {
70719             var cos = Math.cos(angle),
70720                 sin = Math.sin(angle),
70721                 x = cos * this.x - sin * this.y,
70722                 y = sin * this.x + cos * this.y;
70723             this.x = x;
70724             this.y = y;
70725             return this;
70726           },
70727           _rotateAround: function _rotateAround(angle, p) {
70728             var cos = Math.cos(angle),
70729                 sin = Math.sin(angle),
70730                 x = p.x + cos * (this.x - p.x) - sin * (this.y - p.y),
70731                 y = p.y + sin * (this.x - p.x) + cos * (this.y - p.y);
70732             this.x = x;
70733             this.y = y;
70734             return this;
70735           },
70736           _round: function _round() {
70737             this.x = Math.round(this.x);
70738             this.y = Math.round(this.y);
70739             return this;
70740           }
70741         };
70742         /**
70743          * Construct a point from an array if necessary, otherwise if the input
70744          * is already a Point, or an unknown type, return it unchanged
70745          * @param {Array<Number>|Point|*} a any kind of input value
70746          * @return {Point} constructed point, or passed-through value.
70747          * @example
70748          * // this
70749          * var point = Point.convert([0, 1]);
70750          * // is equivalent to
70751          * var point = new Point(0, 1);
70752          */
70753
70754         Point$1.convert = function (a) {
70755           if (a instanceof Point$1) {
70756             return a;
70757           }
70758
70759           if (Array.isArray(a)) {
70760             return new Point$1(a[0], a[1]);
70761           }
70762
70763           return a;
70764         };
70765
70766         var Point = pointGeometry;
70767         var vectortilefeature = VectorTileFeature$1;
70768
70769         function VectorTileFeature$1(pbf, end, extent, keys, values) {
70770           // Public
70771           this.properties = {};
70772           this.extent = extent;
70773           this.type = 0; // Private
70774
70775           this._pbf = pbf;
70776           this._geometry = -1;
70777           this._keys = keys;
70778           this._values = values;
70779           pbf.readFields(readFeature, this, end);
70780         }
70781
70782         function readFeature(tag, feature, pbf) {
70783           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;
70784         }
70785
70786         function readTag(pbf, feature) {
70787           var end = pbf.readVarint() + pbf.pos;
70788
70789           while (pbf.pos < end) {
70790             var key = feature._keys[pbf.readVarint()],
70791                 value = feature._values[pbf.readVarint()];
70792
70793             feature.properties[key] = value;
70794           }
70795         }
70796
70797         VectorTileFeature$1.types = ['Unknown', 'Point', 'LineString', 'Polygon'];
70798
70799         VectorTileFeature$1.prototype.loadGeometry = function () {
70800           var pbf = this._pbf;
70801           pbf.pos = this._geometry;
70802           var end = pbf.readVarint() + pbf.pos,
70803               cmd = 1,
70804               length = 0,
70805               x = 0,
70806               y = 0,
70807               lines = [],
70808               line;
70809
70810           while (pbf.pos < end) {
70811             if (length <= 0) {
70812               var cmdLen = pbf.readVarint();
70813               cmd = cmdLen & 0x7;
70814               length = cmdLen >> 3;
70815             }
70816
70817             length--;
70818
70819             if (cmd === 1 || cmd === 2) {
70820               x += pbf.readSVarint();
70821               y += pbf.readSVarint();
70822
70823               if (cmd === 1) {
70824                 // moveTo
70825                 if (line) lines.push(line);
70826                 line = [];
70827               }
70828
70829               line.push(new Point(x, y));
70830             } else if (cmd === 7) {
70831               // Workaround for https://github.com/mapbox/mapnik-vector-tile/issues/90
70832               if (line) {
70833                 line.push(line[0].clone()); // closePolygon
70834               }
70835             } else {
70836               throw new Error('unknown command ' + cmd);
70837             }
70838           }
70839
70840           if (line) lines.push(line);
70841           return lines;
70842         };
70843
70844         VectorTileFeature$1.prototype.bbox = function () {
70845           var pbf = this._pbf;
70846           pbf.pos = this._geometry;
70847           var end = pbf.readVarint() + pbf.pos,
70848               cmd = 1,
70849               length = 0,
70850               x = 0,
70851               y = 0,
70852               x1 = Infinity,
70853               x2 = -Infinity,
70854               y1 = Infinity,
70855               y2 = -Infinity;
70856
70857           while (pbf.pos < end) {
70858             if (length <= 0) {
70859               var cmdLen = pbf.readVarint();
70860               cmd = cmdLen & 0x7;
70861               length = cmdLen >> 3;
70862             }
70863
70864             length--;
70865
70866             if (cmd === 1 || cmd === 2) {
70867               x += pbf.readSVarint();
70868               y += pbf.readSVarint();
70869               if (x < x1) x1 = x;
70870               if (x > x2) x2 = x;
70871               if (y < y1) y1 = y;
70872               if (y > y2) y2 = y;
70873             } else if (cmd !== 7) {
70874               throw new Error('unknown command ' + cmd);
70875             }
70876           }
70877
70878           return [x1, y1, x2, y2];
70879         };
70880
70881         VectorTileFeature$1.prototype.toGeoJSON = function (x, y, z) {
70882           var size = this.extent * Math.pow(2, z),
70883               x0 = this.extent * x,
70884               y0 = this.extent * y,
70885               coords = this.loadGeometry(),
70886               type = VectorTileFeature$1.types[this.type],
70887               i,
70888               j;
70889
70890           function project(line) {
70891             for (var j = 0; j < line.length; j++) {
70892               var p = line[j],
70893                   y2 = 180 - (p.y + y0) * 360 / size;
70894               line[j] = [(p.x + x0) * 360 / size - 180, 360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90];
70895             }
70896           }
70897
70898           switch (this.type) {
70899             case 1:
70900               var points = [];
70901
70902               for (i = 0; i < coords.length; i++) {
70903                 points[i] = coords[i][0];
70904               }
70905
70906               coords = points;
70907               project(coords);
70908               break;
70909
70910             case 2:
70911               for (i = 0; i < coords.length; i++) {
70912                 project(coords[i]);
70913               }
70914
70915               break;
70916
70917             case 3:
70918               coords = classifyRings(coords);
70919
70920               for (i = 0; i < coords.length; i++) {
70921                 for (j = 0; j < coords[i].length; j++) {
70922                   project(coords[i][j]);
70923                 }
70924               }
70925
70926               break;
70927           }
70928
70929           if (coords.length === 1) {
70930             coords = coords[0];
70931           } else {
70932             type = 'Multi' + type;
70933           }
70934
70935           var result = {
70936             type: "Feature",
70937             geometry: {
70938               type: type,
70939               coordinates: coords
70940             },
70941             properties: this.properties
70942           };
70943
70944           if ('id' in this) {
70945             result.id = this.id;
70946           }
70947
70948           return result;
70949         }; // classifies an array of rings into polygons with outer rings and holes
70950
70951
70952         function classifyRings(rings) {
70953           var len = rings.length;
70954           if (len <= 1) return [rings];
70955           var polygons = [],
70956               polygon,
70957               ccw;
70958
70959           for (var i = 0; i < len; i++) {
70960             var area = signedArea(rings[i]);
70961             if (area === 0) continue;
70962             if (ccw === undefined) ccw = area < 0;
70963
70964             if (ccw === area < 0) {
70965               if (polygon) polygons.push(polygon);
70966               polygon = [rings[i]];
70967             } else {
70968               polygon.push(rings[i]);
70969             }
70970           }
70971
70972           if (polygon) polygons.push(polygon);
70973           return polygons;
70974         }
70975
70976         function signedArea(ring) {
70977           var sum = 0;
70978
70979           for (var i = 0, len = ring.length, j = len - 1, p1, p2; i < len; j = i++) {
70980             p1 = ring[i];
70981             p2 = ring[j];
70982             sum += (p2.x - p1.x) * (p1.y + p2.y);
70983           }
70984
70985           return sum;
70986         }
70987
70988         var VectorTileFeature = vectortilefeature;
70989         var vectortilelayer = VectorTileLayer$1;
70990
70991         function VectorTileLayer$1(pbf, end) {
70992           // Public
70993           this.version = 1;
70994           this.name = null;
70995           this.extent = 4096;
70996           this.length = 0; // Private
70997
70998           this._pbf = pbf;
70999           this._keys = [];
71000           this._values = [];
71001           this._features = [];
71002           pbf.readFields(readLayer, this, end);
71003           this.length = this._features.length;
71004         }
71005
71006         function readLayer(tag, layer, pbf) {
71007           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));
71008         }
71009
71010         function readValueMessage(pbf) {
71011           var value = null,
71012               end = pbf.readVarint() + pbf.pos;
71013
71014           while (pbf.pos < end) {
71015             var tag = pbf.readVarint() >> 3;
71016             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;
71017           }
71018
71019           return value;
71020         } // return feature `i` from this layer as a `VectorTileFeature`
71021
71022
71023         VectorTileLayer$1.prototype.feature = function (i) {
71024           if (i < 0 || i >= this._features.length) throw new Error('feature index out of bounds');
71025           this._pbf.pos = this._features[i];
71026
71027           var end = this._pbf.readVarint() + this._pbf.pos;
71028
71029           return new VectorTileFeature(this._pbf, end, this.extent, this._keys, this._values);
71030         };
71031
71032         var VectorTileLayer = vectortilelayer;
71033         var vectortile = VectorTile$1;
71034
71035         function VectorTile$1(pbf, end) {
71036           this.layers = pbf.readFields(readTile, {}, end);
71037         }
71038
71039         function readTile(tag, layers, pbf) {
71040           if (tag === 3) {
71041             var layer = new VectorTileLayer(pbf, pbf.readVarint() + pbf.pos);
71042             if (layer.length) layers[layer.name] = layer;
71043           }
71044         }
71045
71046         var VectorTile = vectorTile.VectorTile = vectortile;
71047         vectorTile.VectorTileFeature = vectortilefeature;
71048         vectorTile.VectorTileLayer = vectortilelayer;
71049
71050         var accessToken = 'MLY|4100327730013843|5bb78b81720791946a9a7b956c57b7cf';
71051         var apiUrl = 'https://graph.mapillary.com/';
71052         var baseTileUrl = 'https://tiles.mapillary.com/maps/vtp';
71053         var mapFeatureTileUrl = "".concat(baseTileUrl, "/mly_map_feature_point/2/{z}/{x}/{y}?access_token=").concat(accessToken);
71054         var tileUrl = "".concat(baseTileUrl, "/mly1_public/2/{z}/{x}/{y}?access_token=").concat(accessToken);
71055         var trafficSignTileUrl = "".concat(baseTileUrl, "/mly_map_feature_traffic_sign/2/{z}/{x}/{y}?access_token=").concat(accessToken);
71056         var viewercss = 'mapillary-js/mapillary.css';
71057         var viewerjs = 'mapillary-js/mapillary.js';
71058         var minZoom$1 = 14;
71059         var dispatch$4 = dispatch$8('change', 'loadedImages', 'loadedSigns', 'loadedMapFeatures', 'bearingChanged', 'imageChanged');
71060
71061         var _loadViewerPromise$2;
71062
71063         var _mlyActiveImage;
71064
71065         var _mlyCache;
71066
71067         var _mlyFallback = false;
71068
71069         var _mlyHighlightedDetection;
71070
71071         var _mlyShowFeatureDetections = false;
71072         var _mlyShowSignDetections = false;
71073
71074         var _mlyViewer;
71075
71076         var _mlyViewerFilter = ['all']; // Load all data for the specified type from Mapillary vector tiles
71077
71078         function loadTiles$2(which, url, maxZoom, projection) {
71079           var tiler = utilTiler().zoomExtent([minZoom$1, maxZoom]).skipNullIsland(true);
71080           var tiles = tiler.getTiles(projection);
71081           tiles.forEach(function (tile) {
71082             loadTile$1(which, url, tile);
71083           });
71084         } // Load all data for the specified type from one vector tile
71085
71086
71087         function loadTile$1(which, url, tile) {
71088           var cache = _mlyCache.requests;
71089           var tileId = "".concat(tile.id, "-").concat(which);
71090           if (cache.loaded[tileId] || cache.inflight[tileId]) return;
71091           var controller = new AbortController();
71092           cache.inflight[tileId] = controller;
71093           var requestUrl = url.replace('{x}', tile.xyz[0]).replace('{y}', tile.xyz[1]).replace('{z}', tile.xyz[2]);
71094           fetch(requestUrl, {
71095             signal: controller.signal
71096           }).then(function (response) {
71097             if (!response.ok) {
71098               throw new Error(response.status + ' ' + response.statusText);
71099             }
71100
71101             cache.loaded[tileId] = true;
71102             delete cache.inflight[tileId];
71103             return response.arrayBuffer();
71104           }).then(function (data) {
71105             if (!data) {
71106               throw new Error('No Data');
71107             }
71108
71109             loadTileDataToCache(data, tile, which);
71110
71111             if (which === 'images') {
71112               dispatch$4.call('loadedImages');
71113             } else if (which === 'signs') {
71114               dispatch$4.call('loadedSigns');
71115             } else if (which === 'points') {
71116               dispatch$4.call('loadedMapFeatures');
71117             }
71118           })["catch"](function () {
71119             cache.loaded[tileId] = true;
71120             delete cache.inflight[tileId];
71121           });
71122         } // Load the data from the vector tile into cache
71123
71124
71125         function loadTileDataToCache(data, tile, which) {
71126           var vectorTile = new VectorTile(new pbf(data));
71127           var features, cache, layer, i, feature, loc, d;
71128
71129           if (vectorTile.layers.hasOwnProperty('image')) {
71130             features = [];
71131             cache = _mlyCache.images;
71132             layer = vectorTile.layers.image;
71133
71134             for (i = 0; i < layer.length; i++) {
71135               feature = layer.feature(i).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
71136               loc = feature.geometry.coordinates;
71137               d = {
71138                 loc: loc,
71139                 captured_at: feature.properties.captured_at,
71140                 ca: feature.properties.compass_angle,
71141                 id: feature.properties.id,
71142                 is_pano: feature.properties.is_pano,
71143                 sequence_id: feature.properties.sequence_id
71144               };
71145               cache.forImageId[d.id] = d;
71146               features.push({
71147                 minX: loc[0],
71148                 minY: loc[1],
71149                 maxX: loc[0],
71150                 maxY: loc[1],
71151                 data: d
71152               });
71153             }
71154
71155             if (cache.rtree) {
71156               cache.rtree.load(features);
71157             }
71158           }
71159
71160           if (vectorTile.layers.hasOwnProperty('sequence')) {
71161             features = [];
71162             cache = _mlyCache.sequences;
71163             layer = vectorTile.layers.sequence;
71164
71165             for (i = 0; i < layer.length; i++) {
71166               feature = layer.feature(i).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
71167
71168               if (cache.lineString[feature.properties.id]) {
71169                 cache.lineString[feature.properties.id].push(feature);
71170               } else {
71171                 cache.lineString[feature.properties.id] = [feature];
71172               }
71173             }
71174           }
71175
71176           if (vectorTile.layers.hasOwnProperty('point')) {
71177             features = [];
71178             cache = _mlyCache[which];
71179             layer = vectorTile.layers.point;
71180
71181             for (i = 0; i < layer.length; i++) {
71182               feature = layer.feature(i).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
71183               loc = feature.geometry.coordinates;
71184               d = {
71185                 loc: loc,
71186                 id: feature.properties.id,
71187                 first_seen_at: feature.properties.first_seen_at,
71188                 last_seen_at: feature.properties.last_seen_at,
71189                 value: feature.properties.value
71190               };
71191               features.push({
71192                 minX: loc[0],
71193                 minY: loc[1],
71194                 maxX: loc[0],
71195                 maxY: loc[1],
71196                 data: d
71197               });
71198             }
71199
71200             if (cache.rtree) {
71201               cache.rtree.load(features);
71202             }
71203           }
71204
71205           if (vectorTile.layers.hasOwnProperty('traffic_sign')) {
71206             features = [];
71207             cache = _mlyCache[which];
71208             layer = vectorTile.layers.traffic_sign;
71209
71210             for (i = 0; i < layer.length; i++) {
71211               feature = layer.feature(i).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
71212               loc = feature.geometry.coordinates;
71213               d = {
71214                 loc: loc,
71215                 id: feature.properties.id,
71216                 first_seen_at: feature.properties.first_seen_at,
71217                 last_seen_at: feature.properties.last_seen_at,
71218                 value: feature.properties.value
71219               };
71220               features.push({
71221                 minX: loc[0],
71222                 minY: loc[1],
71223                 maxX: loc[0],
71224                 maxY: loc[1],
71225                 data: d
71226               });
71227             }
71228
71229             if (cache.rtree) {
71230               cache.rtree.load(features);
71231             }
71232           }
71233         } // Get data from the API
71234
71235
71236         function loadData(url) {
71237           return fetch(url).then(function (response) {
71238             if (!response.ok) {
71239               throw new Error(response.status + ' ' + response.statusText);
71240             }
71241
71242             return response.json();
71243           }).then(function (result) {
71244             if (!result) {
71245               return [];
71246             }
71247
71248             return result.data || [];
71249           });
71250         } // Partition viewport into higher zoom tiles
71251
71252
71253         function partitionViewport$2(projection) {
71254           var z = geoScaleToZoom(projection.scale());
71255           var z2 = Math.ceil(z * 2) / 2 + 2.5; // round to next 0.5 and add 2.5
71256
71257           var tiler = utilTiler().zoomExtent([z2, z2]);
71258           return tiler.getTiles(projection).map(function (tile) {
71259             return tile.extent;
71260           });
71261         } // Return no more than `limit` results per partition.
71262
71263
71264         function searchLimited$2(limit, projection, rtree) {
71265           limit = limit || 5;
71266           return partitionViewport$2(projection).reduce(function (result, extent) {
71267             var found = rtree.search(extent.bbox()).slice(0, limit).map(function (d) {
71268               return d.data;
71269             });
71270             return found.length ? result.concat(found) : result;
71271           }, []);
71272         }
71273
71274         var serviceMapillary = {
71275           // Initialize Mapillary
71276           init: function init() {
71277             if (!_mlyCache) {
71278               this.reset();
71279             }
71280
71281             this.event = utilRebind(this, dispatch$4, 'on');
71282           },
71283           // Reset cache and state
71284           reset: function reset() {
71285             if (_mlyCache) {
71286               Object.values(_mlyCache.requests.inflight).forEach(function (request) {
71287                 request.abort();
71288               });
71289             }
71290
71291             _mlyCache = {
71292               images: {
71293                 rtree: new RBush(),
71294                 forImageId: {}
71295               },
71296               image_detections: {
71297                 forImageId: {}
71298               },
71299               signs: {
71300                 rtree: new RBush()
71301               },
71302               points: {
71303                 rtree: new RBush()
71304               },
71305               sequences: {
71306                 rtree: new RBush(),
71307                 lineString: {}
71308               },
71309               requests: {
71310                 loaded: {},
71311                 inflight: {}
71312               }
71313             };
71314             _mlyActiveImage = null;
71315           },
71316           // Get visible images
71317           images: function images(projection) {
71318             var limit = 5;
71319             return searchLimited$2(limit, projection, _mlyCache.images.rtree);
71320           },
71321           // Get visible traffic signs
71322           signs: function signs(projection) {
71323             var limit = 5;
71324             return searchLimited$2(limit, projection, _mlyCache.signs.rtree);
71325           },
71326           // Get visible map (point) features
71327           mapFeatures: function mapFeatures(projection) {
71328             var limit = 5;
71329             return searchLimited$2(limit, projection, _mlyCache.points.rtree);
71330           },
71331           // Get cached image by id
71332           cachedImage: function cachedImage(imageId) {
71333             return _mlyCache.images.forImageId[imageId];
71334           },
71335           // Get visible sequences
71336           sequences: function sequences(projection) {
71337             var viewport = projection.clipExtent();
71338             var min = [viewport[0][0], viewport[1][1]];
71339             var max = [viewport[1][0], viewport[0][1]];
71340             var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();
71341             var sequenceIds = {};
71342             var lineStrings = [];
71343
71344             _mlyCache.images.rtree.search(bbox).forEach(function (d) {
71345               if (d.data.sequence_id) {
71346                 sequenceIds[d.data.sequence_id] = true;
71347               }
71348             });
71349
71350             Object.keys(sequenceIds).forEach(function (sequenceId) {
71351               if (_mlyCache.sequences.lineString[sequenceId]) {
71352                 lineStrings = lineStrings.concat(_mlyCache.sequences.lineString[sequenceId]);
71353               }
71354             });
71355             return lineStrings;
71356           },
71357           // Load images in the visible area
71358           loadImages: function loadImages(projection) {
71359             loadTiles$2('images', tileUrl, 14, projection);
71360           },
71361           // Load traffic signs in the visible area
71362           loadSigns: function loadSigns(projection) {
71363             loadTiles$2('signs', trafficSignTileUrl, 14, projection);
71364           },
71365           // Load map (point) features in the visible area
71366           loadMapFeatures: function loadMapFeatures(projection) {
71367             loadTiles$2('points', mapFeatureTileUrl, 14, projection);
71368           },
71369           // Return a promise that resolves when the image viewer (Mapillary JS) library has finished loading
71370           ensureViewerLoaded: function ensureViewerLoaded(context) {
71371             if (_loadViewerPromise$2) return _loadViewerPromise$2; // add mly-wrapper
71372
71373             var wrap = context.container().select('.photoviewer').selectAll('.mly-wrapper').data([0]);
71374             wrap.enter().append('div').attr('id', 'ideditor-mly').attr('class', 'photo-wrapper mly-wrapper').classed('hide', true);
71375             var that = this;
71376             _loadViewerPromise$2 = new Promise(function (resolve, reject) {
71377               var loadedCount = 0;
71378
71379               function loaded() {
71380                 loadedCount += 1; // wait until both files are loaded
71381
71382                 if (loadedCount === 2) resolve();
71383               }
71384
71385               var head = select('head'); // load mapillary-viewercss
71386
71387               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 () {
71388                 reject();
71389               }); // load mapillary-viewerjs
71390
71391               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 () {
71392                 reject();
71393               });
71394             })["catch"](function () {
71395               _loadViewerPromise$2 = null;
71396             }).then(function () {
71397               that.initViewer(context);
71398             });
71399             return _loadViewerPromise$2;
71400           },
71401           // Load traffic sign image sprites
71402           loadSignResources: function loadSignResources(context) {
71403             context.ui().svgDefs.addSprites(['mapillary-sprite'], false
71404             /* don't override colors */
71405             );
71406             return this;
71407           },
71408           // Load map (point) feature image sprites
71409           loadObjectResources: function loadObjectResources(context) {
71410             context.ui().svgDefs.addSprites(['mapillary-object-sprite'], false
71411             /* don't override colors */
71412             );
71413             return this;
71414           },
71415           // Remove previous detections in image viewer
71416           resetTags: function resetTags() {
71417             if (_mlyViewer && !_mlyFallback) {
71418               _mlyViewer.getComponent('tag').removeAll();
71419             }
71420           },
71421           // Show map feature detections in image viewer
71422           showFeatureDetections: function showFeatureDetections(value) {
71423             _mlyShowFeatureDetections = value;
71424
71425             if (!_mlyShowFeatureDetections && !_mlyShowSignDetections) {
71426               this.resetTags();
71427             }
71428           },
71429           // Show traffic sign detections in image viewer
71430           showSignDetections: function showSignDetections(value) {
71431             _mlyShowSignDetections = value;
71432
71433             if (!_mlyShowFeatureDetections && !_mlyShowSignDetections) {
71434               this.resetTags();
71435             }
71436           },
71437           // Apply filter to image viewer
71438           filterViewer: function filterViewer(context) {
71439             var showsPano = context.photos().showsPanoramic();
71440             var showsFlat = context.photos().showsFlat();
71441             var fromDate = context.photos().fromDate();
71442             var toDate = context.photos().toDate();
71443             var filter = ['all'];
71444             if (!showsPano) filter.push(['!=', 'cameraType', 'spherical']);
71445             if (!showsFlat && showsPano) filter.push(['==', 'pano', true]);
71446
71447             if (fromDate) {
71448               filter.push(['>=', 'capturedAt', new Date(fromDate).getTime()]);
71449             }
71450
71451             if (toDate) {
71452               filter.push(['>=', 'capturedAt', new Date(toDate).getTime()]);
71453             }
71454
71455             if (_mlyViewer) {
71456               _mlyViewer.setFilter(filter);
71457             }
71458
71459             _mlyViewerFilter = filter;
71460             return filter;
71461           },
71462           // Make the image viewer visible
71463           showViewer: function showViewer(context) {
71464             var wrap = context.container().select('.photoviewer').classed('hide', false);
71465             var isHidden = wrap.selectAll('.photo-wrapper.mly-wrapper.hide').size();
71466
71467             if (isHidden && _mlyViewer) {
71468               wrap.selectAll('.photo-wrapper:not(.mly-wrapper)').classed('hide', true);
71469               wrap.selectAll('.photo-wrapper.mly-wrapper').classed('hide', false);
71470
71471               _mlyViewer.resize();
71472             }
71473
71474             return this;
71475           },
71476           // Hide the image viewer and resets map markers
71477           hideViewer: function hideViewer(context) {
71478             _mlyActiveImage = null;
71479
71480             if (!_mlyFallback && _mlyViewer) {
71481               _mlyViewer.getComponent('sequence').stop();
71482             }
71483
71484             var viewer = context.container().select('.photoviewer');
71485             if (!viewer.empty()) viewer.datum(null);
71486             viewer.classed('hide', true).selectAll('.photo-wrapper').classed('hide', true);
71487             this.updateUrlImage(null);
71488             dispatch$4.call('imageChanged');
71489             dispatch$4.call('loadedMapFeatures');
71490             dispatch$4.call('loadedSigns');
71491             return this.setStyles(context, null);
71492           },
71493           // Update the URL with current image id
71494           updateUrlImage: function updateUrlImage(imageId) {
71495             if (!window.mocha) {
71496               var hash = utilStringQs(window.location.hash);
71497
71498               if (imageId) {
71499                 hash.photo = 'mapillary/' + imageId;
71500               } else {
71501                 delete hash.photo;
71502               }
71503
71504               window.location.replace('#' + utilQsString(hash, true));
71505             }
71506           },
71507           // Highlight the detection in the viewer that is related to the clicked map feature
71508           highlightDetection: function highlightDetection(detection) {
71509             if (detection) {
71510               _mlyHighlightedDetection = detection.id;
71511             }
71512
71513             return this;
71514           },
71515           // Initialize image viewer (Mapillar JS)
71516           initViewer: function initViewer(context) {
71517             var that = this;
71518             if (!window.mapillary) return;
71519             var opts = {
71520               accessToken: accessToken,
71521               component: {
71522                 cover: false,
71523                 keyboard: false,
71524                 tag: true
71525               },
71526               container: 'ideditor-mly'
71527             }; // Disable components requiring WebGL support
71528
71529             if (!mapillary.isSupported() && mapillary.isFallbackSupported()) {
71530               _mlyFallback = true;
71531               opts.component = {
71532                 cover: false,
71533                 direction: false,
71534                 imagePlane: false,
71535                 keyboard: false,
71536                 mouse: false,
71537                 sequence: false,
71538                 tag: false,
71539                 image: true,
71540                 // fallback
71541                 navigation: true // fallback
71542
71543               };
71544             }
71545
71546             _mlyViewer = new mapillary.Viewer(opts);
71547
71548             _mlyViewer.on('image', imageChanged);
71549
71550             _mlyViewer.on('bearing', bearingChanged);
71551
71552             if (_mlyViewerFilter) {
71553               _mlyViewer.setFilter(_mlyViewerFilter);
71554             } // Register viewer resize handler
71555
71556
71557             context.ui().photoviewer.on('resize.mapillary', function () {
71558               if (_mlyViewer) _mlyViewer.resize();
71559             }); // imageChanged: called after the viewer has changed images and is ready.
71560
71561             function imageChanged(node) {
71562               that.resetTags();
71563               var image = node.image;
71564               that.setActiveImage(image);
71565               that.setStyles(context, null);
71566               var loc = [image.originalLngLat.lng, image.originalLngLat.lat];
71567               context.map().centerEase(loc);
71568               that.updateUrlImage(image.id);
71569
71570               if (_mlyShowFeatureDetections || _mlyShowSignDetections) {
71571                 that.updateDetections(image.id, "".concat(apiUrl, "/").concat(image.id, "/detections?access_token=").concat(accessToken, "&fields=id,image,geometry,value"));
71572               }
71573
71574               dispatch$4.call('imageChanged');
71575             } // bearingChanged: called when the bearing changes in the image viewer.
71576
71577
71578             function bearingChanged(e) {
71579               dispatch$4.call('bearingChanged', undefined, e);
71580             }
71581           },
71582           // Move to an image
71583           selectImage: function selectImage(context, imageId) {
71584             if (_mlyViewer && imageId) {
71585               _mlyViewer.moveTo(imageId)["catch"](function (e) {
71586                 console.error('mly3', e); // eslint-disable-line no-console
71587               });
71588             }
71589
71590             return this;
71591           },
71592           // Return the currently displayed image
71593           getActiveImage: function getActiveImage() {
71594             return _mlyActiveImage;
71595           },
71596           // Return a list of detection objects for the given id
71597           getDetections: function getDetections(id) {
71598             return loadData("".concat(apiUrl, "/").concat(id, "/detections?access_token=").concat(accessToken, "&fields=id,value,image"));
71599           },
71600           // Set the currently visible image
71601           setActiveImage: function setActiveImage(image) {
71602             if (image) {
71603               _mlyActiveImage = {
71604                 ca: image.originalCompassAngle,
71605                 id: image.id,
71606                 loc: [image.originalLngLat.lng, image.originalLngLat.lat],
71607                 is_pano: image.cameraType === 'spherical',
71608                 sequence_id: image.sequenceId
71609               };
71610             } else {
71611               _mlyActiveImage = null;
71612             }
71613           },
71614           // Update the currently highlighted sequence and selected bubble.
71615           setStyles: function setStyles(context, hovered) {
71616             var hoveredImageId = hovered && hovered.id;
71617             var hoveredSequenceId = hovered && hovered.sequence_id;
71618             var selectedSequenceId = _mlyActiveImage && _mlyActiveImage.sequence_id;
71619             context.container().selectAll('.layer-mapillary .viewfield-group').classed('highlighted', function (d) {
71620               return d.sequence_id === selectedSequenceId || d.id === hoveredImageId;
71621             }).classed('hovered', function (d) {
71622               return d.id === hoveredImageId;
71623             });
71624             context.container().selectAll('.layer-mapillary .sequence').classed('highlighted', function (d) {
71625               return d.properties.id === hoveredSequenceId;
71626             }).classed('currentView', function (d) {
71627               return d.properties.id === selectedSequenceId;
71628             });
71629             return this;
71630           },
71631           // Get detections for the current image and shows them in the image viewer
71632           updateDetections: function updateDetections(imageId, url) {
71633             if (!_mlyViewer || _mlyFallback) return;
71634             if (!imageId) return;
71635             var cache = _mlyCache.image_detections;
71636
71637             if (cache.forImageId[imageId]) {
71638               showDetections(_mlyCache.image_detections.forImageId[imageId]);
71639             } else {
71640               loadData(url).then(function (detections) {
71641                 detections.forEach(function (detection) {
71642                   if (!cache.forImageId[imageId]) {
71643                     cache.forImageId[imageId] = [];
71644                   }
71645
71646                   cache.forImageId[imageId].push({
71647                     geometry: detection.geometry,
71648                     id: detection.id,
71649                     image_id: imageId,
71650                     value: detection.value
71651                   });
71652                 });
71653                 showDetections(_mlyCache.image_detections.forImageId[imageId] || []);
71654               });
71655             } // Create a tag for each detection and shows it in the image viewer
71656
71657
71658             function showDetections(detections) {
71659               var tagComponent = _mlyViewer.getComponent('tag');
71660
71661               detections.forEach(function (data) {
71662                 var tag = makeTag(data);
71663
71664                 if (tag) {
71665                   tagComponent.add([tag]);
71666                 }
71667               });
71668             } // Create a Mapillary JS tag object
71669
71670
71671             function makeTag(data) {
71672               var valueParts = data.value.split('--');
71673               if (!valueParts.length) return;
71674               var tag;
71675               var text;
71676               var color = 0xffffff;
71677
71678               if (_mlyHighlightedDetection === data.id) {
71679                 color = 0xffff00;
71680                 text = valueParts[1];
71681
71682                 if (text === 'flat' || text === 'discrete' || text === 'sign') {
71683                   text = valueParts[2];
71684                 }
71685
71686                 text = text.replace(/-/g, ' ');
71687                 text = text.charAt(0).toUpperCase() + text.slice(1);
71688                 _mlyHighlightedDetection = null;
71689               }
71690
71691               var decodedGeometry = window.atob(data.geometry);
71692               var uintArray = new Uint8Array(decodedGeometry.length);
71693
71694               for (var i = 0; i < decodedGeometry.length; i++) {
71695                 uintArray[i] = decodedGeometry.charCodeAt(i);
71696               }
71697
71698               var tile = new VectorTile(new pbf(uintArray.buffer));
71699               var layer = tile.layers['mpy-or'];
71700               var geometries = layer.feature(0).loadGeometry();
71701               var polygon = geometries.map(function (ring) {
71702                 return ring.map(function (point) {
71703                   return [point.x / layer.extent, point.y / layer.extent];
71704                 });
71705               });
71706               tag = new mapillary.OutlineTag(data.id, new mapillary.PolygonGeometry(polygon[0]), {
71707                 text: text,
71708                 textColor: color,
71709                 lineColor: color,
71710                 lineWidth: 2,
71711                 fillColor: color,
71712                 fillOpacity: 0.3
71713               });
71714               return tag;
71715             }
71716           },
71717           // Return the current cache
71718           cache: function cache() {
71719             return _mlyCache;
71720           }
71721         };
71722
71723         function validationIssue(attrs) {
71724           this.type = attrs.type; // required - name of rule that created the issue (e.g. 'missing_tag')
71725
71726           this.subtype = attrs.subtype; // optional - category of the issue within the type (e.g. 'relation_type' under 'missing_tag')
71727
71728           this.severity = attrs.severity; // required - 'warning' or 'error'
71729
71730           this.message = attrs.message; // required - function returning localized string
71731
71732           this.reference = attrs.reference; // optional - function(selection) to render reference information
71733
71734           this.entityIds = attrs.entityIds; // optional - array of IDs of entities involved in the issue
71735
71736           this.loc = attrs.loc; // optional - [lon, lat] to zoom in on to see the issue
71737
71738           this.data = attrs.data; // optional - object containing extra data for the fixes
71739
71740           this.dynamicFixes = attrs.dynamicFixes; // optional - function(context) returning fixes
71741
71742           this.hash = attrs.hash; // optional - string to further differentiate the issue
71743
71744           this.id = generateID.apply(this); // generated - see below
71745
71746           this.key = generateKey.apply(this); // generated - see below (call after generating this.id)
71747
71748           this.autoFix = null; // generated - if autofix exists, will be set below
71749           // A unique, deterministic string hash.
71750           // Issues with identical id values are considered identical.
71751
71752           function generateID() {
71753             var parts = [this.type];
71754
71755             if (this.hash) {
71756               // subclasses can pass in their own differentiator
71757               parts.push(this.hash);
71758             }
71759
71760             if (this.subtype) {
71761               parts.push(this.subtype);
71762             } // include the entities this issue is for
71763             // (sort them so the id is deterministic)
71764
71765
71766             if (this.entityIds) {
71767               var entityKeys = this.entityIds.slice().sort();
71768               parts.push.apply(parts, entityKeys);
71769             }
71770
71771             return parts.join(':');
71772           } // An identifier suitable for use as the second argument to d3.selection#data().
71773           // (i.e. this should change whenever the data needs to be refreshed)
71774
71775
71776           function generateKey() {
71777             return this.id + ':' + Date.now().toString(); // include time of creation
71778           }
71779
71780           this.extent = function (resolver) {
71781             if (this.loc) {
71782               return geoExtent(this.loc);
71783             }
71784
71785             if (this.entityIds && this.entityIds.length) {
71786               return this.entityIds.reduce(function (extent, entityId) {
71787                 return extent.extend(resolver.entity(entityId).extent(resolver));
71788               }, geoExtent());
71789             }
71790
71791             return null;
71792           };
71793
71794           this.fixes = function (context) {
71795             var fixes = this.dynamicFixes ? this.dynamicFixes(context) : [];
71796             var issue = this;
71797
71798             if (issue.severity === 'warning') {
71799               // allow ignoring any issue that's not an error
71800               fixes.push(new validationIssueFix({
71801                 title: _t.html('issues.fix.ignore_issue.title'),
71802                 icon: 'iD-icon-close',
71803                 onClick: function onClick() {
71804                   context.validator().ignoreIssue(this.issue.id);
71805                 }
71806               }));
71807             }
71808
71809             fixes.forEach(function (fix) {
71810               // the id doesn't matter as long as it's unique to this issue/fix
71811               fix.id = fix.title; // add a reference to the issue for use in actions
71812
71813               fix.issue = issue;
71814
71815               if (fix.autoArgs) {
71816                 issue.autoFix = fix;
71817               }
71818             });
71819             return fixes;
71820           };
71821         }
71822         function validationIssueFix(attrs) {
71823           this.title = attrs.title; // Required
71824
71825           this.onClick = attrs.onClick; // Optional - the function to run to apply the fix
71826
71827           this.disabledReason = attrs.disabledReason; // Optional - a string explaining why the fix is unavailable, if any
71828
71829           this.icon = attrs.icon; // Optional - shows 'iD-icon-wrench' if not set
71830
71831           this.entityIds = attrs.entityIds || []; // Optional - used for hover-higlighting.
71832
71833           this.autoArgs = attrs.autoArgs; // Optional - pass [actions, annotation] arglist if this fix can automatically run
71834
71835           this.issue = null; // Generated link - added by validationIssue
71836         }
71837
71838         var buildRuleChecks = function buildRuleChecks() {
71839           return {
71840             equals: function equals(_equals) {
71841               return function (tags) {
71842                 return Object.keys(_equals).every(function (k) {
71843                   return _equals[k] === tags[k];
71844                 });
71845               };
71846             },
71847             notEquals: function notEquals(_notEquals) {
71848               return function (tags) {
71849                 return Object.keys(_notEquals).some(function (k) {
71850                   return _notEquals[k] !== tags[k];
71851                 });
71852               };
71853             },
71854             absence: function absence(_absence) {
71855               return function (tags) {
71856                 return Object.keys(tags).indexOf(_absence) === -1;
71857               };
71858             },
71859             presence: function presence(_presence) {
71860               return function (tags) {
71861                 return Object.keys(tags).indexOf(_presence) > -1;
71862               };
71863             },
71864             greaterThan: function greaterThan(_greaterThan) {
71865               var key = Object.keys(_greaterThan)[0];
71866               var value = _greaterThan[key];
71867               return function (tags) {
71868                 return tags[key] > value;
71869               };
71870             },
71871             greaterThanEqual: function greaterThanEqual(_greaterThanEqual) {
71872               var key = Object.keys(_greaterThanEqual)[0];
71873               var value = _greaterThanEqual[key];
71874               return function (tags) {
71875                 return tags[key] >= value;
71876               };
71877             },
71878             lessThan: function lessThan(_lessThan) {
71879               var key = Object.keys(_lessThan)[0];
71880               var value = _lessThan[key];
71881               return function (tags) {
71882                 return tags[key] < value;
71883               };
71884             },
71885             lessThanEqual: function lessThanEqual(_lessThanEqual) {
71886               var key = Object.keys(_lessThanEqual)[0];
71887               var value = _lessThanEqual[key];
71888               return function (tags) {
71889                 return tags[key] <= value;
71890               };
71891             },
71892             positiveRegex: function positiveRegex(_positiveRegex) {
71893               var tagKey = Object.keys(_positiveRegex)[0];
71894
71895               var expression = _positiveRegex[tagKey].join('|');
71896
71897               var regex = new RegExp(expression);
71898               return function (tags) {
71899                 return regex.test(tags[tagKey]);
71900               };
71901             },
71902             negativeRegex: function negativeRegex(_negativeRegex) {
71903               var tagKey = Object.keys(_negativeRegex)[0];
71904
71905               var expression = _negativeRegex[tagKey].join('|');
71906
71907               var regex = new RegExp(expression);
71908               return function (tags) {
71909                 return !regex.test(tags[tagKey]);
71910               };
71911             }
71912           };
71913         };
71914
71915         var buildLineKeys = function buildLineKeys() {
71916           return {
71917             highway: {
71918               rest_area: true,
71919               services: true
71920             },
71921             railway: {
71922               roundhouse: true,
71923               station: true,
71924               traverser: true,
71925               turntable: true,
71926               wash: true
71927             }
71928           };
71929         };
71930
71931         var serviceMapRules = {
71932           init: function init() {
71933             this._ruleChecks = buildRuleChecks();
71934             this._validationRules = [];
71935             this._areaKeys = osmAreaKeys;
71936             this._lineKeys = buildLineKeys();
71937           },
71938           // list of rules only relevant to tag checks...
71939           filterRuleChecks: function filterRuleChecks(selector) {
71940             var _ruleChecks = this._ruleChecks;
71941             return Object.keys(selector).reduce(function (rules, key) {
71942               if (['geometry', 'error', 'warning'].indexOf(key) === -1) {
71943                 rules.push(_ruleChecks[key](selector[key]));
71944               }
71945
71946               return rules;
71947             }, []);
71948           },
71949           // builds tagMap from mapcss-parse selector object...
71950           buildTagMap: function buildTagMap(selector) {
71951             var getRegexValues = function getRegexValues(regexes) {
71952               return regexes.map(function (regex) {
71953                 return regex.replace(/\$|\^/g, '');
71954               });
71955             };
71956
71957             var tagMap = Object.keys(selector).reduce(function (expectedTags, key) {
71958               var values;
71959               var isRegex = /regex/gi.test(key);
71960               var isEqual = /equals/gi.test(key);
71961
71962               if (isRegex || isEqual) {
71963                 Object.keys(selector[key]).forEach(function (selectorKey) {
71964                   values = isEqual ? [selector[key][selectorKey]] : getRegexValues(selector[key][selectorKey]);
71965
71966                   if (expectedTags.hasOwnProperty(selectorKey)) {
71967                     values = values.concat(expectedTags[selectorKey]);
71968                   }
71969
71970                   expectedTags[selectorKey] = values;
71971                 });
71972               } else if (/(greater|less)Than(Equal)?|presence/g.test(key)) {
71973                 var tagKey = /presence/.test(key) ? selector[key] : Object.keys(selector[key])[0];
71974                 values = [selector[key][tagKey]];
71975
71976                 if (expectedTags.hasOwnProperty(tagKey)) {
71977                   values = values.concat(expectedTags[tagKey]);
71978                 }
71979
71980                 expectedTags[tagKey] = values;
71981               }
71982
71983               return expectedTags;
71984             }, {});
71985             return tagMap;
71986           },
71987           // inspired by osmWay#isArea()
71988           inferGeometry: function inferGeometry(tagMap) {
71989             var _lineKeys = this._lineKeys;
71990             var _areaKeys = this._areaKeys;
71991
71992             var keyValueDoesNotImplyArea = function keyValueDoesNotImplyArea(key) {
71993               return utilArrayIntersection(tagMap[key], Object.keys(_areaKeys[key])).length > 0;
71994             };
71995
71996             var keyValueImpliesLine = function keyValueImpliesLine(key) {
71997               return utilArrayIntersection(tagMap[key], Object.keys(_lineKeys[key])).length > 0;
71998             };
71999
72000             if (tagMap.hasOwnProperty('area')) {
72001               if (tagMap.area.indexOf('yes') > -1) {
72002                 return 'area';
72003               }
72004
72005               if (tagMap.area.indexOf('no') > -1) {
72006                 return 'line';
72007               }
72008             }
72009
72010             for (var key in tagMap) {
72011               if (key in _areaKeys && !keyValueDoesNotImplyArea(key)) {
72012                 return 'area';
72013               }
72014
72015               if (key in _lineKeys && keyValueImpliesLine(key)) {
72016                 return 'area';
72017               }
72018             }
72019
72020             return 'line';
72021           },
72022           // adds from mapcss-parse selector check...
72023           addRule: function addRule(selector) {
72024             var rule = {
72025               // checks relevant to mapcss-selector
72026               checks: this.filterRuleChecks(selector),
72027               // true if all conditions for a tag error are true..
72028               matches: function matches(entity) {
72029                 return this.checks.every(function (check) {
72030                   return check(entity.tags);
72031                 });
72032               },
72033               // borrowed from Way#isArea()
72034               inferredGeometry: this.inferGeometry(this.buildTagMap(selector), this._areaKeys),
72035               geometryMatches: function geometryMatches(entity, graph) {
72036                 if (entity.type === 'node' || entity.type === 'relation') {
72037                   return selector.geometry === entity.type;
72038                 } else if (entity.type === 'way') {
72039                   return this.inferredGeometry === entity.geometry(graph);
72040                 }
72041               },
72042               // when geometries match and tag matches are present, return a warning...
72043               findIssues: function findIssues(entity, graph, issues) {
72044                 if (this.geometryMatches(entity, graph) && this.matches(entity)) {
72045                   var severity = Object.keys(selector).indexOf('error') > -1 ? 'error' : 'warning';
72046                   var _message = selector[severity];
72047                   issues.push(new validationIssue({
72048                     type: 'maprules',
72049                     severity: severity,
72050                     message: function message() {
72051                       return _message;
72052                     },
72053                     entityIds: [entity.id]
72054                   }));
72055                 }
72056               }
72057             };
72058
72059             this._validationRules.push(rule);
72060           },
72061           clearRules: function clearRules() {
72062             this._validationRules = [];
72063           },
72064           // returns validationRules...
72065           validationRules: function validationRules() {
72066             return this._validationRules;
72067           },
72068           // returns ruleChecks
72069           ruleChecks: function ruleChecks() {
72070             return this._ruleChecks;
72071           }
72072         };
72073
72074         var apibase$2 = 'https://nominatim.openstreetmap.org/';
72075         var _inflight$2 = {};
72076
72077         var _nominatimCache;
72078
72079         var serviceNominatim = {
72080           init: function init() {
72081             _inflight$2 = {};
72082             _nominatimCache = new RBush();
72083           },
72084           reset: function reset() {
72085             Object.values(_inflight$2).forEach(function (controller) {
72086               controller.abort();
72087             });
72088             _inflight$2 = {};
72089             _nominatimCache = new RBush();
72090           },
72091           countryCode: function countryCode(location, callback) {
72092             this.reverse(location, function (err, result) {
72093               if (err) {
72094                 return callback(err);
72095               } else if (result.address) {
72096                 return callback(null, result.address.country_code);
72097               } else {
72098                 return callback('Unable to geocode', null);
72099               }
72100             });
72101           },
72102           reverse: function reverse(loc, callback) {
72103             var cached = _nominatimCache.search({
72104               minX: loc[0],
72105               minY: loc[1],
72106               maxX: loc[0],
72107               maxY: loc[1]
72108             });
72109
72110             if (cached.length > 0) {
72111               if (callback) callback(null, cached[0].data);
72112               return;
72113             }
72114
72115             var params = {
72116               zoom: 13,
72117               format: 'json',
72118               addressdetails: 1,
72119               lat: loc[1],
72120               lon: loc[0]
72121             };
72122             var url = apibase$2 + 'reverse?' + utilQsString(params);
72123             if (_inflight$2[url]) return;
72124             var controller = new AbortController();
72125             _inflight$2[url] = controller;
72126             d3_json(url, {
72127               signal: controller.signal
72128             }).then(function (result) {
72129               delete _inflight$2[url];
72130
72131               if (result && result.error) {
72132                 throw new Error(result.error);
72133               }
72134
72135               var extent = geoExtent(loc).padByMeters(200);
72136
72137               _nominatimCache.insert(Object.assign(extent.bbox(), {
72138                 data: result
72139               }));
72140
72141               if (callback) callback(null, result);
72142             })["catch"](function (err) {
72143               delete _inflight$2[url];
72144               if (err.name === 'AbortError') return;
72145               if (callback) callback(err.message);
72146             });
72147           },
72148           search: function search(val, callback) {
72149             var searchVal = encodeURIComponent(val);
72150             var url = apibase$2 + 'search/' + searchVal + '?limit=10&format=json';
72151             if (_inflight$2[url]) return;
72152             var controller = new AbortController();
72153             _inflight$2[url] = controller;
72154             d3_json(url, {
72155               signal: controller.signal
72156             }).then(function (result) {
72157               delete _inflight$2[url];
72158
72159               if (result && result.error) {
72160                 throw new Error(result.error);
72161               }
72162
72163               if (callback) callback(null, result);
72164             })["catch"](function (err) {
72165               delete _inflight$2[url];
72166               if (err.name === 'AbortError') return;
72167               if (callback) callback(err.message);
72168             });
72169           }
72170         };
72171
72172         // for punction see https://stackoverflow.com/a/21224179
72173
72174         function simplify$1(str) {
72175           if (typeof str !== 'string') return '';
72176           return diacritics.remove(str.replace(/&/g, 'and').replace(/İ/ig, 'i') // for BİM, İşbank - #5017
72177           .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());
72178         }
72179
72180         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/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/botique","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"],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/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"]};
72181         var matchGroupsJSON = {
72182         matchGroups: matchGroups$1
72183         };
72184
72185         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$","^церковная( лавка)?$"];
72186         var genericWordsJSON = {
72187         genericWords: genericWords
72188         };
72189
72190         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+)$"}}};
72191         var treesJSON = {
72192         trees: trees$1
72193         };
72194
72195         var matchGroups = matchGroupsJSON.matchGroups;
72196         var trees = treesJSON.trees;
72197         var Matcher = /*#__PURE__*/function () {
72198           //
72199           // `constructor`
72200           // initialize the genericWords regexes
72201           function Matcher() {
72202             var _this = this;
72203
72204             _classCallCheck$1(this, Matcher);
72205
72206             // The `matchIndex` is a specialized structure that allows us to quickly answer
72207             //   _"Given a [key/value tagpair, name, location], what canonical items (brands etc) can match it?"_
72208             //
72209             // The index contains all valid combinations of k/v tagpairs and names
72210             // matchIndex:
72211             // {
72212             //   'k/v': {
72213             //     'primary':         Map (String 'nsimple' -> Set (itemIDs…),   // matches for tags like `name`, `name:xx`, etc.
72214             //     'alternate':       Map (String 'nsimple' -> Set (itemIDs…),   // matches for tags like `alt_name`, `brand`, etc.
72215             //     'excludeNamed':    Map (String 'pattern' -> RegExp),
72216             //     'excludeGeneric':  Map (String 'pattern' -> RegExp)
72217             //   },
72218             // }
72219             //
72220             // {
72221             //   'amenity/bank': {
72222             //     'primary': {
72223             //       'firstbank':              Set ("firstbank-978cca", "firstbank-9794e6", "firstbank-f17495", …),
72224             //       …
72225             //     },
72226             //     'alternate': {
72227             //       '1stbank':                Set ("firstbank-f17495"),
72228             //       …
72229             //     }
72230             //   },
72231             //   'shop/supermarket': {
72232             //     'primary': {
72233             //       'coop':                   Set ("coop-76454b", "coop-ebf2d9", "coop-36e991", …),
72234             //       'coopfood':               Set ("coopfood-a8278b", …),
72235             //       …
72236             //     },
72237             //     'alternate': {
72238             //       'coop':                   Set ("coopfood-a8278b", …),
72239             //       'federatedcooperatives':  Set ("coop-76454b", …),
72240             //       'thecooperative':         Set ("coopfood-a8278b", …),
72241             //       …
72242             //     }
72243             //   }
72244             // }
72245             //
72246             this.matchIndex = undefined; // The `genericWords` structure matches the contents of genericWords.json to instantiated RegExp objects
72247             // Map (String 'pattern' -> RegExp),
72248
72249             this.genericWords = new Map();
72250             (genericWordsJSON.genericWords || []).forEach(function (s) {
72251               return _this.genericWords.set(s, new RegExp(s, 'i'));
72252             }); // The `itemLocation` structure maps itemIDs to locationSetIDs:
72253             // {
72254             //   'firstbank-f17495':  '+[first_bank_western_us.geojson]',
72255             //   'firstbank-978cca':  '+[first_bank_carolinas.geojson]',
72256             //   'coop-76454b':       '+[Q16]',
72257             //   'coopfood-a8278b':   '+[Q23666]',
72258             //   …
72259             // }
72260
72261             this.itemLocation = undefined; // The `locationSets` structure maps locationSetIDs to *resolved* locationSets:
72262             // {
72263             //   '+[first_bank_western_us.geojson]':  GeoJSON {…},
72264             //   '+[first_bank_carolinas.geojson]':   GeoJSON {…},
72265             //   '+[Q16]':                            GeoJSON {…},
72266             //   '+[Q23666]':                         GeoJSON {…},
72267             //   …
72268             // }
72269
72270             this.locationSets = undefined; // The `locationIndex` is an instance of which-polygon spatial index for the locationSets.
72271
72272             this.locationIndex = undefined; // Array of match conflict pairs (currently unused)
72273
72274             this.warnings = [];
72275           } //
72276           // `buildMatchIndex()`
72277           // Call this to prepare the matcher for use
72278           //
72279           // `data` needs to be an Object indexed on a 'tree/key/value' path.
72280           // (e.g. cache filled by `fileTree.read` or data found in `dist/nsi.json`)
72281           // {
72282           //    'brands/amenity/bank': { properties: {}, items: [ {}, {}, … ] },
72283           //    'brands/amenity/bar':  { properties: {}, items: [ {}, {}, … ] },
72284           //    …
72285           // }
72286           //
72287
72288
72289           _createClass$1(Matcher, [{
72290             key: "buildMatchIndex",
72291             value: function buildMatchIndex(data) {
72292               var that = this;
72293               if (that.matchIndex) return; // it was built already
72294
72295               that.matchIndex = new Map();
72296               var seenTree = new Map(); // warn if the same [k, v, nsimple] appears in multiple trees - #5625
72297
72298               Object.keys(data).forEach(function (tkv) {
72299                 var category = data[tkv];
72300                 var parts = tkv.split('/', 3); // tkv = "tree/key/value"
72301
72302                 var t = parts[0];
72303                 var k = parts[1];
72304                 var v = parts[2];
72305                 var thiskv = "".concat(k, "/").concat(v);
72306                 var tree = trees[t];
72307                 var branch = that.matchIndex.get(thiskv);
72308
72309                 if (!branch) {
72310                   branch = {
72311                     primary: new Map(),
72312                     alternate: new Map(),
72313                     excludeGeneric: new Map(),
72314                     excludeNamed: new Map()
72315                   };
72316                   that.matchIndex.set(thiskv, branch);
72317                 } // ADD EXCLUSIONS
72318
72319
72320                 var properties = category.properties || {};
72321                 var exclude = properties.exclude || {};
72322                 (exclude.generic || []).forEach(function (s) {
72323                   return branch.excludeGeneric.set(s, new RegExp(s, 'i'));
72324                 });
72325                 (exclude.named || []).forEach(function (s) {
72326                   return branch.excludeNamed.set(s, new RegExp(s, 'i'));
72327                 });
72328                 var excludeRegexes = [].concat(_toConsumableArray(branch.excludeGeneric.values()), _toConsumableArray(branch.excludeNamed.values())); // ADD ITEMS
72329
72330                 var items = category.items;
72331                 if (!Array.isArray(items) || !items.length) return; // Primary name patterns, match tags to take first
72332                 //  e.g. `name`, `name:ru`
72333
72334                 var primaryName = new RegExp(tree.nameTags.primary, 'i'); // Alternate name patterns, match tags to consider after primary
72335                 //  e.g. `alt_name`, `short_name`, `brand`, `brand:ru`, etc..
72336
72337                 var alternateName = new RegExp(tree.nameTags.alternate, 'i'); // There are a few exceptions to the name matching regexes.
72338                 // Usually a tag suffix contains a language code like `name:en`, `name:ru`
72339                 // but we want to exclude things like `operator:type`, `name:etymology`, etc..
72340
72341                 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`
72342
72343                 var skipGenericKV = skipGenericKVMatches(t, k, v); // We will collect the generic KV pairs anyway (for the purpose of filtering them out of matchTags)
72344
72345                 var genericKV = new Set(["".concat(k, "/yes"), "building/yes"]); // Collect alternate tagpairs for this kv category from matchGroups.
72346                 // We might also pick up a few more generic KVs (like `shop/yes`)
72347
72348                 var matchGroupKV = new Set();
72349                 Object.values(matchGroups).forEach(function (matchGroup) {
72350                   var inGroup = matchGroup.some(function (otherkv) {
72351                     return otherkv === thiskv;
72352                   });
72353                   if (!inGroup) return;
72354                   matchGroup.forEach(function (otherkv) {
72355                     if (otherkv === thiskv) return; // skip self
72356
72357                     matchGroupKV.add(otherkv);
72358                     var otherk = otherkv.split('/', 2)[0]; // we might pick up a `shop/yes`
72359
72360                     genericKV.add("".concat(otherk, "/yes"));
72361                   });
72362                 }); // For each item, insert all [key, value, name] combinations into the match index
72363
72364                 items.forEach(function (item) {
72365                   if (!item.id) return; // Automatically remove redundant `matchTags` - #3417
72366                   // (i.e. This kv is already covered by matchGroups, so it doesn't need to be in `item.matchTags`)
72367
72368                   if (Array.isArray(item.matchTags) && item.matchTags.length) {
72369                     item.matchTags = item.matchTags.filter(function (matchTag) {
72370                       return !matchGroupKV.has(matchTag) && !genericKV.has(matchTag);
72371                     });
72372                     if (!item.matchTags.length) delete item.matchTags;
72373                   } // key/value tagpairs to insert into the match index..
72374
72375
72376                   var kvTags = ["".concat(thiskv)].concat(item.matchTags || []);
72377
72378                   if (!skipGenericKV) {
72379                     kvTags = kvTags.concat(Array.from(genericKV)); // #3454 - match some generic tags
72380                   } // Index all the namelike tag values
72381
72382
72383                   Object.keys(item.tags).forEach(function (osmkey) {
72384                     if (notName.test(osmkey)) return; // osmkey is not a namelike tag, skip
72385
72386                     var osmvalue = item.tags[osmkey];
72387                     if (!osmvalue || excludeRegexes.some(function (regex) {
72388                       return regex.test(osmvalue);
72389                     })) return; // osmvalue missing or excluded
72390
72391                     if (primaryName.test(osmkey)) {
72392                       kvTags.forEach(function (kv) {
72393                         return insertName('primary', t, kv, simplify$1(osmvalue), item.id);
72394                       });
72395                     } else if (alternateName.test(osmkey)) {
72396                       kvTags.forEach(function (kv) {
72397                         return insertName('alternate', t, kv, simplify$1(osmvalue), item.id);
72398                       });
72399                     }
72400                   }); // Index `matchNames` after indexing all other names..
72401
72402                   var keepMatchNames = new Set();
72403                   (item.matchNames || []).forEach(function (matchName) {
72404                     // If this matchname isn't already indexed, add it to the alternate index
72405                     var nsimple = simplify$1(matchName);
72406                     kvTags.forEach(function (kv) {
72407                       var branch = that.matchIndex.get(kv);
72408                       var primaryLeaf = branch && branch.primary.get(nsimple);
72409                       var alternateLeaf = branch && branch.alternate.get(nsimple);
72410                       var inPrimary = primaryLeaf && primaryLeaf.has(item.id);
72411                       var inAlternate = alternateLeaf && alternateLeaf.has(item.id);
72412
72413                       if (!inPrimary && !inAlternate) {
72414                         insertName('alternate', t, kv, nsimple, item.id);
72415                         keepMatchNames.add(matchName);
72416                       }
72417                     });
72418                   }); // Automatically remove redundant `matchNames` - #3417
72419                   // (i.e. This name got indexed some other way, so it doesn't need to be in `item.matchNames`)
72420
72421                   if (keepMatchNames.size) {
72422                     item.matchNames = Array.from(keepMatchNames);
72423                   } else {
72424                     delete item.matchNames;
72425                   }
72426                 }); // each item
72427               }); // each tkv
72428               // Insert this item into the matchIndex
72429
72430               function insertName(which, t, kv, nsimple, itemID) {
72431                 if (!nsimple) {
72432                   that.warnings.push("Warning: skipping empty ".concat(which, " name for item ").concat(t, "/").concat(kv, ": ").concat(itemID));
72433                   return;
72434                 }
72435
72436                 var branch = that.matchIndex.get(kv);
72437
72438                 if (!branch) {
72439                   branch = {
72440                     primary: new Map(),
72441                     alternate: new Map(),
72442                     excludeGeneric: new Map(),
72443                     excludeNamed: new Map()
72444                   };
72445                   that.matchIndex.set(kv, branch);
72446                 }
72447
72448                 var leaf = branch[which].get(nsimple);
72449
72450                 if (!leaf) {
72451                   leaf = new Set();
72452                   branch[which].set(nsimple, leaf);
72453                 }
72454
72455                 leaf.add(itemID); // insert
72456                 // check for duplicates - #5625
72457
72458                 if (!/yes$/.test(kv)) {
72459                   // ignore genericKV like amenity/yes, building/yes, etc
72460                   var kvnsimple = "".concat(kv, "/").concat(nsimple);
72461                   var existing = seenTree.get(kvnsimple);
72462
72463                   if (existing && existing !== t) {
72464                     var items = Array.from(leaf);
72465                     that.warnings.push("Duplicate cache key \"".concat(kvnsimple, "\" in trees \"").concat(t, "\" and \"").concat(existing, "\", check items: ").concat(items));
72466                     return;
72467                   }
72468
72469                   seenTree.set(kvnsimple, t);
72470                 }
72471               } // For certain categories we do not want to match generic KV pairs like `building/yes` or `amenity/yes`
72472
72473
72474               function skipGenericKVMatches(t, k, v) {
72475                 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';
72476               }
72477             } //
72478             // `buildLocationIndex()`
72479             // Call this to prepare a which-polygon location index.
72480             // This *resolves* all the locationSets into GeoJSON, which takes some time.
72481             // You can skip this step if you don't care about matching within a location.
72482             //
72483             // `data` needs to be an Object indexed on a 'tree/key/value' path.
72484             // (e.g. cache filled by `fileTree.read` or data found in `dist/nsi.json`)
72485             // {
72486             //    'brands/amenity/bank': { properties: {}, items: [ {}, {}, … ] },
72487             //    'brands/amenity/bar':  { properties: {}, items: [ {}, {}, … ] },
72488             //    …
72489             // }
72490             //
72491
72492           }, {
72493             key: "buildLocationIndex",
72494             value: function buildLocationIndex(data, loco) {
72495               var that = this;
72496               if (that.locationIndex) return; // it was built already
72497
72498               that.itemLocation = new Map();
72499               that.locationSets = new Map();
72500               Object.keys(data).forEach(function (tkv) {
72501                 var items = data[tkv].items;
72502                 if (!Array.isArray(items) || !items.length) return;
72503                 items.forEach(function (item) {
72504                   if (that.itemLocation.has(item.id)) return; // we've seen item id already - shouldn't be possible?
72505
72506                   var resolved;
72507
72508                   try {
72509                     resolved = loco.resolveLocationSet(item.locationSet); // resolve a feature for this locationSet
72510                   } catch (err) {
72511                     console.warn("buildLocationIndex: ".concat(err.message)); // couldn't resolve
72512                   }
72513
72514                   if (!resolved || !resolved.id) return;
72515                   that.itemLocation.set(item.id, resolved.id); // link it to the item
72516
72517                   if (that.locationSets.has(resolved.id)) return; // we've seen this locationSet feature before..
72518                   // First time seeing this locationSet feature, make a copy and add to locationSet cache..
72519
72520                   var feature = _cloneDeep(resolved.feature);
72521
72522                   feature.id = resolved.id; // Important: always use the locationSet `id` (`+[Q30]`), not the feature `id` (`Q30`)
72523
72524                   feature.properties.id = resolved.id;
72525
72526                   if (!feature.geometry.coordinates.length || !feature.properties.area) {
72527                     console.warn("buildLocationIndex: locationSet ".concat(resolved.id, " for ").concat(item.id, " resolves to an empty feature:"));
72528                     console.warn(JSON.stringify(feature));
72529                     return;
72530                   }
72531
72532                   that.locationSets.set(resolved.id, feature);
72533                 });
72534               });
72535               that.locationIndex = whichPolygon_1({
72536                 type: 'FeatureCollection',
72537                 features: _toConsumableArray(that.locationSets.values())
72538               });
72539
72540               function _cloneDeep(obj) {
72541                 return JSON.parse(JSON.stringify(obj));
72542               }
72543             } //
72544             // `match()`
72545             // Pass parts and return an Array of matches.
72546             // `k` - key
72547             // `v` - value
72548             // `n` - namelike
72549             // `loc` - optional - [lon,lat] location to search
72550             //
72551             // 1. If the [k,v,n] tuple matches a canonical item…
72552             // Return an Array of match results.
72553             // Each result will include the area in km² that the item is valid.
72554             //
72555             // Order of results:
72556             // Primary ordering will be on the "match" column:
72557             //   "primary" - where the query matches the `name` tag, followed by
72558             //   "alternate" - where the query matches an alternate name tag (e.g. short_name, brand, operator, etc)
72559             // Secondary ordering will be on the "area" column:
72560             //   "area descending" if no location was provided, (worldwide before local)
72561             //   "area ascending" if location was provided (local before worldwide)
72562             //
72563             // [
72564             //   { match: 'primary',   itemID: String,  area: Number,  kv: String,  nsimple: String },
72565             //   { match: 'primary',   itemID: String,  area: Number,  kv: String,  nsimple: String },
72566             //   { match: 'alternate', itemID: String,  area: Number,  kv: String,  nsimple: String },
72567             //   { match: 'alternate', itemID: String,  area: Number,  kv: String,  nsimple: String },
72568             //   …
72569             // ]
72570             //
72571             // -or-
72572             //
72573             // 2. If the [k,v,n] tuple matches an exclude pattern…
72574             // Return an Array with a single exclude result, either
72575             //
72576             // [ { match: 'excludeGeneric', pattern: String,  kv: String } ]  // "generic" e.g. "Food Court"
72577             //   or
72578             // [ { match: 'excludeNamed', pattern: String,  kv: String } ]    // "named", e.g. "Kebabai"
72579             //
72580             // About results
72581             //   "generic" - a generic word that is probably not really a name.
72582             //     For these, iD should warn the user "Hey don't put 'food court' in the name tag".
72583             //   "named" - a real name like "Kebabai" that is just common, but not a brand.
72584             //     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.
72585             //
72586             // -or-
72587             //
72588             // 3. If the [k,v,n] tuple matches nothing of any kind, return `null`
72589             //
72590             //
72591
72592           }, {
72593             key: "match",
72594             value: function match(k, v, n, loc) {
72595               var that = this;
72596
72597               if (!that.matchIndex) {
72598                 throw new Error('match:  matchIndex not built.');
72599               } // If we were supplied a location, and a that.locationIndex has been set up,
72600               // get the locationSets that are valid there so we can filter results.
72601
72602
72603               var matchLocations;
72604
72605               if (Array.isArray(loc) && that.locationIndex) {
72606                 // which-polygon query returns an array of GeoJSON properties, pass true to return all results
72607                 matchLocations = that.locationIndex([loc[0], loc[1], loc[0], loc[1]], true);
72608               }
72609
72610               var nsimple = simplify$1(n);
72611               var seen = new Set();
72612               var results = [];
72613               gatherResults('primary');
72614               gatherResults('alternate');
72615               if (results.length) return results;
72616               gatherResults('exclude');
72617               return results.length ? results : null;
72618
72619               function gatherResults(which) {
72620                 // First try an exact match on k/v
72621                 var kv = "".concat(k, "/").concat(v);
72622                 var didMatch = tryMatch(which, kv);
72623                 if (didMatch) return; // If that didn't work, look in match groups for other pairs considered equivalent to k/v..
72624
72625                 for (var mg in matchGroups) {
72626                   var matchGroup = matchGroups[mg];
72627                   var inGroup = matchGroup.some(function (otherkv) {
72628                     return otherkv === kv;
72629                   });
72630                   if (!inGroup) continue;
72631
72632                   for (var i = 0; i < matchGroup.length; i++) {
72633                     var otherkv = matchGroup[i];
72634                     if (otherkv === kv) continue; // skip self
72635
72636                     didMatch = tryMatch(which, otherkv);
72637                     if (didMatch) return;
72638                   }
72639                 } // If finished 'exclude' pass and still haven't matched anything, try the global `genericWords.json` patterns
72640
72641
72642                 if (which === 'exclude') {
72643                   var regex = _toConsumableArray(that.genericWords.values()).find(function (regex) {
72644                     return regex.test(n);
72645                   });
72646
72647                   if (regex) {
72648                     results.push({
72649                       match: 'excludeGeneric',
72650                       pattern: String(regex)
72651                     }); // note no `branch`, no `kv`
72652
72653                     return;
72654                   }
72655                 }
72656               }
72657
72658               function tryMatch(which, kv) {
72659                 var branch = that.matchIndex.get(kv);
72660                 if (!branch) return;
72661
72662                 if (which === 'exclude') {
72663                   // Test name `n` against named and generic exclude patterns
72664                   var regex = _toConsumableArray(branch.excludeNamed.values()).find(function (regex) {
72665                     return regex.test(n);
72666                   });
72667
72668                   if (regex) {
72669                     results.push({
72670                       match: 'excludeNamed',
72671                       pattern: String(regex),
72672                       kv: kv
72673                     });
72674                     return;
72675                   }
72676
72677                   regex = _toConsumableArray(branch.excludeGeneric.values()).find(function (regex) {
72678                     return regex.test(n);
72679                   });
72680
72681                   if (regex) {
72682                     results.push({
72683                       match: 'excludeGeneric',
72684                       pattern: String(regex),
72685                       kv: kv
72686                     });
72687                     return;
72688                   }
72689
72690                   return;
72691                 }
72692
72693                 var leaf = branch[which].get(nsimple);
72694                 if (!leaf || !leaf.size) return; // If we get here, we matched something..
72695                 // Prepare the results, calculate areas (if location index was set up)
72696
72697                 var hits = Array.from(leaf).map(function (itemID) {
72698                   var area = Infinity;
72699
72700                   if (that.itemLocation && that.locationSets) {
72701                     var location = that.locationSets.get(that.itemLocation.get(itemID));
72702                     area = location && location.properties.area || Infinity;
72703                   }
72704
72705                   return {
72706                     match: which,
72707                     itemID: itemID,
72708                     area: area,
72709                     kv: kv,
72710                     nsimple: nsimple
72711                   };
72712                 });
72713                 var sortFn = byAreaDescending; // Filter the match to include only results valid in the requested `loc`..
72714
72715                 if (matchLocations) {
72716                   hits = hits.filter(isValidLocation);
72717                   sortFn = byAreaAscending;
72718                 }
72719
72720                 if (!hits.length) return; // push results
72721
72722                 hits.sort(sortFn).forEach(function (hit) {
72723                   if (seen.has(hit.itemID)) return;
72724                   seen.add(hit.itemID);
72725                   results.push(hit);
72726                 });
72727                 return true;
72728
72729                 function isValidLocation(hit) {
72730                   if (!that.itemLocation) return true;
72731                   return matchLocations.find(function (props) {
72732                     return props.id === that.itemLocation.get(hit.itemID);
72733                   });
72734                 } // Sort smaller (more local) locations first.
72735
72736
72737                 function byAreaAscending(hitA, hitB) {
72738                   return hitA.area - hitB.area;
72739                 } // Sort larger (more worldwide) locations first.
72740
72741
72742                 function byAreaDescending(hitA, hitB) {
72743                   return hitB.area - hitA.area;
72744                 }
72745               }
72746             } //
72747             // `getWarnings()`
72748             // Return any warnings discovered when buiding the index.
72749             // (currently this does nothing)
72750             //
72751
72752           }, {
72753             key: "getWarnings",
72754             value: function getWarnings() {
72755               return this.warnings;
72756             }
72757           }]);
72758
72759           return Matcher;
72760         }();
72761
72762         /*
72763             iD.coreDifference represents the difference between two graphs.
72764             It knows how to calculate the set of entities that were
72765             created, modified, or deleted, and also contains the logic
72766             for recursively extending a difference to the complete set
72767             of entities that will require a redraw, taking into account
72768             child and parent relationships.
72769          */
72770
72771         function coreDifference(base, head) {
72772           var _changes = {};
72773           var _didChange = {}; // 'addition', 'deletion', 'geometry', 'properties'
72774
72775           var _diff = {};
72776
72777           function checkEntityID(id) {
72778             var h = head.entities[id];
72779             var b = base.entities[id];
72780             if (h === b) return;
72781             if (_changes[id]) return;
72782
72783             if (!h && b) {
72784               _changes[id] = {
72785                 base: b,
72786                 head: h
72787               };
72788               _didChange.deletion = true;
72789               return;
72790             }
72791
72792             if (h && !b) {
72793               _changes[id] = {
72794                 base: b,
72795                 head: h
72796               };
72797               _didChange.addition = true;
72798               return;
72799             }
72800
72801             if (h && b) {
72802               if (h.members && b.members && !fastDeepEqual(h.members, b.members)) {
72803                 _changes[id] = {
72804                   base: b,
72805                   head: h
72806                 };
72807                 _didChange.geometry = true;
72808                 _didChange.properties = true;
72809                 return;
72810               }
72811
72812               if (h.loc && b.loc && !geoVecEqual(h.loc, b.loc)) {
72813                 _changes[id] = {
72814                   base: b,
72815                   head: h
72816                 };
72817                 _didChange.geometry = true;
72818               }
72819
72820               if (h.nodes && b.nodes && !fastDeepEqual(h.nodes, b.nodes)) {
72821                 _changes[id] = {
72822                   base: b,
72823                   head: h
72824                 };
72825                 _didChange.geometry = true;
72826               }
72827
72828               if (h.tags && b.tags && !fastDeepEqual(h.tags, b.tags)) {
72829                 _changes[id] = {
72830                   base: b,
72831                   head: h
72832                 };
72833                 _didChange.properties = true;
72834               }
72835             }
72836           }
72837
72838           function load() {
72839             // HOT CODE: there can be many thousands of downloaded entities, so looping
72840             // through them all can become a performance bottleneck. Optimize by
72841             // resolving duplicates and using a basic `for` loop
72842             var ids = utilArrayUniq(Object.keys(head.entities).concat(Object.keys(base.entities)));
72843
72844             for (var i = 0; i < ids.length; i++) {
72845               checkEntityID(ids[i]);
72846             }
72847           }
72848
72849           load();
72850
72851           _diff.length = function length() {
72852             return Object.keys(_changes).length;
72853           };
72854
72855           _diff.changes = function changes() {
72856             return _changes;
72857           };
72858
72859           _diff.didChange = _didChange; // pass true to include affected relation members
72860
72861           _diff.extantIDs = function extantIDs(includeRelMembers) {
72862             var result = new Set();
72863             Object.keys(_changes).forEach(function (id) {
72864               if (_changes[id].head) {
72865                 result.add(id);
72866               }
72867
72868               var h = _changes[id].head;
72869               var b = _changes[id].base;
72870               var entity = h || b;
72871
72872               if (includeRelMembers && entity.type === 'relation') {
72873                 var mh = h ? h.members.map(function (m) {
72874                   return m.id;
72875                 }) : [];
72876                 var mb = b ? b.members.map(function (m) {
72877                   return m.id;
72878                 }) : [];
72879                 utilArrayUnion(mh, mb).forEach(function (memberID) {
72880                   if (head.hasEntity(memberID)) {
72881                     result.add(memberID);
72882                   }
72883                 });
72884               }
72885             });
72886             return Array.from(result);
72887           };
72888
72889           _diff.modified = function modified() {
72890             var result = [];
72891             Object.values(_changes).forEach(function (change) {
72892               if (change.base && change.head) {
72893                 result.push(change.head);
72894               }
72895             });
72896             return result;
72897           };
72898
72899           _diff.created = function created() {
72900             var result = [];
72901             Object.values(_changes).forEach(function (change) {
72902               if (!change.base && change.head) {
72903                 result.push(change.head);
72904               }
72905             });
72906             return result;
72907           };
72908
72909           _diff.deleted = function deleted() {
72910             var result = [];
72911             Object.values(_changes).forEach(function (change) {
72912               if (change.base && !change.head) {
72913                 result.push(change.base);
72914               }
72915             });
72916             return result;
72917           };
72918
72919           _diff.summary = function summary() {
72920             var relevant = {};
72921             var keys = Object.keys(_changes);
72922
72923             for (var i = 0; i < keys.length; i++) {
72924               var change = _changes[keys[i]];
72925
72926               if (change.head && change.head.geometry(head) !== 'vertex') {
72927                 addEntity(change.head, head, change.base ? 'modified' : 'created');
72928               } else if (change.base && change.base.geometry(base) !== 'vertex') {
72929                 addEntity(change.base, base, 'deleted');
72930               } else if (change.base && change.head) {
72931                 // modified vertex
72932                 var moved = !fastDeepEqual(change.base.loc, change.head.loc);
72933                 var retagged = !fastDeepEqual(change.base.tags, change.head.tags);
72934
72935                 if (moved) {
72936                   addParents(change.head);
72937                 }
72938
72939                 if (retagged || moved && change.head.hasInterestingTags()) {
72940                   addEntity(change.head, head, 'modified');
72941                 }
72942               } else if (change.head && change.head.hasInterestingTags()) {
72943                 // created vertex
72944                 addEntity(change.head, head, 'created');
72945               } else if (change.base && change.base.hasInterestingTags()) {
72946                 // deleted vertex
72947                 addEntity(change.base, base, 'deleted');
72948               }
72949             }
72950
72951             return Object.values(relevant);
72952
72953             function addEntity(entity, graph, changeType) {
72954               relevant[entity.id] = {
72955                 entity: entity,
72956                 graph: graph,
72957                 changeType: changeType
72958               };
72959             }
72960
72961             function addParents(entity) {
72962               var parents = head.parentWays(entity);
72963
72964               for (var j = parents.length - 1; j >= 0; j--) {
72965                 var parent = parents[j];
72966
72967                 if (!(parent.id in relevant)) {
72968                   addEntity(parent, head, 'modified');
72969                 }
72970               }
72971             }
72972           }; // returns complete set of entities that require a redraw
72973           //  (optionally within given `extent`)
72974
72975
72976           _diff.complete = function complete(extent) {
72977             var result = {};
72978             var id, change;
72979
72980             for (id in _changes) {
72981               change = _changes[id];
72982               var h = change.head;
72983               var b = change.base;
72984               var entity = h || b;
72985               var i;
72986
72987               if (extent && (!h || !h.intersects(extent, head)) && (!b || !b.intersects(extent, base))) {
72988                 continue;
72989               }
72990
72991               result[id] = h;
72992
72993               if (entity.type === 'way') {
72994                 var nh = h ? h.nodes : [];
72995                 var nb = b ? b.nodes : [];
72996                 var diff;
72997                 diff = utilArrayDifference(nh, nb);
72998
72999                 for (i = 0; i < diff.length; i++) {
73000                   result[diff[i]] = head.hasEntity(diff[i]);
73001                 }
73002
73003                 diff = utilArrayDifference(nb, nh);
73004
73005                 for (i = 0; i < diff.length; i++) {
73006                   result[diff[i]] = head.hasEntity(diff[i]);
73007                 }
73008               }
73009
73010               if (entity.type === 'relation' && entity.isMultipolygon()) {
73011                 var mh = h ? h.members.map(function (m) {
73012                   return m.id;
73013                 }) : [];
73014                 var mb = b ? b.members.map(function (m) {
73015                   return m.id;
73016                 }) : [];
73017                 var ids = utilArrayUnion(mh, mb);
73018
73019                 for (i = 0; i < ids.length; i++) {
73020                   var member = head.hasEntity(ids[i]);
73021                   if (!member) continue; // not downloaded
73022
73023                   if (extent && !member.intersects(extent, head)) continue; // not visible
73024
73025                   result[ids[i]] = member;
73026                 }
73027               }
73028
73029               addParents(head.parentWays(entity), result);
73030               addParents(head.parentRelations(entity), result);
73031             }
73032
73033             return result;
73034
73035             function addParents(parents, result) {
73036               for (var i = 0; i < parents.length; i++) {
73037                 var parent = parents[i];
73038                 if (parent.id in result) continue;
73039                 result[parent.id] = parent;
73040                 addParents(head.parentRelations(parent), result);
73041               }
73042             }
73043           };
73044
73045           return _diff;
73046         }
73047
73048         function coreTree(head) {
73049           // tree for entities
73050           var _rtree = new RBush();
73051
73052           var _bboxes = {}; // maintain a separate tree for granular way segments
73053
73054           var _segmentsRTree = new RBush();
73055
73056           var _segmentsBBoxes = {};
73057           var _segmentsByWayId = {};
73058           var tree = {};
73059
73060           function entityBBox(entity) {
73061             var bbox = entity.extent(head).bbox();
73062             bbox.id = entity.id;
73063             _bboxes[entity.id] = bbox;
73064             return bbox;
73065           }
73066
73067           function segmentBBox(segment) {
73068             var extent = segment.extent(head); // extent can be null if the node entities aren't in the graph for some reason
73069
73070             if (!extent) return null;
73071             var bbox = extent.bbox();
73072             bbox.segment = segment;
73073             _segmentsBBoxes[segment.id] = bbox;
73074             return bbox;
73075           }
73076
73077           function removeEntity(entity) {
73078             _rtree.remove(_bboxes[entity.id]);
73079
73080             delete _bboxes[entity.id];
73081
73082             if (_segmentsByWayId[entity.id]) {
73083               _segmentsByWayId[entity.id].forEach(function (segment) {
73084                 _segmentsRTree.remove(_segmentsBBoxes[segment.id]);
73085
73086                 delete _segmentsBBoxes[segment.id];
73087               });
73088
73089               delete _segmentsByWayId[entity.id];
73090             }
73091           }
73092
73093           function loadEntities(entities) {
73094             _rtree.load(entities.map(entityBBox));
73095
73096             var segments = [];
73097             entities.forEach(function (entity) {
73098               if (entity.segments) {
73099                 var entitySegments = entity.segments(head); // cache these to make them easy to remove later
73100
73101                 _segmentsByWayId[entity.id] = entitySegments;
73102                 segments = segments.concat(entitySegments);
73103               }
73104             });
73105             if (segments.length) _segmentsRTree.load(segments.map(segmentBBox).filter(Boolean));
73106           }
73107
73108           function updateParents(entity, insertions, memo) {
73109             head.parentWays(entity).forEach(function (way) {
73110               if (_bboxes[way.id]) {
73111                 removeEntity(way);
73112                 insertions[way.id] = way;
73113               }
73114
73115               updateParents(way, insertions, memo);
73116             });
73117             head.parentRelations(entity).forEach(function (relation) {
73118               if (memo[entity.id]) return;
73119               memo[entity.id] = true;
73120
73121               if (_bboxes[relation.id]) {
73122                 removeEntity(relation);
73123                 insertions[relation.id] = relation;
73124               }
73125
73126               updateParents(relation, insertions, memo);
73127             });
73128           }
73129
73130           tree.rebase = function (entities, force) {
73131             var insertions = {};
73132
73133             for (var i = 0; i < entities.length; i++) {
73134               var entity = entities[i];
73135               if (!entity.visible) continue;
73136
73137               if (head.entities.hasOwnProperty(entity.id) || _bboxes[entity.id]) {
73138                 if (!force) {
73139                   continue;
73140                 } else if (_bboxes[entity.id]) {
73141                   removeEntity(entity);
73142                 }
73143               }
73144
73145               insertions[entity.id] = entity;
73146               updateParents(entity, insertions, {});
73147             }
73148
73149             loadEntities(Object.values(insertions));
73150             return tree;
73151           };
73152
73153           function updateToGraph(graph) {
73154             if (graph === head) return;
73155             var diff = coreDifference(head, graph);
73156             head = graph;
73157             var changed = diff.didChange;
73158             if (!changed.addition && !changed.deletion && !changed.geometry) return;
73159             var insertions = {};
73160
73161             if (changed.deletion) {
73162               diff.deleted().forEach(function (entity) {
73163                 removeEntity(entity);
73164               });
73165             }
73166
73167             if (changed.geometry) {
73168               diff.modified().forEach(function (entity) {
73169                 removeEntity(entity);
73170                 insertions[entity.id] = entity;
73171                 updateParents(entity, insertions, {});
73172               });
73173             }
73174
73175             if (changed.addition) {
73176               diff.created().forEach(function (entity) {
73177                 insertions[entity.id] = entity;
73178               });
73179             }
73180
73181             loadEntities(Object.values(insertions));
73182           } // returns an array of entities with bounding boxes overlapping `extent` for the given `graph`
73183
73184
73185           tree.intersects = function (extent, graph) {
73186             updateToGraph(graph);
73187             return _rtree.search(extent.bbox()).map(function (bbox) {
73188               return graph.entity(bbox.id);
73189             });
73190           }; // returns an array of segment objects with bounding boxes overlapping `extent` for the given `graph`
73191
73192
73193           tree.waySegments = function (extent, graph) {
73194             updateToGraph(graph);
73195             return _segmentsRTree.search(extent.bbox()).map(function (bbox) {
73196               return bbox.segment;
73197             });
73198           };
73199
73200           return tree;
73201         }
73202
73203         function svgIcon(name, svgklass, useklass) {
73204           return function drawIcon(selection) {
73205             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);
73206           };
73207         }
73208
73209         function uiModal(selection, blocking) {
73210           var _this = this;
73211
73212           var keybinding = utilKeybinding('modal');
73213           var previous = selection.select('div.modal');
73214           var animate = previous.empty();
73215           previous.transition().duration(200).style('opacity', 0).remove();
73216           var shaded = selection.append('div').attr('class', 'shaded').style('opacity', 0);
73217
73218           shaded.close = function () {
73219             shaded.transition().duration(200).style('opacity', 0).remove();
73220             modal.transition().duration(200).style('top', '0px');
73221             select(document).call(keybinding.unbind);
73222           };
73223
73224           var modal = shaded.append('div').attr('class', 'modal fillL');
73225           modal.append('input').attr('class', 'keytrap keytrap-first').on('focus.keytrap', moveFocusToLast);
73226
73227           if (!blocking) {
73228             shaded.on('click.remove-modal', function (d3_event) {
73229               if (d3_event.target === _this) {
73230                 shaded.close();
73231               }
73232             });
73233             modal.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', shaded.close).call(svgIcon('#iD-icon-close'));
73234             keybinding.on('⌫', shaded.close).on('⎋', shaded.close);
73235             select(document).call(keybinding);
73236           }
73237
73238           modal.append('div').attr('class', 'content');
73239           modal.append('input').attr('class', 'keytrap keytrap-last').on('focus.keytrap', moveFocusToFirst);
73240
73241           if (animate) {
73242             shaded.transition().style('opacity', 1);
73243           } else {
73244             shaded.style('opacity', 1);
73245           }
73246
73247           return shaded;
73248
73249           function moveFocusToFirst() {
73250             var node = modal // there are additional rules about what's focusable, but this suits our purposes
73251             .select('a, button, input:not(.keytrap), select, textarea').node();
73252
73253             if (node) {
73254               node.focus();
73255             } else {
73256               select(this).node().blur();
73257             }
73258           }
73259
73260           function moveFocusToLast() {
73261             var nodes = modal.selectAll('a, button, input:not(.keytrap), select, textarea').nodes();
73262
73263             if (nodes.length) {
73264               nodes[nodes.length - 1].focus();
73265             } else {
73266               select(this).node().blur();
73267             }
73268           }
73269         }
73270
73271         function uiLoading(context) {
73272           var _modalSelection = select(null);
73273
73274           var _message = '';
73275           var _blocking = false;
73276
73277           var loading = function loading(selection) {
73278             _modalSelection = uiModal(selection, _blocking);
73279
73280             var loadertext = _modalSelection.select('.content').classed('loading-modal', true).append('div').attr('class', 'modal-section fillL');
73281
73282             loadertext.append('img').attr('class', 'loader').attr('src', context.imagePath('loader-white.gif'));
73283             loadertext.append('h3').html(_message);
73284
73285             _modalSelection.select('button.close').attr('class', 'hide');
73286
73287             return loading;
73288           };
73289
73290           loading.message = function (val) {
73291             if (!arguments.length) return _message;
73292             _message = val;
73293             return loading;
73294           };
73295
73296           loading.blocking = function (val) {
73297             if (!arguments.length) return _blocking;
73298             _blocking = val;
73299             return loading;
73300           };
73301
73302           loading.close = function () {
73303             _modalSelection.remove();
73304           };
73305
73306           loading.isShown = function () {
73307             return _modalSelection && !_modalSelection.empty() && _modalSelection.node().parentNode;
73308           };
73309
73310           return loading;
73311         }
73312
73313         function coreHistory(context) {
73314           var dispatch = dispatch$8('reset', 'change', 'merge', 'restore', 'undone', 'redone', 'storage_error');
73315
73316           var _lock = utilSessionMutex('lock'); // restorable if iD not open in another window/tab and a saved history exists in localStorage
73317
73318
73319           var _hasUnresolvedRestorableChanges = _lock.lock() && !!corePreferences(getKey('saved_history'));
73320
73321           var duration = 150;
73322           var _imageryUsed = [];
73323           var _photoOverlaysUsed = [];
73324           var _checkpoints = {};
73325
73326           var _pausedGraph;
73327
73328           var _stack;
73329
73330           var _index;
73331
73332           var _tree; // internal _act, accepts list of actions and eased time
73333
73334
73335           function _act(actions, t) {
73336             actions = Array.prototype.slice.call(actions);
73337             var annotation;
73338
73339             if (typeof actions[actions.length - 1] !== 'function') {
73340               annotation = actions.pop();
73341             }
73342
73343             var graph = _stack[_index].graph;
73344
73345             for (var i = 0; i < actions.length; i++) {
73346               graph = actions[i](graph, t);
73347             }
73348
73349             return {
73350               graph: graph,
73351               annotation: annotation,
73352               imageryUsed: _imageryUsed,
73353               photoOverlaysUsed: _photoOverlaysUsed,
73354               transform: context.projection.transform(),
73355               selectedIDs: context.selectedIDs()
73356             };
73357           } // internal _perform with eased time
73358
73359
73360           function _perform(args, t) {
73361             var previous = _stack[_index].graph;
73362             _stack = _stack.slice(0, _index + 1);
73363
73364             var actionResult = _act(args, t);
73365
73366             _stack.push(actionResult);
73367
73368             _index++;
73369             return change(previous);
73370           } // internal _replace with eased time
73371
73372
73373           function _replace(args, t) {
73374             var previous = _stack[_index].graph; // assert(_index == _stack.length - 1)
73375
73376             var actionResult = _act(args, t);
73377
73378             _stack[_index] = actionResult;
73379             return change(previous);
73380           } // internal _overwrite with eased time
73381
73382
73383           function _overwrite(args, t) {
73384             var previous = _stack[_index].graph;
73385
73386             if (_index > 0) {
73387               _index--;
73388
73389               _stack.pop();
73390             }
73391
73392             _stack = _stack.slice(0, _index + 1);
73393
73394             var actionResult = _act(args, t);
73395
73396             _stack.push(actionResult);
73397
73398             _index++;
73399             return change(previous);
73400           } // determine difference and dispatch a change event
73401
73402
73403           function change(previous) {
73404             var difference = coreDifference(previous, history.graph());
73405
73406             if (!_pausedGraph) {
73407               dispatch.call('change', this, difference);
73408             }
73409
73410             return difference;
73411           } // iD uses namespaced keys so multiple installations do not conflict
73412
73413
73414           function getKey(n) {
73415             return 'iD_' + window.location.origin + '_' + n;
73416           }
73417
73418           var history = {
73419             graph: function graph() {
73420               return _stack[_index].graph;
73421             },
73422             tree: function tree() {
73423               return _tree;
73424             },
73425             base: function base() {
73426               return _stack[0].graph;
73427             },
73428             merge: function merge(entities
73429             /*, extent*/
73430             ) {
73431               var stack = _stack.map(function (state) {
73432                 return state.graph;
73433               });
73434
73435               _stack[0].graph.rebase(entities, stack, false);
73436
73437               _tree.rebase(entities, false);
73438
73439               dispatch.call('merge', this, entities);
73440             },
73441             perform: function perform() {
73442               // complete any transition already in progress
73443               select(document).interrupt('history.perform');
73444               var transitionable = false;
73445               var action0 = arguments[0];
73446
73447               if (arguments.length === 1 || arguments.length === 2 && typeof arguments[1] !== 'function') {
73448                 transitionable = !!action0.transitionable;
73449               }
73450
73451               if (transitionable) {
73452                 var origArguments = arguments;
73453                 select(document).transition('history.perform').duration(duration).ease(linear$1).tween('history.tween', function () {
73454                   return function (t) {
73455                     if (t < 1) _overwrite([action0], t);
73456                   };
73457                 }).on('start', function () {
73458                   _perform([action0], 0);
73459                 }).on('end interrupt', function () {
73460                   _overwrite(origArguments, 1);
73461                 });
73462               } else {
73463                 return _perform(arguments);
73464               }
73465             },
73466             replace: function replace() {
73467               select(document).interrupt('history.perform');
73468               return _replace(arguments, 1);
73469             },
73470             // Same as calling pop and then perform
73471             overwrite: function overwrite() {
73472               select(document).interrupt('history.perform');
73473               return _overwrite(arguments, 1);
73474             },
73475             pop: function pop(n) {
73476               select(document).interrupt('history.perform');
73477               var previous = _stack[_index].graph;
73478
73479               if (isNaN(+n) || +n < 0) {
73480                 n = 1;
73481               }
73482
73483               while (n-- > 0 && _index > 0) {
73484                 _index--;
73485
73486                 _stack.pop();
73487               }
73488
73489               return change(previous);
73490             },
73491             // Back to the previous annotated state or _index = 0.
73492             undo: function undo() {
73493               select(document).interrupt('history.perform');
73494               var previousStack = _stack[_index];
73495               var previous = previousStack.graph;
73496
73497               while (_index > 0) {
73498                 _index--;
73499                 if (_stack[_index].annotation) break;
73500               }
73501
73502               dispatch.call('undone', this, _stack[_index], previousStack);
73503               return change(previous);
73504             },
73505             // Forward to the next annotated state.
73506             redo: function redo() {
73507               select(document).interrupt('history.perform');
73508               var previousStack = _stack[_index];
73509               var previous = previousStack.graph;
73510               var tryIndex = _index;
73511
73512               while (tryIndex < _stack.length - 1) {
73513                 tryIndex++;
73514
73515                 if (_stack[tryIndex].annotation) {
73516                   _index = tryIndex;
73517                   dispatch.call('redone', this, _stack[_index], previousStack);
73518                   break;
73519                 }
73520               }
73521
73522               return change(previous);
73523             },
73524             pauseChangeDispatch: function pauseChangeDispatch() {
73525               if (!_pausedGraph) {
73526                 _pausedGraph = _stack[_index].graph;
73527               }
73528             },
73529             resumeChangeDispatch: function resumeChangeDispatch() {
73530               if (_pausedGraph) {
73531                 var previous = _pausedGraph;
73532                 _pausedGraph = null;
73533                 return change(previous);
73534               }
73535             },
73536             undoAnnotation: function undoAnnotation() {
73537               var i = _index;
73538
73539               while (i >= 0) {
73540                 if (_stack[i].annotation) return _stack[i].annotation;
73541                 i--;
73542               }
73543             },
73544             redoAnnotation: function redoAnnotation() {
73545               var i = _index + 1;
73546
73547               while (i <= _stack.length - 1) {
73548                 if (_stack[i].annotation) return _stack[i].annotation;
73549                 i++;
73550               }
73551             },
73552             // Returns the entities from the active graph with bounding boxes
73553             // overlapping the given `extent`.
73554             intersects: function intersects(extent) {
73555               return _tree.intersects(extent, _stack[_index].graph);
73556             },
73557             difference: function difference() {
73558               var base = _stack[0].graph;
73559               var head = _stack[_index].graph;
73560               return coreDifference(base, head);
73561             },
73562             changes: function changes(action) {
73563               var base = _stack[0].graph;
73564               var head = _stack[_index].graph;
73565
73566               if (action) {
73567                 head = action(head);
73568               }
73569
73570               var difference = coreDifference(base, head);
73571               return {
73572                 modified: difference.modified(),
73573                 created: difference.created(),
73574                 deleted: difference.deleted()
73575               };
73576             },
73577             hasChanges: function hasChanges() {
73578               return this.difference().length() > 0;
73579             },
73580             imageryUsed: function imageryUsed(sources) {
73581               if (sources) {
73582                 _imageryUsed = sources;
73583                 return history;
73584               } else {
73585                 var s = new Set();
73586
73587                 _stack.slice(1, _index + 1).forEach(function (state) {
73588                   state.imageryUsed.forEach(function (source) {
73589                     if (source !== 'Custom') {
73590                       s.add(source);
73591                     }
73592                   });
73593                 });
73594
73595                 return Array.from(s);
73596               }
73597             },
73598             photoOverlaysUsed: function photoOverlaysUsed(sources) {
73599               if (sources) {
73600                 _photoOverlaysUsed = sources;
73601                 return history;
73602               } else {
73603                 var s = new Set();
73604
73605                 _stack.slice(1, _index + 1).forEach(function (state) {
73606                   if (state.photoOverlaysUsed && Array.isArray(state.photoOverlaysUsed)) {
73607                     state.photoOverlaysUsed.forEach(function (photoOverlay) {
73608                       s.add(photoOverlay);
73609                     });
73610                   }
73611                 });
73612
73613                 return Array.from(s);
73614               }
73615             },
73616             // save the current history state
73617             checkpoint: function checkpoint(key) {
73618               _checkpoints[key] = {
73619                 stack: _stack,
73620                 index: _index
73621               };
73622               return history;
73623             },
73624             // restore history state to a given checkpoint or reset completely
73625             reset: function reset(key) {
73626               if (key !== undefined && _checkpoints.hasOwnProperty(key)) {
73627                 _stack = _checkpoints[key].stack;
73628                 _index = _checkpoints[key].index;
73629               } else {
73630                 _stack = [{
73631                   graph: coreGraph()
73632                 }];
73633                 _index = 0;
73634                 _tree = coreTree(_stack[0].graph);
73635                 _checkpoints = {};
73636               }
73637
73638               dispatch.call('reset');
73639               dispatch.call('change');
73640               return history;
73641             },
73642             // `toIntroGraph()` is used to export the intro graph used by the walkthrough.
73643             //
73644             // To use it:
73645             //  1. Start the walkthrough.
73646             //  2. Get to a "free editing" tutorial step
73647             //  3. Make your edits to the walkthrough map
73648             //  4. In your browser dev console run:
73649             //        `id.history().toIntroGraph()`
73650             //  5. This outputs stringified JSON to the browser console
73651             //  6. Copy it to `data/intro_graph.json` and prettify it in your code editor
73652             toIntroGraph: function toIntroGraph() {
73653               var nextID = {
73654                 n: 0,
73655                 r: 0,
73656                 w: 0
73657               };
73658               var permIDs = {};
73659               var graph = this.graph();
73660               var baseEntities = {}; // clone base entities..
73661
73662               Object.values(graph.base().entities).forEach(function (entity) {
73663                 var copy = copyIntroEntity(entity);
73664                 baseEntities[copy.id] = copy;
73665               }); // replace base entities with head entities..
73666
73667               Object.keys(graph.entities).forEach(function (id) {
73668                 var entity = graph.entities[id];
73669
73670                 if (entity) {
73671                   var copy = copyIntroEntity(entity);
73672                   baseEntities[copy.id] = copy;
73673                 } else {
73674                   delete baseEntities[id];
73675                 }
73676               }); // swap temporary for permanent ids..
73677
73678               Object.values(baseEntities).forEach(function (entity) {
73679                 if (Array.isArray(entity.nodes)) {
73680                   entity.nodes = entity.nodes.map(function (node) {
73681                     return permIDs[node] || node;
73682                   });
73683                 }
73684
73685                 if (Array.isArray(entity.members)) {
73686                   entity.members = entity.members.map(function (member) {
73687                     member.id = permIDs[member.id] || member.id;
73688                     return member;
73689                   });
73690                 }
73691               });
73692               return JSON.stringify({
73693                 dataIntroGraph: baseEntities
73694               });
73695
73696               function copyIntroEntity(source) {
73697                 var copy = utilObjectOmit(source, ['type', 'user', 'v', 'version', 'visible']); // Note: the copy is no longer an osmEntity, so it might not have `tags`
73698
73699                 if (copy.tags && !Object.keys(copy.tags)) {
73700                   delete copy.tags;
73701                 }
73702
73703                 if (Array.isArray(copy.loc)) {
73704                   copy.loc[0] = +copy.loc[0].toFixed(6);
73705                   copy.loc[1] = +copy.loc[1].toFixed(6);
73706                 }
73707
73708                 var match = source.id.match(/([nrw])-\d*/); // temporary id
73709
73710                 if (match !== null) {
73711                   var nrw = match[1];
73712                   var permID;
73713
73714                   do {
73715                     permID = nrw + ++nextID[nrw];
73716                   } while (baseEntities.hasOwnProperty(permID));
73717
73718                   copy.id = permIDs[source.id] = permID;
73719                 }
73720
73721                 return copy;
73722               }
73723             },
73724             toJSON: function toJSON() {
73725               if (!this.hasChanges()) return;
73726               var allEntities = {};
73727               var baseEntities = {};
73728               var base = _stack[0];
73729
73730               var s = _stack.map(function (i) {
73731                 var modified = [];
73732                 var deleted = [];
73733                 Object.keys(i.graph.entities).forEach(function (id) {
73734                   var entity = i.graph.entities[id];
73735
73736                   if (entity) {
73737                     var key = osmEntity.key(entity);
73738                     allEntities[key] = entity;
73739                     modified.push(key);
73740                   } else {
73741                     deleted.push(id);
73742                   } // make sure that the originals of changed or deleted entities get merged
73743                   // into the base of the _stack after restoring the data from JSON.
73744
73745
73746                   if (id in base.graph.entities) {
73747                     baseEntities[id] = base.graph.entities[id];
73748                   }
73749
73750                   if (entity && entity.nodes) {
73751                     // get originals of pre-existing child nodes
73752                     entity.nodes.forEach(function (nodeID) {
73753                       if (nodeID in base.graph.entities) {
73754                         baseEntities[nodeID] = base.graph.entities[nodeID];
73755                       }
73756                     });
73757                   } // get originals of parent entities too
73758
73759
73760                   var baseParents = base.graph._parentWays[id];
73761
73762                   if (baseParents) {
73763                     baseParents.forEach(function (parentID) {
73764                       if (parentID in base.graph.entities) {
73765                         baseEntities[parentID] = base.graph.entities[parentID];
73766                       }
73767                     });
73768                   }
73769                 });
73770                 var x = {};
73771                 if (modified.length) x.modified = modified;
73772                 if (deleted.length) x.deleted = deleted;
73773                 if (i.imageryUsed) x.imageryUsed = i.imageryUsed;
73774                 if (i.photoOverlaysUsed) x.photoOverlaysUsed = i.photoOverlaysUsed;
73775                 if (i.annotation) x.annotation = i.annotation;
73776                 if (i.transform) x.transform = i.transform;
73777                 if (i.selectedIDs) x.selectedIDs = i.selectedIDs;
73778                 return x;
73779               });
73780
73781               return JSON.stringify({
73782                 version: 3,
73783                 entities: Object.values(allEntities),
73784                 baseEntities: Object.values(baseEntities),
73785                 stack: s,
73786                 nextIDs: osmEntity.id.next,
73787                 index: _index,
73788                 // note the time the changes were saved
73789                 timestamp: new Date().getTime()
73790               });
73791             },
73792             fromJSON: function fromJSON(json, loadChildNodes) {
73793               var h = JSON.parse(json);
73794               var loadComplete = true;
73795               osmEntity.id.next = h.nextIDs;
73796               _index = h.index;
73797
73798               if (h.version === 2 || h.version === 3) {
73799                 var allEntities = {};
73800                 h.entities.forEach(function (entity) {
73801                   allEntities[osmEntity.key(entity)] = osmEntity(entity);
73802                 });
73803
73804                 if (h.version === 3) {
73805                   // This merges originals for changed entities into the base of
73806                   // the _stack even if the current _stack doesn't have them (for
73807                   // example when iD has been restarted in a different region)
73808                   var baseEntities = h.baseEntities.map(function (d) {
73809                     return osmEntity(d);
73810                   });
73811
73812                   var stack = _stack.map(function (state) {
73813                     return state.graph;
73814                   });
73815
73816                   _stack[0].graph.rebase(baseEntities, stack, true);
73817
73818                   _tree.rebase(baseEntities, true); // When we restore a modified way, we also need to fetch any missing
73819                   // childnodes that would normally have been downloaded with it.. #2142
73820
73821
73822                   if (loadChildNodes) {
73823                     var osm = context.connection();
73824                     var baseWays = baseEntities.filter(function (e) {
73825                       return e.type === 'way';
73826                     });
73827                     var nodeIDs = baseWays.reduce(function (acc, way) {
73828                       return utilArrayUnion(acc, way.nodes);
73829                     }, []);
73830                     var missing = nodeIDs.filter(function (n) {
73831                       return !_stack[0].graph.hasEntity(n);
73832                     });
73833
73834                     if (missing.length && osm) {
73835                       loadComplete = false;
73836                       context.map().redrawEnable(false);
73837                       var loading = uiLoading(context).blocking(true);
73838                       context.container().call(loading);
73839
73840                       var childNodesLoaded = function childNodesLoaded(err, result) {
73841                         if (!err) {
73842                           var visibleGroups = utilArrayGroupBy(result.data, 'visible');
73843                           var visibles = visibleGroups["true"] || []; // alive nodes
73844
73845                           var invisibles = visibleGroups["false"] || []; // deleted nodes
73846
73847                           if (visibles.length) {
73848                             var visibleIDs = visibles.map(function (entity) {
73849                               return entity.id;
73850                             });
73851
73852                             var stack = _stack.map(function (state) {
73853                               return state.graph;
73854                             });
73855
73856                             missing = utilArrayDifference(missing, visibleIDs);
73857
73858                             _stack[0].graph.rebase(visibles, stack, true);
73859
73860                             _tree.rebase(visibles, true);
73861                           } // fetch older versions of nodes that were deleted..
73862
73863
73864                           invisibles.forEach(function (entity) {
73865                             osm.loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded);
73866                           });
73867                         }
73868
73869                         if (err || !missing.length) {
73870                           loading.close();
73871                           context.map().redrawEnable(true);
73872                           dispatch.call('change');
73873                           dispatch.call('restore', this);
73874                         }
73875                       };
73876
73877                       osm.loadMultiple(missing, childNodesLoaded);
73878                     }
73879                   }
73880                 }
73881
73882                 _stack = h.stack.map(function (d) {
73883                   var entities = {},
73884                       entity;
73885
73886                   if (d.modified) {
73887                     d.modified.forEach(function (key) {
73888                       entity = allEntities[key];
73889                       entities[entity.id] = entity;
73890                     });
73891                   }
73892
73893                   if (d.deleted) {
73894                     d.deleted.forEach(function (id) {
73895                       entities[id] = undefined;
73896                     });
73897                   }
73898
73899                   return {
73900                     graph: coreGraph(_stack[0].graph).load(entities),
73901                     annotation: d.annotation,
73902                     imageryUsed: d.imageryUsed,
73903                     photoOverlaysUsed: d.photoOverlaysUsed,
73904                     transform: d.transform,
73905                     selectedIDs: d.selectedIDs
73906                   };
73907                 });
73908               } else {
73909                 // original version
73910                 _stack = h.stack.map(function (d) {
73911                   var entities = {};
73912
73913                   for (var i in d.entities) {
73914                     var entity = d.entities[i];
73915                     entities[i] = entity === 'undefined' ? undefined : osmEntity(entity);
73916                   }
73917
73918                   d.graph = coreGraph(_stack[0].graph).load(entities);
73919                   return d;
73920                 });
73921               }
73922
73923               var transform = _stack[_index].transform;
73924
73925               if (transform) {
73926                 context.map().transformEase(transform, 0); // 0 = immediate, no easing
73927               }
73928
73929               if (loadComplete) {
73930                 dispatch.call('change');
73931                 dispatch.call('restore', this);
73932               }
73933
73934               return history;
73935             },
73936             lock: function lock() {
73937               return _lock.lock();
73938             },
73939             unlock: function unlock() {
73940               _lock.unlock();
73941             },
73942             save: function save() {
73943               if (_lock.locked() && // don't overwrite existing, unresolved changes
73944               !_hasUnresolvedRestorableChanges) {
73945                 var success = corePreferences(getKey('saved_history'), history.toJSON() || null);
73946                 if (!success) dispatch.call('storage_error');
73947               }
73948
73949               return history;
73950             },
73951             // delete the history version saved in localStorage
73952             clearSaved: function clearSaved() {
73953               context.debouncedSave.cancel();
73954
73955               if (_lock.locked()) {
73956                 _hasUnresolvedRestorableChanges = false;
73957                 corePreferences(getKey('saved_history'), null); // clear the changeset metadata associated with the saved history
73958
73959                 corePreferences('comment', null);
73960                 corePreferences('hashtags', null);
73961                 corePreferences('source', null);
73962               }
73963
73964               return history;
73965             },
73966             savedHistoryJSON: function savedHistoryJSON() {
73967               return corePreferences(getKey('saved_history'));
73968             },
73969             hasRestorableChanges: function hasRestorableChanges() {
73970               return _hasUnresolvedRestorableChanges;
73971             },
73972             // load history from a version stored in localStorage
73973             restore: function restore() {
73974               if (_lock.locked()) {
73975                 _hasUnresolvedRestorableChanges = false;
73976                 var json = this.savedHistoryJSON();
73977                 if (json) history.fromJSON(json, true);
73978               }
73979             },
73980             _getKey: getKey
73981           };
73982           history.reset();
73983           return utilRebind(history, dispatch, 'on');
73984         }
73985
73986         /**
73987          * Look for roads that can be connected to other roads with a short extension
73988          */
73989
73990         function validationAlmostJunction(context) {
73991           var type = 'almost_junction';
73992           var EXTEND_TH_METERS = 5;
73993           var WELD_TH_METERS = 0.75; // Comes from considering bounding case of parallel ways
73994
73995           var CLOSE_NODE_TH = EXTEND_TH_METERS - WELD_TH_METERS; // Comes from considering bounding case of perpendicular ways
73996
73997           var SIG_ANGLE_TH = Math.atan(WELD_TH_METERS / EXTEND_TH_METERS);
73998
73999           function isHighway(entity) {
74000             return entity.type === 'way' && osmRoutableHighwayTagValues[entity.tags.highway];
74001           }
74002
74003           function isTaggedAsNotContinuing(node) {
74004             return node.tags.noexit === 'yes' || node.tags.amenity === 'parking_entrance' || node.tags.entrance && node.tags.entrance !== 'no';
74005           }
74006
74007           var validation = function checkAlmostJunction(entity, graph) {
74008             if (!isHighway(entity)) return [];
74009             if (entity.isDegenerate()) return [];
74010             var tree = context.history().tree();
74011             var extendableNodeInfos = findConnectableEndNodesByExtension(entity);
74012             var issues = [];
74013             extendableNodeInfos.forEach(function (extendableNodeInfo) {
74014               issues.push(new validationIssue({
74015                 type: type,
74016                 subtype: 'highway-highway',
74017                 severity: 'warning',
74018                 message: function message(context) {
74019                   var entity1 = context.hasEntity(this.entityIds[0]);
74020
74021                   if (this.entityIds[0] === this.entityIds[2]) {
74022                     return entity1 ? _t.html('issues.almost_junction.self.message', {
74023                       feature: utilDisplayLabel(entity1, context.graph())
74024                     }) : '';
74025                   } else {
74026                     var entity2 = context.hasEntity(this.entityIds[2]);
74027                     return entity1 && entity2 ? _t.html('issues.almost_junction.message', {
74028                       feature: utilDisplayLabel(entity1, context.graph()),
74029                       feature2: utilDisplayLabel(entity2, context.graph())
74030                     }) : '';
74031                   }
74032                 },
74033                 reference: showReference,
74034                 entityIds: [entity.id, extendableNodeInfo.node.id, extendableNodeInfo.wid],
74035                 loc: extendableNodeInfo.node.loc,
74036                 hash: JSON.stringify(extendableNodeInfo.node.loc),
74037                 data: {
74038                   midId: extendableNodeInfo.mid.id,
74039                   edge: extendableNodeInfo.edge,
74040                   cross_loc: extendableNodeInfo.cross_loc
74041                 },
74042                 dynamicFixes: makeFixes
74043               }));
74044             });
74045             return issues;
74046
74047             function makeFixes(context) {
74048               var fixes = [new validationIssueFix({
74049                 icon: 'iD-icon-abutment',
74050                 title: _t.html('issues.fix.connect_features.title'),
74051                 onClick: function onClick(context) {
74052                   var annotation = _t('issues.fix.connect_almost_junction.annotation');
74053
74054                   var _this$issue$entityIds = _slicedToArray(this.issue.entityIds, 3),
74055                       endNodeId = _this$issue$entityIds[1],
74056                       crossWayId = _this$issue$entityIds[2];
74057
74058                   var midNode = context.entity(this.issue.data.midId);
74059                   var endNode = context.entity(endNodeId);
74060                   var crossWay = context.entity(crossWayId); // When endpoints are close, just join if resulting small change in angle (#7201)
74061
74062                   var nearEndNodes = findNearbyEndNodes(endNode, crossWay);
74063
74064                   if (nearEndNodes.length > 0) {
74065                     var collinear = findSmallJoinAngle(midNode, endNode, nearEndNodes);
74066
74067                     if (collinear) {
74068                       context.perform(actionMergeNodes([collinear.id, endNode.id], collinear.loc), annotation);
74069                       return;
74070                     }
74071                   }
74072
74073                   var targetEdge = this.issue.data.edge;
74074                   var crossLoc = this.issue.data.cross_loc;
74075                   var edgeNodes = [context.entity(targetEdge[0]), context.entity(targetEdge[1])];
74076                   var closestNodeInfo = geoSphericalClosestNode(edgeNodes, crossLoc); // already a point nearby, just connect to that
74077
74078                   if (closestNodeInfo.distance < WELD_TH_METERS) {
74079                     context.perform(actionMergeNodes([closestNodeInfo.node.id, endNode.id], closestNodeInfo.node.loc), annotation); // else add the end node to the edge way
74080                   } else {
74081                     context.perform(actionAddMidpoint({
74082                       loc: crossLoc,
74083                       edge: targetEdge
74084                     }, endNode), annotation);
74085                   }
74086                 }
74087               })];
74088               var node = context.hasEntity(this.entityIds[1]);
74089
74090               if (node && !node.hasInterestingTags()) {
74091                 // node has no descriptive tags, suggest noexit fix
74092                 fixes.push(new validationIssueFix({
74093                   icon: 'maki-barrier',
74094                   title: _t.html('issues.fix.tag_as_disconnected.title'),
74095                   onClick: function onClick(context) {
74096                     var nodeID = this.issue.entityIds[1];
74097                     var tags = Object.assign({}, context.entity(nodeID).tags);
74098                     tags.noexit = 'yes';
74099                     context.perform(actionChangeTags(nodeID, tags), _t('issues.fix.tag_as_disconnected.annotation'));
74100                   }
74101                 }));
74102               }
74103
74104               return fixes;
74105             }
74106
74107             function showReference(selection) {
74108               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.almost_junction.highway-highway.reference'));
74109             }
74110
74111             function isExtendableCandidate(node, way) {
74112               // can not accurately test vertices on tiles not downloaded from osm - #5938
74113               var osm = services.osm;
74114
74115               if (osm && !osm.isDataLoaded(node.loc)) {
74116                 return false;
74117               }
74118
74119               if (isTaggedAsNotContinuing(node) || graph.parentWays(node).length !== 1) {
74120                 return false;
74121               }
74122
74123               var occurrences = 0;
74124
74125               for (var index in way.nodes) {
74126                 if (way.nodes[index] === node.id) {
74127                   occurrences += 1;
74128
74129                   if (occurrences > 1) {
74130                     return false;
74131                   }
74132                 }
74133               }
74134
74135               return true;
74136             }
74137
74138             function findConnectableEndNodesByExtension(way) {
74139               var results = [];
74140               if (way.isClosed()) return results;
74141               var testNodes;
74142               var indices = [0, way.nodes.length - 1];
74143               indices.forEach(function (nodeIndex) {
74144                 var nodeID = way.nodes[nodeIndex];
74145                 var node = graph.entity(nodeID);
74146                 if (!isExtendableCandidate(node, way)) return;
74147                 var connectionInfo = canConnectByExtend(way, nodeIndex);
74148                 if (!connectionInfo) return;
74149                 testNodes = graph.childNodes(way).slice(); // shallow copy
74150
74151                 testNodes[nodeIndex] = testNodes[nodeIndex].move(connectionInfo.cross_loc); // don't flag issue if connecting the ways would cause self-intersection
74152
74153                 if (geoHasSelfIntersections(testNodes, nodeID)) return;
74154                 results.push(connectionInfo);
74155               });
74156               return results;
74157             }
74158
74159             function findNearbyEndNodes(node, way) {
74160               return [way.nodes[0], way.nodes[way.nodes.length - 1]].map(function (d) {
74161                 return graph.entity(d);
74162               }).filter(function (d) {
74163                 // Node cannot be near to itself, but other endnode of same way could be
74164                 return d.id !== node.id && geoSphericalDistance(node.loc, d.loc) <= CLOSE_NODE_TH;
74165               });
74166             }
74167
74168             function findSmallJoinAngle(midNode, tipNode, endNodes) {
74169               // Both nodes could be close, so want to join whichever is closest to collinear
74170               var joinTo;
74171               var minAngle = Infinity; // Checks midNode -> tipNode -> endNode for collinearity
74172
74173               endNodes.forEach(function (endNode) {
74174                 var a1 = geoAngle(midNode, tipNode, context.projection) + Math.PI;
74175                 var a2 = geoAngle(midNode, endNode, context.projection) + Math.PI;
74176                 var diff = Math.max(a1, a2) - Math.min(a1, a2);
74177
74178                 if (diff < minAngle) {
74179                   joinTo = endNode;
74180                   minAngle = diff;
74181                 }
74182               });
74183               /* Threshold set by considering right angle triangle
74184               based on node joining threshold and extension distance */
74185
74186               if (minAngle <= SIG_ANGLE_TH) return joinTo;
74187               return null;
74188             }
74189
74190             function hasTag(tags, key) {
74191               return tags[key] !== undefined && tags[key] !== 'no';
74192             }
74193
74194             function canConnectWays(way, way2) {
74195               // allow self-connections
74196               if (way.id === way2.id) return true; // if one is bridge or tunnel, both must be bridge or tunnel
74197
74198               if ((hasTag(way.tags, 'bridge') || hasTag(way2.tags, 'bridge')) && !(hasTag(way.tags, 'bridge') && hasTag(way2.tags, 'bridge'))) return false;
74199               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
74200
74201               var layer1 = way.tags.layer || '0',
74202                   layer2 = way2.tags.layer || '0';
74203               if (layer1 !== layer2) return false;
74204               var level1 = way.tags.level || '0',
74205                   level2 = way2.tags.level || '0';
74206               if (level1 !== level2) return false;
74207               return true;
74208             }
74209
74210             function canConnectByExtend(way, endNodeIdx) {
74211               var tipNid = way.nodes[endNodeIdx]; // the 'tip' node for extension point
74212
74213               var midNid = endNodeIdx === 0 ? way.nodes[1] : way.nodes[way.nodes.length - 2]; // the other node of the edge
74214
74215               var tipNode = graph.entity(tipNid);
74216               var midNode = graph.entity(midNid);
74217               var lon = tipNode.loc[0];
74218               var lat = tipNode.loc[1];
74219               var lon_range = geoMetersToLon(EXTEND_TH_METERS, lat) / 2;
74220               var lat_range = geoMetersToLat(EXTEND_TH_METERS) / 2;
74221               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
74222
74223               var edgeLen = geoSphericalDistance(midNode.loc, tipNode.loc);
74224               var t = EXTEND_TH_METERS / edgeLen + 1.0;
74225               var extTipLoc = geoVecInterp(midNode.loc, tipNode.loc, t); // then, check if the extension part [tipNode.loc -> extTipLoc] intersects any other ways
74226
74227               var segmentInfos = tree.waySegments(queryExtent, graph);
74228
74229               for (var i = 0; i < segmentInfos.length; i++) {
74230                 var segmentInfo = segmentInfos[i];
74231                 var way2 = graph.entity(segmentInfo.wayId);
74232                 if (!isHighway(way2)) continue;
74233                 if (!canConnectWays(way, way2)) continue;
74234                 var nAid = segmentInfo.nodes[0],
74235                     nBid = segmentInfo.nodes[1];
74236                 if (nAid === tipNid || nBid === tipNid) continue;
74237                 var nA = graph.entity(nAid),
74238                     nB = graph.entity(nBid);
74239                 var crossLoc = geoLineIntersection([tipNode.loc, extTipLoc], [nA.loc, nB.loc]);
74240
74241                 if (crossLoc) {
74242                   return {
74243                     mid: midNode,
74244                     node: tipNode,
74245                     wid: way2.id,
74246                     edge: [nA.id, nB.id],
74247                     cross_loc: crossLoc
74248                   };
74249                 }
74250               }
74251
74252               return null;
74253             }
74254           };
74255
74256           validation.type = type;
74257           return validation;
74258         }
74259
74260         function validationCloseNodes(context) {
74261           var type = 'close_nodes';
74262           var pointThresholdMeters = 0.2;
74263
74264           var validation = function validation(entity, graph) {
74265             if (entity.type === 'node') {
74266               return getIssuesForNode(entity);
74267             } else if (entity.type === 'way') {
74268               return getIssuesForWay(entity);
74269             }
74270
74271             return [];
74272
74273             function getIssuesForNode(node) {
74274               var parentWays = graph.parentWays(node);
74275
74276               if (parentWays.length) {
74277                 return getIssuesForVertex(node, parentWays);
74278               } else {
74279                 return getIssuesForDetachedPoint(node);
74280               }
74281             }
74282
74283             function wayTypeFor(way) {
74284               if (way.tags.boundary && way.tags.boundary !== 'no') return 'boundary';
74285               if (way.tags.indoor && way.tags.indoor !== 'no') return 'indoor';
74286               if (way.tags.building && way.tags.building !== 'no' || way.tags['building:part'] && way.tags['building:part'] !== 'no') return 'building';
74287               if (osmPathHighwayTagValues[way.tags.highway]) return 'path';
74288               var parentRelations = graph.parentRelations(way);
74289
74290               for (var i in parentRelations) {
74291                 var relation = parentRelations[i];
74292                 if (relation.tags.type === 'boundary') return 'boundary';
74293
74294                 if (relation.isMultipolygon()) {
74295                   if (relation.tags.indoor && relation.tags.indoor !== 'no') return 'indoor';
74296                   if (relation.tags.building && relation.tags.building !== 'no' || relation.tags['building:part'] && relation.tags['building:part'] !== 'no') return 'building';
74297                 }
74298               }
74299
74300               return 'other';
74301             }
74302
74303             function shouldCheckWay(way) {
74304               // don't flag issues where merging would create degenerate ways
74305               if (way.nodes.length <= 2 || way.isClosed() && way.nodes.length <= 4) return false;
74306               var bbox = way.extent(graph).bbox();
74307               var hypotenuseMeters = geoSphericalDistance([bbox.minX, bbox.minY], [bbox.maxX, bbox.maxY]); // don't flag close nodes in very small ways
74308
74309               if (hypotenuseMeters < 1.5) return false;
74310               return true;
74311             }
74312
74313             function getIssuesForWay(way) {
74314               if (!shouldCheckWay(way)) return [];
74315               var issues = [],
74316                   nodes = graph.childNodes(way);
74317
74318               for (var i = 0; i < nodes.length - 1; i++) {
74319                 var node1 = nodes[i];
74320                 var node2 = nodes[i + 1];
74321                 var issue = getWayIssueIfAny(node1, node2, way);
74322                 if (issue) issues.push(issue);
74323               }
74324
74325               return issues;
74326             }
74327
74328             function getIssuesForVertex(node, parentWays) {
74329               var issues = [];
74330
74331               function checkForCloseness(node1, node2, way) {
74332                 var issue = getWayIssueIfAny(node1, node2, way);
74333                 if (issue) issues.push(issue);
74334               }
74335
74336               for (var i = 0; i < parentWays.length; i++) {
74337                 var parentWay = parentWays[i];
74338                 if (!shouldCheckWay(parentWay)) continue;
74339                 var lastIndex = parentWay.nodes.length - 1;
74340
74341                 for (var j = 0; j < parentWay.nodes.length; j++) {
74342                   if (j !== 0) {
74343                     if (parentWay.nodes[j - 1] === node.id) {
74344                       checkForCloseness(node, graph.entity(parentWay.nodes[j]), parentWay);
74345                     }
74346                   }
74347
74348                   if (j !== lastIndex) {
74349                     if (parentWay.nodes[j + 1] === node.id) {
74350                       checkForCloseness(graph.entity(parentWay.nodes[j]), node, parentWay);
74351                     }
74352                   }
74353                 }
74354               }
74355
74356               return issues;
74357             }
74358
74359             function thresholdMetersForWay(way) {
74360               if (!shouldCheckWay(way)) return 0;
74361               var wayType = wayTypeFor(way); // don't flag boundaries since they might be highly detailed and can't be easily verified
74362
74363               if (wayType === 'boundary') return 0; // expect some features to be mapped with higher levels of detail
74364
74365               if (wayType === 'indoor') return 0.01;
74366               if (wayType === 'building') return 0.05;
74367               if (wayType === 'path') return 0.1;
74368               return 0.2;
74369             }
74370
74371             function getIssuesForDetachedPoint(node) {
74372               var issues = [];
74373               var lon = node.loc[0];
74374               var lat = node.loc[1];
74375               var lon_range = geoMetersToLon(pointThresholdMeters, lat) / 2;
74376               var lat_range = geoMetersToLat(pointThresholdMeters) / 2;
74377               var queryExtent = geoExtent([[lon - lon_range, lat - lat_range], [lon + lon_range, lat + lat_range]]);
74378               var intersected = context.history().tree().intersects(queryExtent, graph);
74379
74380               for (var j = 0; j < intersected.length; j++) {
74381                 var nearby = intersected[j];
74382                 if (nearby.id === node.id) continue;
74383                 if (nearby.type !== 'node' || nearby.geometry(graph) !== 'point') continue;
74384
74385                 if (nearby.loc === node.loc || geoSphericalDistance(node.loc, nearby.loc) < pointThresholdMeters) {
74386                   // allow very close points if tags indicate the z-axis might vary
74387                   var zAxisKeys = {
74388                     layer: true,
74389                     level: true,
74390                     'addr:housenumber': true,
74391                     'addr:unit': true
74392                   };
74393                   var zAxisDifferentiates = false;
74394
74395                   for (var key in zAxisKeys) {
74396                     var nodeValue = node.tags[key] || '0';
74397                     var nearbyValue = nearby.tags[key] || '0';
74398
74399                     if (nodeValue !== nearbyValue) {
74400                       zAxisDifferentiates = true;
74401                       break;
74402                     }
74403                   }
74404
74405                   if (zAxisDifferentiates) continue;
74406                   issues.push(new validationIssue({
74407                     type: type,
74408                     subtype: 'detached',
74409                     severity: 'warning',
74410                     message: function message(context) {
74411                       var entity = context.hasEntity(this.entityIds[0]),
74412                           entity2 = context.hasEntity(this.entityIds[1]);
74413                       return entity && entity2 ? _t.html('issues.close_nodes.detached.message', {
74414                         feature: utilDisplayLabel(entity, context.graph()),
74415                         feature2: utilDisplayLabel(entity2, context.graph())
74416                       }) : '';
74417                     },
74418                     reference: showReference,
74419                     entityIds: [node.id, nearby.id],
74420                     dynamicFixes: function dynamicFixes() {
74421                       return [new validationIssueFix({
74422                         icon: 'iD-operation-disconnect',
74423                         title: _t.html('issues.fix.move_points_apart.title')
74424                       }), new validationIssueFix({
74425                         icon: 'iD-icon-layers',
74426                         title: _t.html('issues.fix.use_different_layers_or_levels.title')
74427                       })];
74428                     }
74429                   }));
74430                 }
74431               }
74432
74433               return issues;
74434
74435               function showReference(selection) {
74436                 var referenceText = _t('issues.close_nodes.detached.reference');
74437                 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').html(referenceText);
74438               }
74439             }
74440
74441             function getWayIssueIfAny(node1, node2, way) {
74442               if (node1.id === node2.id || node1.hasInterestingTags() && node2.hasInterestingTags()) {
74443                 return null;
74444               }
74445
74446               if (node1.loc !== node2.loc) {
74447                 var parentWays1 = graph.parentWays(node1);
74448                 var parentWays2 = new Set(graph.parentWays(node2));
74449                 var sharedWays = parentWays1.filter(function (parentWay) {
74450                   return parentWays2.has(parentWay);
74451                 });
74452                 var thresholds = sharedWays.map(function (parentWay) {
74453                   return thresholdMetersForWay(parentWay);
74454                 });
74455                 var threshold = Math.min.apply(Math, _toConsumableArray(thresholds));
74456                 var distance = geoSphericalDistance(node1.loc, node2.loc);
74457                 if (distance > threshold) return null;
74458               }
74459
74460               return new validationIssue({
74461                 type: type,
74462                 subtype: 'vertices',
74463                 severity: 'warning',
74464                 message: function message(context) {
74465                   var entity = context.hasEntity(this.entityIds[0]);
74466                   return entity ? _t.html('issues.close_nodes.message', {
74467                     way: utilDisplayLabel(entity, context.graph())
74468                   }) : '';
74469                 },
74470                 reference: showReference,
74471                 entityIds: [way.id, node1.id, node2.id],
74472                 loc: node1.loc,
74473                 dynamicFixes: function dynamicFixes() {
74474                   return [new validationIssueFix({
74475                     icon: 'iD-icon-plus',
74476                     title: _t.html('issues.fix.merge_points.title'),
74477                     onClick: function onClick(context) {
74478                       var entityIds = this.issue.entityIds;
74479                       var action = actionMergeNodes([entityIds[1], entityIds[2]]);
74480                       context.perform(action, _t('issues.fix.merge_close_vertices.annotation'));
74481                     }
74482                   }), new validationIssueFix({
74483                     icon: 'iD-operation-disconnect',
74484                     title: _t.html('issues.fix.move_points_apart.title')
74485                   })];
74486                 }
74487               });
74488
74489               function showReference(selection) {
74490                 var referenceText = _t('issues.close_nodes.reference');
74491                 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').html(referenceText);
74492               }
74493             }
74494           };
74495
74496           validation.type = type;
74497           return validation;
74498         }
74499
74500         function validationCrossingWays(context) {
74501           var type = 'crossing_ways'; // returns the way or its parent relation, whichever has a useful feature type
74502
74503           function getFeatureWithFeatureTypeTagsForWay(way, graph) {
74504             if (getFeatureType(way, graph) === null) {
74505               // if the way doesn't match a feature type, check its parent relations
74506               var parentRels = graph.parentRelations(way);
74507
74508               for (var i = 0; i < parentRels.length; i++) {
74509                 var rel = parentRels[i];
74510
74511                 if (getFeatureType(rel, graph) !== null) {
74512                   return rel;
74513                 }
74514               }
74515             }
74516
74517             return way;
74518           }
74519
74520           function hasTag(tags, key) {
74521             return tags[key] !== undefined && tags[key] !== 'no';
74522           }
74523
74524           function taggedAsIndoor(tags) {
74525             return hasTag(tags, 'indoor') || hasTag(tags, 'level') || tags.highway === 'corridor';
74526           }
74527
74528           function allowsBridge(featureType) {
74529             return featureType === 'highway' || featureType === 'railway' || featureType === 'waterway';
74530           }
74531
74532           function allowsTunnel(featureType) {
74533             return featureType === 'highway' || featureType === 'railway' || featureType === 'waterway';
74534           } // discard
74535
74536
74537           var ignoredBuildings = {
74538             demolished: true,
74539             dismantled: true,
74540             proposed: true,
74541             razed: true
74542           };
74543
74544           function getFeatureType(entity, graph) {
74545             var geometry = entity.geometry(graph);
74546             if (geometry !== 'line' && geometry !== 'area') return null;
74547             var tags = entity.tags;
74548             if (hasTag(tags, 'building') && !ignoredBuildings[tags.building]) return 'building';
74549             if (hasTag(tags, 'highway') && osmRoutableHighwayTagValues[tags.highway]) return 'highway'; // don't check railway or waterway areas
74550
74551             if (geometry !== 'line') return null;
74552             if (hasTag(tags, 'railway') && osmRailwayTrackTagValues[tags.railway]) return 'railway';
74553             if (hasTag(tags, 'waterway') && osmFlowingWaterwayTagValues[tags.waterway]) return 'waterway';
74554             return null;
74555           }
74556
74557           function isLegitCrossing(tags1, featureType1, tags2, featureType2) {
74558             // assume 0 by default
74559             var level1 = tags1.level || '0';
74560             var level2 = tags2.level || '0';
74561
74562             if (taggedAsIndoor(tags1) && taggedAsIndoor(tags2) && level1 !== level2) {
74563               // assume features don't interact if they're indoor on different levels
74564               return true;
74565             } // assume 0 by default; don't use way.layer() since we account for structures here
74566
74567
74568             var layer1 = tags1.layer || '0';
74569             var layer2 = tags2.layer || '0';
74570
74571             if (allowsBridge(featureType1) && allowsBridge(featureType2)) {
74572               if (hasTag(tags1, 'bridge') && !hasTag(tags2, 'bridge')) return true;
74573               if (!hasTag(tags1, 'bridge') && hasTag(tags2, 'bridge')) return true; // crossing bridges must use different layers
74574
74575               if (hasTag(tags1, 'bridge') && hasTag(tags2, 'bridge') && layer1 !== layer2) return true;
74576             } else if (allowsBridge(featureType1) && hasTag(tags1, 'bridge')) return true;else if (allowsBridge(featureType2) && hasTag(tags2, 'bridge')) return true;
74577
74578             if (allowsTunnel(featureType1) && allowsTunnel(featureType2)) {
74579               if (hasTag(tags1, 'tunnel') && !hasTag(tags2, 'tunnel')) return true;
74580               if (!hasTag(tags1, 'tunnel') && hasTag(tags2, 'tunnel')) return true; // crossing tunnels must use different layers
74581
74582               if (hasTag(tags1, 'tunnel') && hasTag(tags2, 'tunnel') && layer1 !== layer2) return true;
74583             } 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
74584
74585
74586             if (featureType1 === 'waterway' && featureType2 === 'highway' && tags2.man_made === 'pier') return true;
74587             if (featureType2 === 'waterway' && featureType1 === 'highway' && tags1.man_made === 'pier') return true;
74588
74589             if (featureType1 === 'building' || featureType2 === 'building') {
74590               // for building crossings, different layers are enough
74591               if (layer1 !== layer2) return true;
74592             }
74593
74594             return false;
74595           } // highway values for which we shouldn't recommend connecting to waterways
74596
74597
74598           var highwaysDisallowingFords = {
74599             motorway: true,
74600             motorway_link: true,
74601             trunk: true,
74602             trunk_link: true,
74603             primary: true,
74604             primary_link: true,
74605             secondary: true,
74606             secondary_link: true
74607           };
74608           var nonCrossingHighways = {
74609             track: true
74610           };
74611
74612           function tagsForConnectionNodeIfAllowed(entity1, entity2, graph) {
74613             var featureType1 = getFeatureType(entity1, graph);
74614             var featureType2 = getFeatureType(entity2, graph);
74615             var geometry1 = entity1.geometry(graph);
74616             var geometry2 = entity2.geometry(graph);
74617             var bothLines = geometry1 === 'line' && geometry2 === 'line';
74618
74619             if (featureType1 === featureType2) {
74620               if (featureType1 === 'highway') {
74621                 var entity1IsPath = osmPathHighwayTagValues[entity1.tags.highway];
74622                 var entity2IsPath = osmPathHighwayTagValues[entity2.tags.highway];
74623
74624                 if ((entity1IsPath || entity2IsPath) && entity1IsPath !== entity2IsPath) {
74625                   // one feature is a path but not both
74626                   var roadFeature = entity1IsPath ? entity2 : entity1;
74627
74628                   if (nonCrossingHighways[roadFeature.tags.highway]) {
74629                     // don't mark path connections with certain roads as crossings
74630                     return {};
74631                   }
74632
74633                   var pathFeature = entity1IsPath ? entity1 : entity2;
74634
74635                   if (['marked', 'unmarked'].indexOf(pathFeature.tags.crossing) !== -1) {
74636                     // if the path is a crossing, match the crossing type
74637                     return bothLines ? {
74638                       highway: 'crossing',
74639                       crossing: pathFeature.tags.crossing
74640                     } : {};
74641                   } // don't add a `crossing` subtag to ambiguous crossings
74642
74643
74644                   return bothLines ? {
74645                     highway: 'crossing'
74646                   } : {};
74647                 }
74648
74649                 return {};
74650               }
74651
74652               if (featureType1 === 'waterway') return {};
74653               if (featureType1 === 'railway') return {};
74654             } else {
74655               var featureTypes = [featureType1, featureType2];
74656
74657               if (featureTypes.indexOf('highway') !== -1) {
74658                 if (featureTypes.indexOf('railway') !== -1) {
74659                   if (!bothLines) return {};
74660                   var isTram = entity1.tags.railway === 'tram' || entity2.tags.railway === 'tram';
74661
74662                   if (osmPathHighwayTagValues[entity1.tags.highway] || osmPathHighwayTagValues[entity2.tags.highway]) {
74663                     // path-tram connections use this tag
74664                     if (isTram) return {
74665                       railway: 'tram_crossing'
74666                     }; // other path-rail connections use this tag
74667
74668                     return {
74669                       railway: 'crossing'
74670                     };
74671                   } else {
74672                     // path-tram connections use this tag
74673                     if (isTram) return {
74674                       railway: 'tram_level_crossing'
74675                     }; // other road-rail connections use this tag
74676
74677                     return {
74678                       railway: 'level_crossing'
74679                     };
74680                   }
74681                 }
74682
74683                 if (featureTypes.indexOf('waterway') !== -1) {
74684                   // do not allow fords on structures
74685                   if (hasTag(entity1.tags, 'tunnel') && hasTag(entity2.tags, 'tunnel')) return null;
74686                   if (hasTag(entity1.tags, 'bridge') && hasTag(entity2.tags, 'bridge')) return null;
74687
74688                   if (highwaysDisallowingFords[entity1.tags.highway] || highwaysDisallowingFords[entity2.tags.highway]) {
74689                     // do not allow fords on major highways
74690                     return null;
74691                   }
74692
74693                   return bothLines ? {
74694                     ford: 'yes'
74695                   } : {};
74696                 }
74697               }
74698             }
74699
74700             return null;
74701           }
74702
74703           function findCrossingsByWay(way1, graph, tree) {
74704             var edgeCrossInfos = [];
74705             if (way1.type !== 'way') return edgeCrossInfos;
74706             var taggedFeature1 = getFeatureWithFeatureTypeTagsForWay(way1, graph);
74707             var way1FeatureType = getFeatureType(taggedFeature1, graph);
74708             if (way1FeatureType === null) return edgeCrossInfos;
74709             var checkedSingleCrossingWays = {}; // declare vars ahead of time to reduce garbage collection
74710
74711             var i, j;
74712             var extent;
74713             var n1, n2, nA, nB, nAId, nBId;
74714             var segment1, segment2;
74715             var oneOnly;
74716             var segmentInfos, segment2Info, way2, taggedFeature2, way2FeatureType;
74717             var way1Nodes = graph.childNodes(way1);
74718             var comparedWays = {};
74719
74720             for (i = 0; i < way1Nodes.length - 1; i++) {
74721               n1 = way1Nodes[i];
74722               n2 = way1Nodes[i + 1];
74723               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
74724               // of overlapping ways
74725
74726               segmentInfos = tree.waySegments(extent, graph);
74727
74728               for (j = 0; j < segmentInfos.length; j++) {
74729                 segment2Info = segmentInfos[j]; // don't check for self-intersection in this validation
74730
74731                 if (segment2Info.wayId === way1.id) continue; // skip if this way was already checked and only one issue is needed
74732
74733                 if (checkedSingleCrossingWays[segment2Info.wayId]) continue; // mark this way as checked even if there are no crossings
74734
74735                 comparedWays[segment2Info.wayId] = true;
74736                 way2 = graph.hasEntity(segment2Info.wayId);
74737                 if (!way2) continue;
74738                 taggedFeature2 = getFeatureWithFeatureTypeTagsForWay(way2, graph); // only check crossing highway, waterway, building, and railway
74739
74740                 way2FeatureType = getFeatureType(taggedFeature2, graph);
74741
74742                 if (way2FeatureType === null || isLegitCrossing(taggedFeature1.tags, way1FeatureType, taggedFeature2.tags, way2FeatureType)) {
74743                   continue;
74744                 } // create only one issue for building crossings
74745
74746
74747                 oneOnly = way1FeatureType === 'building' || way2FeatureType === 'building';
74748                 nAId = segment2Info.nodes[0];
74749                 nBId = segment2Info.nodes[1];
74750
74751                 if (nAId === n1.id || nAId === n2.id || nBId === n1.id || nBId === n2.id) {
74752                   // n1 or n2 is a connection node; skip
74753                   continue;
74754                 }
74755
74756                 nA = graph.hasEntity(nAId);
74757                 if (!nA) continue;
74758                 nB = graph.hasEntity(nBId);
74759                 if (!nB) continue;
74760                 segment1 = [n1.loc, n2.loc];
74761                 segment2 = [nA.loc, nB.loc];
74762                 var point = geoLineIntersection(segment1, segment2);
74763
74764                 if (point) {
74765                   edgeCrossInfos.push({
74766                     wayInfos: [{
74767                       way: way1,
74768                       featureType: way1FeatureType,
74769                       edge: [n1.id, n2.id]
74770                     }, {
74771                       way: way2,
74772                       featureType: way2FeatureType,
74773                       edge: [nA.id, nB.id]
74774                     }],
74775                     crossPoint: point
74776                   });
74777
74778                   if (oneOnly) {
74779                     checkedSingleCrossingWays[way2.id] = true;
74780                     break;
74781                   }
74782                 }
74783               }
74784             }
74785
74786             return edgeCrossInfos;
74787           }
74788
74789           function waysToCheck(entity, graph) {
74790             var featureType = getFeatureType(entity, graph);
74791             if (!featureType) return [];
74792
74793             if (entity.type === 'way') {
74794               return [entity];
74795             } else if (entity.type === 'relation') {
74796               return entity.members.reduce(function (array, member) {
74797                 if (member.type === 'way' && ( // only look at geometry ways
74798                 !member.role || member.role === 'outer' || member.role === 'inner')) {
74799                   var entity = graph.hasEntity(member.id); // don't add duplicates
74800
74801                   if (entity && array.indexOf(entity) === -1) {
74802                     array.push(entity);
74803                   }
74804                 }
74805
74806                 return array;
74807               }, []);
74808             }
74809
74810             return [];
74811           }
74812
74813           var validation = function checkCrossingWays(entity, graph) {
74814             var tree = context.history().tree();
74815             var ways = waysToCheck(entity, graph);
74816             var issues = []; // declare these here to reduce garbage collection
74817
74818             var wayIndex, crossingIndex, crossings;
74819
74820             for (wayIndex in ways) {
74821               crossings = findCrossingsByWay(ways[wayIndex], graph, tree);
74822
74823               for (crossingIndex in crossings) {
74824                 issues.push(createIssue(crossings[crossingIndex], graph));
74825               }
74826             }
74827
74828             return issues;
74829           };
74830
74831           function createIssue(crossing, graph) {
74832             // use the entities with the tags that define the feature type
74833             crossing.wayInfos.sort(function (way1Info, way2Info) {
74834               var type1 = way1Info.featureType;
74835               var type2 = way2Info.featureType;
74836
74837               if (type1 === type2) {
74838                 return utilDisplayLabel(way1Info.way, graph) > utilDisplayLabel(way2Info.way, graph);
74839               } else if (type1 === 'waterway') {
74840                 return true;
74841               } else if (type2 === 'waterway') {
74842                 return false;
74843               }
74844
74845               return type1 < type2;
74846             });
74847             var entities = crossing.wayInfos.map(function (wayInfo) {
74848               return getFeatureWithFeatureTypeTagsForWay(wayInfo.way, graph);
74849             });
74850             var edges = [crossing.wayInfos[0].edge, crossing.wayInfos[1].edge];
74851             var featureTypes = [crossing.wayInfos[0].featureType, crossing.wayInfos[1].featureType];
74852             var connectionTags = tagsForConnectionNodeIfAllowed(entities[0], entities[1], graph);
74853             var featureType1 = crossing.wayInfos[0].featureType;
74854             var featureType2 = crossing.wayInfos[1].featureType;
74855             var isCrossingIndoors = taggedAsIndoor(entities[0].tags) && taggedAsIndoor(entities[1].tags);
74856             var isCrossingTunnels = allowsTunnel(featureType1) && hasTag(entities[0].tags, 'tunnel') && allowsTunnel(featureType2) && hasTag(entities[1].tags, 'tunnel');
74857             var isCrossingBridges = allowsBridge(featureType1) && hasTag(entities[0].tags, 'bridge') && allowsBridge(featureType2) && hasTag(entities[1].tags, 'bridge');
74858             var subtype = [featureType1, featureType2].sort().join('-');
74859             var crossingTypeID = subtype;
74860
74861             if (isCrossingIndoors) {
74862               crossingTypeID = 'indoor-indoor';
74863             } else if (isCrossingTunnels) {
74864               crossingTypeID = 'tunnel-tunnel';
74865             } else if (isCrossingBridges) {
74866               crossingTypeID = 'bridge-bridge';
74867             }
74868
74869             if (connectionTags && (isCrossingIndoors || isCrossingTunnels || isCrossingBridges)) {
74870               crossingTypeID += '_connectable';
74871             } // Differentiate based on the loc rounded to 4 digits, since two ways can cross multiple times.
74872
74873
74874             var uniqueID = crossing.crossPoint[0].toFixed(4) + ',' + crossing.crossPoint[1].toFixed(4);
74875             return new validationIssue({
74876               type: type,
74877               subtype: subtype,
74878               severity: 'warning',
74879               message: function message(context) {
74880                 var graph = context.graph();
74881                 var entity1 = graph.hasEntity(this.entityIds[0]),
74882                     entity2 = graph.hasEntity(this.entityIds[1]);
74883                 return entity1 && entity2 ? _t.html('issues.crossing_ways.message', {
74884                   feature: utilDisplayLabel(entity1, graph),
74885                   feature2: utilDisplayLabel(entity2, graph)
74886                 }) : '';
74887               },
74888               reference: showReference,
74889               entityIds: entities.map(function (entity) {
74890                 return entity.id;
74891               }),
74892               data: {
74893                 edges: edges,
74894                 featureTypes: featureTypes,
74895                 connectionTags: connectionTags
74896               },
74897               hash: uniqueID,
74898               loc: crossing.crossPoint,
74899               dynamicFixes: function dynamicFixes(context) {
74900                 var mode = context.mode();
74901                 if (!mode || mode.id !== 'select' || mode.selectedIDs().length !== 1) return [];
74902                 var selectedIndex = this.entityIds[0] === mode.selectedIDs()[0] ? 0 : 1;
74903                 var selectedFeatureType = this.data.featureTypes[selectedIndex];
74904                 var otherFeatureType = this.data.featureTypes[selectedIndex === 0 ? 1 : 0];
74905                 var fixes = [];
74906
74907                 if (connectionTags) {
74908                   fixes.push(makeConnectWaysFix(this.data.connectionTags));
74909                 }
74910
74911                 if (isCrossingIndoors) {
74912                   fixes.push(new validationIssueFix({
74913                     icon: 'iD-icon-layers',
74914                     title: _t.html('issues.fix.use_different_levels.title')
74915                   }));
74916                 } else if (isCrossingTunnels || isCrossingBridges || featureType1 === 'building' || featureType2 === 'building') {
74917                   fixes.push(makeChangeLayerFix('higher'));
74918                   fixes.push(makeChangeLayerFix('lower')); // can only add bridge/tunnel if both features are lines
74919                 } else if (context.graph().geometry(this.entityIds[0]) === 'line' && context.graph().geometry(this.entityIds[1]) === 'line') {
74920                   // don't recommend adding bridges to waterways since they're uncommon
74921                   if (allowsBridge(selectedFeatureType) && selectedFeatureType !== 'waterway') {
74922                     fixes.push(makeAddBridgeOrTunnelFix('add_a_bridge', 'temaki-bridge', 'bridge'));
74923                   } // don't recommend adding tunnels under waterways since they're uncommon
74924
74925
74926                   var skipTunnelFix = otherFeatureType === 'waterway' && selectedFeatureType !== 'waterway';
74927
74928                   if (allowsTunnel(selectedFeatureType) && !skipTunnelFix) {
74929                     fixes.push(makeAddBridgeOrTunnelFix('add_a_tunnel', 'temaki-tunnel', 'tunnel'));
74930                   }
74931                 } // repositioning the features is always an option
74932
74933
74934                 fixes.push(new validationIssueFix({
74935                   icon: 'iD-operation-move',
74936                   title: _t.html('issues.fix.reposition_features.title')
74937                 }));
74938                 return fixes;
74939               }
74940             });
74941
74942             function showReference(selection) {
74943               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.crossing_ways.' + crossingTypeID + '.reference'));
74944             }
74945           }
74946
74947           function makeAddBridgeOrTunnelFix(fixTitleID, iconName, bridgeOrTunnel) {
74948             return new validationIssueFix({
74949               icon: iconName,
74950               title: _t.html('issues.fix.' + fixTitleID + '.title'),
74951               onClick: function onClick(context) {
74952                 var mode = context.mode();
74953                 if (!mode || mode.id !== 'select') return;
74954                 var selectedIDs = mode.selectedIDs();
74955                 if (selectedIDs.length !== 1) return;
74956                 var selectedWayID = selectedIDs[0];
74957                 if (!context.hasEntity(selectedWayID)) return;
74958                 var resultWayIDs = [selectedWayID];
74959                 var edge, crossedEdge, crossedWayID;
74960
74961                 if (this.issue.entityIds[0] === selectedWayID) {
74962                   edge = this.issue.data.edges[0];
74963                   crossedEdge = this.issue.data.edges[1];
74964                   crossedWayID = this.issue.entityIds[1];
74965                 } else {
74966                   edge = this.issue.data.edges[1];
74967                   crossedEdge = this.issue.data.edges[0];
74968                   crossedWayID = this.issue.entityIds[0];
74969                 }
74970
74971                 var crossingLoc = this.issue.loc;
74972                 var projection = context.projection;
74973
74974                 var action = function actionAddStructure(graph) {
74975                   var edgeNodes = [graph.entity(edge[0]), graph.entity(edge[1])];
74976                   var crossedWay = graph.hasEntity(crossedWayID); // use the explicit width of the crossed feature as the structure length, if available
74977
74978                   var structLengthMeters = crossedWay && crossedWay.tags.width && parseFloat(crossedWay.tags.width);
74979
74980                   if (!structLengthMeters) {
74981                     // if no explicit width is set, approximate the width based on the tags
74982                     structLengthMeters = crossedWay && crossedWay.impliedLineWidthMeters();
74983                   }
74984
74985                   if (structLengthMeters) {
74986                     if (getFeatureType(crossedWay, graph) === 'railway') {
74987                       // bridges over railways are generally much longer than the rail bed itself, compensate
74988                       structLengthMeters *= 2;
74989                     }
74990                   } else {
74991                     // should ideally never land here since all rail/water/road tags should have an implied width
74992                     structLengthMeters = 8;
74993                   }
74994
74995                   var a1 = geoAngle(edgeNodes[0], edgeNodes[1], projection) + Math.PI;
74996                   var a2 = geoAngle(graph.entity(crossedEdge[0]), graph.entity(crossedEdge[1]), projection) + Math.PI;
74997                   var crossingAngle = Math.max(a1, a2) - Math.min(a1, a2);
74998                   if (crossingAngle > Math.PI) crossingAngle -= Math.PI; // lengthen the structure to account for the angle of the crossing
74999
75000                   structLengthMeters = structLengthMeters / 2 / Math.sin(crossingAngle) * 2; // add padding since the structure must extend past the edges of the crossed feature
75001
75002                   structLengthMeters += 4; // clamp the length to a reasonable range
75003
75004                   structLengthMeters = Math.min(Math.max(structLengthMeters, 4), 50);
75005
75006                   function geomToProj(geoPoint) {
75007                     return [geoLonToMeters(geoPoint[0], geoPoint[1]), geoLatToMeters(geoPoint[1])];
75008                   }
75009
75010                   function projToGeom(projPoint) {
75011                     var lat = geoMetersToLat(projPoint[1]);
75012                     return [geoMetersToLon(projPoint[0], lat), lat];
75013                   }
75014
75015                   var projEdgeNode1 = geomToProj(edgeNodes[0].loc);
75016                   var projEdgeNode2 = geomToProj(edgeNodes[1].loc);
75017                   var projectedAngle = geoVecAngle(projEdgeNode1, projEdgeNode2);
75018                   var projectedCrossingLoc = geomToProj(crossingLoc);
75019                   var linearToSphericalMetersRatio = geoVecLength(projEdgeNode1, projEdgeNode2) / geoSphericalDistance(edgeNodes[0].loc, edgeNodes[1].loc);
75020
75021                   function locSphericalDistanceFromCrossingLoc(angle, distanceMeters) {
75022                     var lengthSphericalMeters = distanceMeters * linearToSphericalMetersRatio;
75023                     return projToGeom([projectedCrossingLoc[0] + Math.cos(angle) * lengthSphericalMeters, projectedCrossingLoc[1] + Math.sin(angle) * lengthSphericalMeters]);
75024                   }
75025
75026                   var endpointLocGetter1 = function endpointLocGetter1(lengthMeters) {
75027                     return locSphericalDistanceFromCrossingLoc(projectedAngle, lengthMeters);
75028                   };
75029
75030                   var endpointLocGetter2 = function endpointLocGetter2(lengthMeters) {
75031                     return locSphericalDistanceFromCrossingLoc(projectedAngle + Math.PI, lengthMeters);
75032                   }; // avoid creating very short edges from splitting too close to another node
75033
75034
75035                   var minEdgeLengthMeters = 0.55; // decide where to bound the structure along the way, splitting as necessary
75036
75037                   function determineEndpoint(edge, endNode, locGetter) {
75038                     var newNode;
75039                     var idealLengthMeters = structLengthMeters / 2; // distance between the crossing location and the end of the edge,
75040                     // the maximum length of this side of the structure
75041
75042                     var crossingToEdgeEndDistance = geoSphericalDistance(crossingLoc, endNode.loc);
75043
75044                     if (crossingToEdgeEndDistance - idealLengthMeters > minEdgeLengthMeters) {
75045                       // the edge is long enough to insert a new node
75046                       // the loc that would result in the full expected length
75047                       var idealNodeLoc = locGetter(idealLengthMeters);
75048                       newNode = osmNode();
75049                       graph = actionAddMidpoint({
75050                         loc: idealNodeLoc,
75051                         edge: edge
75052                       }, newNode)(graph);
75053                     } else {
75054                       var edgeCount = 0;
75055                       endNode.parentIntersectionWays(graph).forEach(function (way) {
75056                         way.nodes.forEach(function (nodeID) {
75057                           if (nodeID === endNode.id) {
75058                             if (endNode.id === way.first() && endNode.id !== way.last() || endNode.id === way.last() && endNode.id !== way.first()) {
75059                               edgeCount += 1;
75060                             } else {
75061                               edgeCount += 2;
75062                             }
75063                           }
75064                         });
75065                       });
75066
75067                       if (edgeCount >= 3) {
75068                         // the end node is a junction, try to leave a segment
75069                         // between it and the structure - #7202
75070                         var insetLength = crossingToEdgeEndDistance - minEdgeLengthMeters;
75071
75072                         if (insetLength > minEdgeLengthMeters) {
75073                           var insetNodeLoc = locGetter(insetLength);
75074                           newNode = osmNode();
75075                           graph = actionAddMidpoint({
75076                             loc: insetNodeLoc,
75077                             edge: edge
75078                           }, newNode)(graph);
75079                         }
75080                       }
75081                     } // if the edge is too short to subdivide as desired, then
75082                     // just bound the structure at the existing end node
75083
75084
75085                     if (!newNode) newNode = endNode;
75086                     var splitAction = actionSplit([newNode.id]).limitWays(resultWayIDs); // only split selected or created ways
75087                     // do the split
75088
75089                     graph = splitAction(graph);
75090
75091                     if (splitAction.getCreatedWayIDs().length) {
75092                       resultWayIDs.push(splitAction.getCreatedWayIDs()[0]);
75093                     }
75094
75095                     return newNode;
75096                   }
75097
75098                   var structEndNode1 = determineEndpoint(edge, edgeNodes[1], endpointLocGetter1);
75099                   var structEndNode2 = determineEndpoint([edgeNodes[0].id, structEndNode1.id], edgeNodes[0], endpointLocGetter2);
75100                   var structureWay = resultWayIDs.map(function (id) {
75101                     return graph.entity(id);
75102                   }).find(function (way) {
75103                     return way.nodes.indexOf(structEndNode1.id) !== -1 && way.nodes.indexOf(structEndNode2.id) !== -1;
75104                   });
75105                   var tags = Object.assign({}, structureWay.tags); // copy tags
75106
75107                   if (bridgeOrTunnel === 'bridge') {
75108                     tags.bridge = 'yes';
75109                     tags.layer = '1';
75110                   } else {
75111                     var tunnelValue = 'yes';
75112
75113                     if (getFeatureType(structureWay, graph) === 'waterway') {
75114                       // use `tunnel=culvert` for waterways by default
75115                       tunnelValue = 'culvert';
75116                     }
75117
75118                     tags.tunnel = tunnelValue;
75119                     tags.layer = '-1';
75120                   } // apply the structure tags to the way
75121
75122
75123                   graph = actionChangeTags(structureWay.id, tags)(graph);
75124                   return graph;
75125                 };
75126
75127                 context.perform(action, _t('issues.fix.' + fixTitleID + '.annotation'));
75128                 context.enter(modeSelect(context, resultWayIDs));
75129               }
75130             });
75131           }
75132
75133           function makeConnectWaysFix(connectionTags) {
75134             var fixTitleID = 'connect_features';
75135
75136             if (connectionTags.ford) {
75137               fixTitleID = 'connect_using_ford';
75138             }
75139
75140             return new validationIssueFix({
75141               icon: 'iD-icon-crossing',
75142               title: _t.html('issues.fix.' + fixTitleID + '.title'),
75143               onClick: function onClick(context) {
75144                 var loc = this.issue.loc;
75145                 var connectionTags = this.issue.data.connectionTags;
75146                 var edges = this.issue.data.edges;
75147                 context.perform(function actionConnectCrossingWays(graph) {
75148                   // create the new node for the points
75149                   var node = osmNode({
75150                     loc: loc,
75151                     tags: connectionTags
75152                   });
75153                   graph = graph.replace(node);
75154                   var nodesToMerge = [node.id];
75155                   var mergeThresholdInMeters = 0.75;
75156                   edges.forEach(function (edge) {
75157                     var edgeNodes = [graph.entity(edge[0]), graph.entity(edge[1])];
75158                     var nearby = geoSphericalClosestNode(edgeNodes, loc); // if there is already a suitable node nearby, use that
75159                     // use the node if node has no interesting tags or if it is a crossing node #8326
75160
75161                     if ((!nearby.node.hasInterestingTags() || nearby.node.isCrossing()) && nearby.distance < mergeThresholdInMeters) {
75162                       nodesToMerge.push(nearby.node.id); // else add the new node to the way
75163                     } else {
75164                       graph = actionAddMidpoint({
75165                         loc: loc,
75166                         edge: edge
75167                       }, node)(graph);
75168                     }
75169                   });
75170
75171                   if (nodesToMerge.length > 1) {
75172                     // if we're using nearby nodes, merge them with the new node
75173                     graph = actionMergeNodes(nodesToMerge, loc)(graph);
75174                   }
75175
75176                   return graph;
75177                 }, _t('issues.fix.connect_crossing_features.annotation'));
75178               }
75179             });
75180           }
75181
75182           function makeChangeLayerFix(higherOrLower) {
75183             return new validationIssueFix({
75184               icon: 'iD-icon-' + (higherOrLower === 'higher' ? 'up' : 'down'),
75185               title: _t.html('issues.fix.tag_this_as_' + higherOrLower + '.title'),
75186               onClick: function onClick(context) {
75187                 var mode = context.mode();
75188                 if (!mode || mode.id !== 'select') return;
75189                 var selectedIDs = mode.selectedIDs();
75190                 if (selectedIDs.length !== 1) return;
75191                 var selectedID = selectedIDs[0];
75192                 if (!this.issue.entityIds.some(function (entityId) {
75193                   return entityId === selectedID;
75194                 })) return;
75195                 var entity = context.hasEntity(selectedID);
75196                 if (!entity) return;
75197                 var tags = Object.assign({}, entity.tags); // shallow copy
75198
75199                 var layer = tags.layer && Number(tags.layer);
75200
75201                 if (layer && !isNaN(layer)) {
75202                   if (higherOrLower === 'higher') {
75203                     layer += 1;
75204                   } else {
75205                     layer -= 1;
75206                   }
75207                 } else {
75208                   if (higherOrLower === 'higher') {
75209                     layer = 1;
75210                   } else {
75211                     layer = -1;
75212                   }
75213                 }
75214
75215                 tags.layer = layer.toString();
75216                 context.perform(actionChangeTags(entity.id, tags), _t('operations.change_tags.annotation'));
75217               }
75218             });
75219           }
75220
75221           validation.type = type;
75222           return validation;
75223         }
75224
75225         function behaviorDrawWay(context, wayID, mode, startGraph) {
75226           var keybinding = utilKeybinding('drawWay');
75227           var dispatch = dispatch$8('rejectedSelfIntersection');
75228           var behavior = behaviorDraw(context); // Must be set by `drawWay.nodeIndex` before each install of this behavior.
75229
75230           var _nodeIndex;
75231
75232           var _origWay;
75233
75234           var _wayGeometry;
75235
75236           var _headNodeID;
75237
75238           var _annotation;
75239
75240           var _pointerHasMoved = false; // The osmNode to be placed.
75241           // This is temporary and just follows the mouse cursor until an "add" event occurs.
75242
75243           var _drawNode;
75244
75245           var _didResolveTempEdit = false;
75246
75247           function createDrawNode(loc) {
75248             // don't make the draw node until we actually need it
75249             _drawNode = osmNode({
75250               loc: loc
75251             });
75252             context.pauseChangeDispatch();
75253             context.replace(function actionAddDrawNode(graph) {
75254               // add the draw node to the graph and insert it into the way
75255               var way = graph.entity(wayID);
75256               return graph.replace(_drawNode).replace(way.addNode(_drawNode.id, _nodeIndex));
75257             }, _annotation);
75258             context.resumeChangeDispatch();
75259             setActiveElements();
75260           }
75261
75262           function removeDrawNode() {
75263             context.pauseChangeDispatch();
75264             context.replace(function actionDeleteDrawNode(graph) {
75265               var way = graph.entity(wayID);
75266               return graph.replace(way.removeNode(_drawNode.id)).remove(_drawNode);
75267             }, _annotation);
75268             _drawNode = undefined;
75269             context.resumeChangeDispatch();
75270           }
75271
75272           function keydown(d3_event) {
75273             if (d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
75274               if (context.surface().classed('nope')) {
75275                 context.surface().classed('nope-suppressed', true);
75276               }
75277
75278               context.surface().classed('nope', false).classed('nope-disabled', true);
75279             }
75280           }
75281
75282           function keyup(d3_event) {
75283             if (d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
75284               if (context.surface().classed('nope-suppressed')) {
75285                 context.surface().classed('nope', true);
75286               }
75287
75288               context.surface().classed('nope-suppressed', false).classed('nope-disabled', false);
75289             }
75290           }
75291
75292           function allowsVertex(d) {
75293             return d.geometry(context.graph()) === 'vertex' || _mainPresetIndex.allowsVertex(d, context.graph());
75294           } // related code
75295           // - `mode/drag_node.js`     `doMove()`
75296           // - `behavior/draw.js`      `click()`
75297           // - `behavior/draw_way.js`  `move()`
75298
75299
75300           function move(d3_event, datum) {
75301             var loc = context.map().mouseCoordinates();
75302             if (!_drawNode) createDrawNode(loc);
75303             context.surface().classed('nope-disabled', d3_event.altKey);
75304             var targetLoc = datum && datum.properties && datum.properties.entity && allowsVertex(datum.properties.entity) && datum.properties.entity.loc;
75305             var targetNodes = datum && datum.properties && datum.properties.nodes;
75306
75307             if (targetLoc) {
75308               // snap to node/vertex - a point target with `.loc`
75309               loc = targetLoc;
75310             } else if (targetNodes) {
75311               // snap to way - a line target with `.nodes`
75312               var choice = geoChooseEdge(targetNodes, context.map().mouse(), context.projection, _drawNode.id);
75313
75314               if (choice) {
75315                 loc = choice.loc;
75316               }
75317             }
75318
75319             context.replace(actionMoveNode(_drawNode.id, loc), _annotation);
75320             _drawNode = context.entity(_drawNode.id);
75321             checkGeometry(true
75322             /* includeDrawNode */
75323             );
75324           } // Check whether this edit causes the geometry to break.
75325           // If so, class the surface with a nope cursor.
75326           // `includeDrawNode` - Only check the relevant line segments if finishing drawing
75327
75328
75329           function checkGeometry(includeDrawNode) {
75330             var nopeDisabled = context.surface().classed('nope-disabled');
75331             var isInvalid = isInvalidGeometry(includeDrawNode);
75332
75333             if (nopeDisabled) {
75334               context.surface().classed('nope', false).classed('nope-suppressed', isInvalid);
75335             } else {
75336               context.surface().classed('nope', isInvalid).classed('nope-suppressed', false);
75337             }
75338           }
75339
75340           function isInvalidGeometry(includeDrawNode) {
75341             var testNode = _drawNode; // we only need to test the single way we're drawing
75342
75343             var parentWay = context.graph().entity(wayID);
75344             var nodes = context.graph().childNodes(parentWay).slice(); // shallow copy
75345
75346             if (includeDrawNode) {
75347               if (parentWay.isClosed()) {
75348                 // don't test the last segment for closed ways - #4655
75349                 // (still test the first segment)
75350                 nodes.pop();
75351               }
75352             } else {
75353               // discount the draw node
75354               if (parentWay.isClosed()) {
75355                 if (nodes.length < 3) return false;
75356                 if (_drawNode) nodes.splice(-2, 1);
75357                 testNode = nodes[nodes.length - 2];
75358               } else {
75359                 // there's nothing we need to test if we ignore the draw node on open ways
75360                 return false;
75361               }
75362             }
75363
75364             return testNode && geoHasSelfIntersections(nodes, testNode.id);
75365           }
75366
75367           function undone() {
75368             // undoing removed the temp edit
75369             _didResolveTempEdit = true;
75370             context.pauseChangeDispatch();
75371             var nextMode;
75372
75373             if (context.graph() === startGraph) {
75374               // We've undone back to the initial state before we started drawing.
75375               // Just exit the draw mode without undoing whatever we did before
75376               // we entered the draw mode.
75377               nextMode = modeSelect(context, [wayID]);
75378             } else {
75379               // The `undo` only removed the temporary edit, so here we have to
75380               // manually undo to actually remove the last node we added. We can't
75381               // use the `undo` function since the initial "add" graph doesn't have
75382               // an annotation and so cannot be undone to.
75383               context.pop(1); // continue drawing
75384
75385               nextMode = mode;
75386             } // clear the redo stack by adding and removing a blank edit
75387
75388
75389             context.perform(actionNoop());
75390             context.pop(1);
75391             context.resumeChangeDispatch();
75392             context.enter(nextMode);
75393           }
75394
75395           function setActiveElements() {
75396             if (!_drawNode) return;
75397             context.surface().selectAll('.' + _drawNode.id).classed('active', true);
75398           }
75399
75400           function resetToStartGraph() {
75401             while (context.graph() !== startGraph) {
75402               context.pop();
75403             }
75404           }
75405
75406           var drawWay = function drawWay(surface) {
75407             _drawNode = undefined;
75408             _didResolveTempEdit = false;
75409             _origWay = context.entity(wayID);
75410
75411             if (typeof _nodeIndex === 'number') {
75412               _headNodeID = _origWay.nodes[_nodeIndex];
75413             } else if (_origWay.isClosed()) {
75414               _headNodeID = _origWay.nodes[_origWay.nodes.length - 2];
75415             } else {
75416               _headNodeID = _origWay.nodes[_origWay.nodes.length - 1];
75417             }
75418
75419             _wayGeometry = _origWay.geometry(context.graph());
75420             _annotation = _t((_origWay.nodes.length === (_origWay.isClosed() ? 2 : 1) ? 'operations.start.annotation.' : 'operations.continue.annotation.') + _wayGeometry);
75421             _pointerHasMoved = false; // Push an annotated state for undo to return back to.
75422             // We must make sure to replace or remove it later.
75423
75424             context.pauseChangeDispatch();
75425             context.perform(actionNoop(), _annotation);
75426             context.resumeChangeDispatch();
75427             behavior.hover().initialNodeID(_headNodeID);
75428             behavior.on('move', function () {
75429               _pointerHasMoved = true;
75430               move.apply(this, arguments);
75431             }).on('down', function () {
75432               move.apply(this, arguments);
75433             }).on('downcancel', function () {
75434               if (_drawNode) removeDrawNode();
75435             }).on('click', drawWay.add).on('clickWay', drawWay.addWay).on('clickNode', drawWay.addNode).on('undo', context.undo).on('cancel', drawWay.cancel).on('finish', drawWay.finish);
75436             select(window).on('keydown.drawWay', keydown).on('keyup.drawWay', keyup);
75437             context.map().dblclickZoomEnable(false).on('drawn.draw', setActiveElements);
75438             setActiveElements();
75439             surface.call(behavior);
75440             context.history().on('undone.draw', undone);
75441           };
75442
75443           drawWay.off = function (surface) {
75444             if (!_didResolveTempEdit) {
75445               // Drawing was interrupted unexpectedly.
75446               // This can happen if the user changes modes,
75447               // clicks geolocate button, a hashchange event occurs, etc.
75448               context.pauseChangeDispatch();
75449               resetToStartGraph();
75450               context.resumeChangeDispatch();
75451             }
75452
75453             _drawNode = undefined;
75454             _nodeIndex = undefined;
75455             context.map().on('drawn.draw', null);
75456             surface.call(behavior.off).selectAll('.active').classed('active', false);
75457             surface.classed('nope', false).classed('nope-suppressed', false).classed('nope-disabled', false);
75458             select(window).on('keydown.drawWay', null).on('keyup.drawWay', null);
75459             context.history().on('undone.draw', null);
75460           };
75461
75462           function attemptAdd(d, loc, doAdd) {
75463             if (_drawNode) {
75464               // move the node to the final loc in case move wasn't called
75465               // consistently (e.g. on touch devices)
75466               context.replace(actionMoveNode(_drawNode.id, loc), _annotation);
75467               _drawNode = context.entity(_drawNode.id);
75468             } else {
75469               createDrawNode(loc);
75470             }
75471
75472             checkGeometry(true
75473             /* includeDrawNode */
75474             );
75475
75476             if (d && d.properties && d.properties.nope || context.surface().classed('nope')) {
75477               if (!_pointerHasMoved) {
75478                 // prevent the temporary draw node from appearing on touch devices
75479                 removeDrawNode();
75480               }
75481
75482               dispatch.call('rejectedSelfIntersection', this);
75483               return; // can't click here
75484             }
75485
75486             context.pauseChangeDispatch();
75487             doAdd(); // we just replaced the temporary edit with the real one
75488
75489             _didResolveTempEdit = true;
75490             context.resumeChangeDispatch();
75491             context.enter(mode);
75492           } // Accept the current position of the drawing node
75493
75494
75495           drawWay.add = function (loc, d) {
75496             attemptAdd(d, loc, function () {// don't need to do anything extra
75497             });
75498           }; // Connect the way to an existing way
75499
75500
75501           drawWay.addWay = function (loc, edge, d) {
75502             attemptAdd(d, loc, function () {
75503               context.replace(actionAddMidpoint({
75504                 loc: loc,
75505                 edge: edge
75506               }, _drawNode), _annotation);
75507             });
75508           }; // Connect the way to an existing node
75509
75510
75511           drawWay.addNode = function (node, d) {
75512             // finish drawing if the mapper targets the prior node
75513             if (node.id === _headNodeID || // or the first node when drawing an area
75514             _origWay.isClosed() && node.id === _origWay.first()) {
75515               drawWay.finish();
75516               return;
75517             }
75518
75519             attemptAdd(d, node.loc, function () {
75520               context.replace(function actionReplaceDrawNode(graph) {
75521                 // remove the temporary draw node and insert the existing node
75522                 // at the same index
75523                 graph = graph.replace(graph.entity(wayID).removeNode(_drawNode.id)).remove(_drawNode);
75524                 return graph.replace(graph.entity(wayID).addNode(node.id, _nodeIndex));
75525               }, _annotation);
75526             });
75527           };
75528           /**
75529            * @param {(typeof osmWay)[]} ways
75530            * @returns {"line" | "area" | "generic"}
75531            */
75532
75533
75534           function getFeatureType(ways) {
75535             if (ways.every(function (way) {
75536               return way.isClosed();
75537             })) return 'area';
75538             if (ways.every(function (way) {
75539               return !way.isClosed();
75540             })) return 'line';
75541             return 'generic';
75542           }
75543           /** see PR #8671 */
75544
75545
75546           function followMode() {
75547             if (_didResolveTempEdit) return;
75548
75549             try {
75550               // get the last 2 added nodes.
75551               // check if they are both part of only oneway (the same one)
75552               // check if the ways that they're part of are the same way
75553               // find index of the last two nodes, to determine the direction to travel around the existing way
75554               // add the next node to the way we are drawing
75555               // if we're drawing an area, the first node = last node.
75556               var isDrawingArea = _origWay.nodes[0] === _origWay.nodes.slice(-1)[0];
75557
75558               var _origWay$nodes$slice = _origWay.nodes.slice(isDrawingArea ? -3 : -2),
75559                   _origWay$nodes$slice2 = _slicedToArray(_origWay$nodes$slice, 2),
75560                   secondLastNodeId = _origWay$nodes$slice2[0],
75561                   lastNodeId = _origWay$nodes$slice2[1]; // Unlike startGraph, the full history graph may contain unsaved vertices to follow.
75562               // https://github.com/openstreetmap/iD/issues/8749
75563
75564
75565               var historyGraph = context.history().graph();
75566
75567               if (!lastNodeId || !secondLastNodeId || !historyGraph.hasEntity(lastNodeId) || !historyGraph.hasEntity(secondLastNodeId)) {
75568                 context.ui().flash.duration(4000).iconName('#iD-icon-no').label(_t.html('operations.follow.error.needs_more_initial_nodes'))();
75569                 return;
75570               } // If the way has looped over itself, follow some other way.
75571
75572
75573               var lastNodesParents = historyGraph.parentWays(historyGraph.entity(lastNodeId)).filter(function (w) {
75574                 return w.id !== wayID;
75575               });
75576               var secondLastNodesParents = historyGraph.parentWays(historyGraph.entity(secondLastNodeId)).filter(function (w) {
75577                 return w.id !== wayID;
75578               });
75579               var featureType = getFeatureType(lastNodesParents);
75580
75581               if (lastNodesParents.length !== 1 || secondLastNodesParents.length === 0) {
75582                 context.ui().flash.duration(4000).iconName('#iD-icon-no').label(_t.html("operations.follow.error.intersection_of_multiple_ways.".concat(featureType)))();
75583                 return;
75584               } // Check if the last node's parent is also the parent of the second last node.
75585               // The last node must only have one parent, but the second last node can have
75586               // multiple parents.
75587
75588
75589               if (!secondLastNodesParents.some(function (n) {
75590                 return n.id === lastNodesParents[0].id;
75591               })) {
75592                 context.ui().flash.duration(4000).iconName('#iD-icon-no').label(_t.html("operations.follow.error.intersection_of_different_ways.".concat(featureType)))();
75593                 return;
75594               }
75595
75596               var way = lastNodesParents[0];
75597               var indexOfLast = way.nodes.indexOf(lastNodeId);
75598               var indexOfSecondLast = way.nodes.indexOf(secondLastNodeId); // for a closed way, the first/last node is the same so it appears twice in the array,
75599               // but indexOf always finds the first occurrence. This is only an issue when following a way
75600               // in descending order
75601
75602               var isDescendingPastZero = indexOfLast === way.nodes.length - 2 && indexOfSecondLast === 0;
75603               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
75604
75605               if (nextNodeIndex === -1) nextNodeIndex = indexOfSecondLast === 1 ? way.nodes.length - 2 : 1;
75606               var nextNode = historyGraph.entity(way.nodes[nextNodeIndex]);
75607               drawWay.addNode(nextNode, {
75608                 geometry: {
75609                   type: 'Point',
75610                   coordinates: nextNode.loc
75611                 },
75612                 id: nextNode.id,
75613                 properties: {
75614                   target: true,
75615                   entity: nextNode
75616                 }
75617               });
75618             } catch (ex) {
75619               context.ui().flash.duration(4000).iconName('#iD-icon-no').label(_t.html('operations.follow.error.unknown'))();
75620             }
75621           }
75622
75623           keybinding.on(_t('operations.follow.key'), followMode);
75624           select(document).call(keybinding); // Finish the draw operation, removing the temporary edit.
75625           // If the way has enough nodes to be valid, it's selected.
75626           // Otherwise, delete everything and return to browse mode.
75627
75628           drawWay.finish = function () {
75629             checkGeometry(false
75630             /* includeDrawNode */
75631             );
75632
75633             if (context.surface().classed('nope')) {
75634               dispatch.call('rejectedSelfIntersection', this);
75635               return; // can't click here
75636             }
75637
75638             context.pauseChangeDispatch(); // remove the temporary edit
75639
75640             context.pop(1);
75641             _didResolveTempEdit = true;
75642             context.resumeChangeDispatch();
75643             var way = context.hasEntity(wayID);
75644
75645             if (!way || way.isDegenerate()) {
75646               drawWay.cancel();
75647               return;
75648             }
75649
75650             window.setTimeout(function () {
75651               context.map().dblclickZoomEnable(true);
75652             }, 1000);
75653             var isNewFeature = !mode.isContinuing;
75654             context.enter(modeSelect(context, [wayID]).newFeature(isNewFeature));
75655           }; // Cancel the draw operation, delete everything, and return to browse mode.
75656
75657
75658           drawWay.cancel = function () {
75659             context.pauseChangeDispatch();
75660             resetToStartGraph();
75661             context.resumeChangeDispatch();
75662             window.setTimeout(function () {
75663               context.map().dblclickZoomEnable(true);
75664             }, 1000);
75665             context.surface().classed('nope', false).classed('nope-disabled', false).classed('nope-suppressed', false);
75666             context.enter(modeBrowse(context));
75667           };
75668
75669           drawWay.nodeIndex = function (val) {
75670             if (!arguments.length) return _nodeIndex;
75671             _nodeIndex = val;
75672             return drawWay;
75673           };
75674
75675           drawWay.activeID = function () {
75676             if (!arguments.length) return _drawNode && _drawNode.id; // no assign
75677
75678             return drawWay;
75679           };
75680
75681           return utilRebind(drawWay, dispatch, 'on');
75682         }
75683
75684         function modeDrawLine(context, wayID, startGraph, button, affix, continuing) {
75685           var mode = {
75686             button: button,
75687             id: 'draw-line'
75688           };
75689           var behavior = behaviorDrawWay(context, wayID, mode, startGraph).on('rejectedSelfIntersection.modeDrawLine', function () {
75690             context.ui().flash.iconName('#iD-icon-no').label(_t.html('self_intersection.error.lines'))();
75691           });
75692           mode.wayID = wayID;
75693           mode.isContinuing = continuing;
75694
75695           mode.enter = function () {
75696             behavior.nodeIndex(affix === 'prefix' ? 0 : undefined);
75697             context.install(behavior);
75698           };
75699
75700           mode.exit = function () {
75701             context.uninstall(behavior);
75702           };
75703
75704           mode.selectedIDs = function () {
75705             return [wayID];
75706           };
75707
75708           mode.activeID = function () {
75709             return behavior && behavior.activeID() || [];
75710           };
75711
75712           return mode;
75713         }
75714
75715         function validationDisconnectedWay() {
75716           var type = 'disconnected_way';
75717
75718           function isTaggedAsHighway(entity) {
75719             return osmRoutableHighwayTagValues[entity.tags.highway];
75720           }
75721
75722           var validation = function checkDisconnectedWay(entity, graph) {
75723             var routingIslandWays = routingIslandForEntity(entity);
75724             if (!routingIslandWays) return [];
75725             return [new validationIssue({
75726               type: type,
75727               subtype: 'highway',
75728               severity: 'warning',
75729               message: function message(context) {
75730                 var entity = this.entityIds.length && context.hasEntity(this.entityIds[0]);
75731                 var label = entity && utilDisplayLabel(entity, context.graph());
75732                 return _t.html('issues.disconnected_way.routable.message', {
75733                   count: this.entityIds.length,
75734                   highway: label
75735                 });
75736               },
75737               reference: showReference,
75738               entityIds: Array.from(routingIslandWays).map(function (way) {
75739                 return way.id;
75740               }),
75741               dynamicFixes: makeFixes
75742             })];
75743
75744             function makeFixes(context) {
75745               var fixes = [];
75746               var singleEntity = this.entityIds.length === 1 && context.hasEntity(this.entityIds[0]);
75747
75748               if (singleEntity) {
75749                 if (singleEntity.type === 'way' && !singleEntity.isClosed()) {
75750                   var textDirection = _mainLocalizer.textDirection();
75751                   var startFix = makeContinueDrawingFixIfAllowed(textDirection, singleEntity.first(), 'start');
75752                   if (startFix) fixes.push(startFix);
75753                   var endFix = makeContinueDrawingFixIfAllowed(textDirection, singleEntity.last(), 'end');
75754                   if (endFix) fixes.push(endFix);
75755                 }
75756
75757                 if (!fixes.length) {
75758                   fixes.push(new validationIssueFix({
75759                     title: _t.html('issues.fix.connect_feature.title')
75760                   }));
75761                 }
75762
75763                 fixes.push(new validationIssueFix({
75764                   icon: 'iD-operation-delete',
75765                   title: _t.html('issues.fix.delete_feature.title'),
75766                   entityIds: [singleEntity.id],
75767                   onClick: function onClick(context) {
75768                     var id = this.issue.entityIds[0];
75769                     var operation = operationDelete(context, [id]);
75770
75771                     if (!operation.disabled()) {
75772                       operation();
75773                     }
75774                   }
75775                 }));
75776               } else {
75777                 fixes.push(new validationIssueFix({
75778                   title: _t.html('issues.fix.connect_features.title')
75779                 }));
75780               }
75781
75782               return fixes;
75783             }
75784
75785             function showReference(selection) {
75786               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.disconnected_way.routable.reference'));
75787             }
75788
75789             function routingIslandForEntity(entity) {
75790               var routingIsland = new Set(); // the interconnected routable features
75791
75792               var waysToCheck = []; // the queue of remaining routable ways to traverse
75793
75794               function queueParentWays(node) {
75795                 graph.parentWays(node).forEach(function (parentWay) {
75796                   if (!routingIsland.has(parentWay) && // only check each feature once
75797                   isRoutableWay(parentWay, false)) {
75798                     // only check routable features
75799                     routingIsland.add(parentWay);
75800                     waysToCheck.push(parentWay);
75801                   }
75802                 });
75803               }
75804
75805               if (entity.type === 'way' && isRoutableWay(entity, true)) {
75806                 routingIsland.add(entity);
75807                 waysToCheck.push(entity);
75808               } else if (entity.type === 'node' && isRoutableNode(entity)) {
75809                 routingIsland.add(entity);
75810                 queueParentWays(entity);
75811               } else {
75812                 // this feature isn't routable, cannot be a routing island
75813                 return null;
75814               }
75815
75816               while (waysToCheck.length) {
75817                 var wayToCheck = waysToCheck.pop();
75818                 var childNodes = graph.childNodes(wayToCheck);
75819
75820                 for (var i in childNodes) {
75821                   var vertex = childNodes[i];
75822
75823                   if (isConnectedVertex(vertex)) {
75824                     // found a link to the wider network, not a routing island
75825                     return null;
75826                   }
75827
75828                   if (isRoutableNode(vertex)) {
75829                     routingIsland.add(vertex);
75830                   }
75831
75832                   queueParentWays(vertex);
75833                 }
75834               } // no network link found, this is a routing island, return its members
75835
75836
75837               return routingIsland;
75838             }
75839
75840             function isConnectedVertex(vertex) {
75841               // assume ways overlapping unloaded tiles are connected to the wider road network  - #5938
75842               var osm = services.osm;
75843               if (osm && !osm.isDataLoaded(vertex.loc)) return true; // entrances are considered connected
75844
75845               if (vertex.tags.entrance && vertex.tags.entrance !== 'no') return true;
75846               if (vertex.tags.amenity === 'parking_entrance') return true;
75847               return false;
75848             }
75849
75850             function isRoutableNode(node) {
75851               // treat elevators as distinct features in the highway network
75852               if (node.tags.highway === 'elevator') return true;
75853               return false;
75854             }
75855
75856             function isRoutableWay(way, ignoreInnerWays) {
75857               if (isTaggedAsHighway(way) || way.tags.route === 'ferry') return true;
75858               return graph.parentRelations(way).some(function (parentRelation) {
75859                 if (parentRelation.tags.type === 'route' && parentRelation.tags.route === 'ferry') return true;
75860                 if (parentRelation.isMultipolygon() && isTaggedAsHighway(parentRelation) && (!ignoreInnerWays || parentRelation.memberById(way.id).role !== 'inner')) return true;
75861                 return false;
75862               });
75863             }
75864
75865             function makeContinueDrawingFixIfAllowed(textDirection, vertexID, whichEnd) {
75866               var vertex = graph.hasEntity(vertexID);
75867               if (!vertex || vertex.tags.noexit === 'yes') return null;
75868               var useLeftContinue = whichEnd === 'start' && textDirection === 'ltr' || whichEnd === 'end' && textDirection === 'rtl';
75869               return new validationIssueFix({
75870                 icon: 'iD-operation-continue' + (useLeftContinue ? '-left' : ''),
75871                 title: _t.html('issues.fix.continue_from_' + whichEnd + '.title'),
75872                 entityIds: [vertexID],
75873                 onClick: function onClick(context) {
75874                   var wayId = this.issue.entityIds[0];
75875                   var way = context.hasEntity(wayId);
75876                   var vertexId = this.entityIds[0];
75877                   var vertex = context.hasEntity(vertexId);
75878                   if (!way || !vertex) return; // make sure the vertex is actually visible and editable
75879
75880                   var map = context.map();
75881
75882                   if (!context.editable() || !map.trimmedExtent().contains(vertex.loc)) {
75883                     map.zoomToEase(vertex);
75884                   }
75885
75886                   context.enter(modeDrawLine(context, wayId, context.graph(), 'line', way.affix(vertexId), true));
75887                 }
75888               });
75889             }
75890           };
75891
75892           validation.type = type;
75893           return validation;
75894         }
75895
75896         function validationFormatting() {
75897           var type = 'invalid_format';
75898
75899           var validation = function validation(entity) {
75900             var issues = [];
75901
75902             function isValidEmail(email) {
75903               // Emails in OSM are going to be official so they should be pretty simple
75904               // Using negated lists to better support all possible unicode characters (#6494)
75905               var valid_email = /^[^\(\)\\,":;<>@\[\]]+@[^\(\)\\,":;<>@\[\]\.]+(?:\.[a-z0-9-]+)*$/i; // An empty value is also acceptable
75906
75907               return !email || valid_email.test(email);
75908             }
75909
75910             function showReferenceEmail(selection) {
75911               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.invalid_format.email.reference'));
75912             }
75913             /* see https://github.com/openstreetmap/iD/issues/6831#issuecomment-537121379
75914             function isSchemePresent(url) {
75915                 var valid_scheme = /^https?:\/\//i;
75916                 return (!url || valid_scheme.test(url));
75917             }
75918             function showReferenceWebsite(selection) {
75919                 selection.selectAll('.issue-reference')
75920                     .data([0])
75921                     .enter()
75922                     .append('div')
75923                     .attr('class', 'issue-reference')
75924                     .call(t.append('issues.invalid_format.website.reference'));
75925             }
75926              if (entity.tags.website) {
75927                 // Multiple websites are possible
75928                 // If ever we support ES6, arrow functions make this nicer
75929                 var websites = entity.tags.website
75930                     .split(';')
75931                     .map(function(s) { return s.trim(); })
75932                     .filter(function(x) { return !isSchemePresent(x); });
75933                  if (websites.length) {
75934                     issues.push(new validationIssue({
75935                         type: type,
75936                         subtype: 'website',
75937                         severity: 'warning',
75938                         message: function(context) {
75939                             var entity = context.hasEntity(this.entityIds[0]);
75940                             return entity ? t.html('issues.invalid_format.website.message' + this.data,
75941                                 { feature: utilDisplayLabel(entity, context.graph()), site: websites.join(', ') }) : '';
75942                         },
75943                         reference: showReferenceWebsite,
75944                         entityIds: [entity.id],
75945                         hash: websites.join(),
75946                         data: (websites.length > 1) ? '_multi' : ''
75947                     }));
75948                 }
75949             }*/
75950
75951
75952             if (entity.tags.email) {
75953               // Multiple emails are possible
75954               var emails = entity.tags.email.split(';').map(function (s) {
75955                 return s.trim();
75956               }).filter(function (x) {
75957                 return !isValidEmail(x);
75958               });
75959
75960               if (emails.length) {
75961                 issues.push(new validationIssue({
75962                   type: type,
75963                   subtype: 'email',
75964                   severity: 'warning',
75965                   message: function message(context) {
75966                     var entity = context.hasEntity(this.entityIds[0]);
75967                     return entity ? _t.html('issues.invalid_format.email.message' + this.data, {
75968                       feature: utilDisplayLabel(entity, context.graph()),
75969                       email: emails.join(', ')
75970                     }) : '';
75971                   },
75972                   reference: showReferenceEmail,
75973                   entityIds: [entity.id],
75974                   hash: emails.join(),
75975                   data: emails.length > 1 ? '_multi' : ''
75976                 }));
75977               }
75978             }
75979
75980             return issues;
75981           };
75982
75983           validation.type = type;
75984           return validation;
75985         }
75986
75987         function validationHelpRequest(context) {
75988           var type = 'help_request';
75989
75990           var validation = function checkFixmeTag(entity) {
75991             if (!entity.tags.fixme) return []; // don't flag fixmes on features added by the user
75992
75993             if (entity.version === undefined) return [];
75994
75995             if (entity.v !== undefined) {
75996               var baseEntity = context.history().base().hasEntity(entity.id); // don't flag fixmes added by the user on existing features
75997
75998               if (!baseEntity || !baseEntity.tags.fixme) return [];
75999             }
76000
76001             return [new validationIssue({
76002               type: type,
76003               subtype: 'fixme_tag',
76004               severity: 'warning',
76005               message: function message(context) {
76006                 var entity = context.hasEntity(this.entityIds[0]);
76007                 return entity ? _t.html('issues.fixme_tag.message', {
76008                   feature: utilDisplayLabel(entity, context.graph(), true
76009                   /* verbose */
76010                   )
76011                 }) : '';
76012               },
76013               dynamicFixes: function dynamicFixes() {
76014                 return [new validationIssueFix({
76015                   title: _t.html('issues.fix.address_the_concern.title')
76016                 })];
76017               },
76018               reference: showReference,
76019               entityIds: [entity.id]
76020             })];
76021
76022             function showReference(selection) {
76023               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.fixme_tag.reference'));
76024             }
76025           };
76026
76027           validation.type = type;
76028           return validation;
76029         }
76030
76031         function validationImpossibleOneway() {
76032           var type = 'impossible_oneway';
76033
76034           var validation = function checkImpossibleOneway(entity, graph) {
76035             if (entity.type !== 'way' || entity.geometry(graph) !== 'line') return [];
76036             if (entity.isClosed()) return [];
76037             if (!typeForWay(entity)) return [];
76038             if (!isOneway(entity)) return [];
76039             var firstIssues = issuesForNode(entity, entity.first());
76040             var lastIssues = issuesForNode(entity, entity.last());
76041             return firstIssues.concat(lastIssues);
76042
76043             function typeForWay(way) {
76044               if (way.geometry(graph) !== 'line') return null;
76045               if (osmRoutableHighwayTagValues[way.tags.highway]) return 'highway';
76046               if (osmFlowingWaterwayTagValues[way.tags.waterway]) return 'waterway';
76047               return null;
76048             }
76049
76050             function isOneway(way) {
76051               if (way.tags.oneway === 'yes') return true;
76052               if (way.tags.oneway) return false;
76053
76054               for (var key in way.tags) {
76055                 if (osmOneWayTags[key] && osmOneWayTags[key][way.tags[key]]) {
76056                   return true;
76057                 }
76058               }
76059
76060               return false;
76061             }
76062
76063             function nodeOccursMoreThanOnce(way, nodeID) {
76064               var occurrences = 0;
76065
76066               for (var index in way.nodes) {
76067                 if (way.nodes[index] === nodeID) {
76068                   occurrences += 1;
76069                   if (occurrences > 1) return true;
76070                 }
76071               }
76072
76073               return false;
76074             }
76075
76076             function isConnectedViaOtherTypes(way, node) {
76077               var wayType = typeForWay(way);
76078
76079               if (wayType === 'highway') {
76080                 // entrances are considered connected
76081                 if (node.tags.entrance && node.tags.entrance !== 'no') return true;
76082                 if (node.tags.amenity === 'parking_entrance') return true;
76083               } else if (wayType === 'waterway') {
76084                 if (node.id === way.first()) {
76085                   // multiple waterways may start at the same spring
76086                   if (node.tags.natural === 'spring') return true;
76087                 } else {
76088                   // multiple waterways may end at the same drain
76089                   if (node.tags.manhole === 'drain') return true;
76090                 }
76091               }
76092
76093               return graph.parentWays(node).some(function (parentWay) {
76094                 if (parentWay.id === way.id) return false;
76095
76096                 if (wayType === 'highway') {
76097                   // allow connections to highway areas
76098                   if (parentWay.geometry(graph) === 'area' && osmRoutableHighwayTagValues[parentWay.tags.highway]) return true; // count connections to ferry routes as connected
76099
76100                   if (parentWay.tags.route === 'ferry') return true;
76101                   return graph.parentRelations(parentWay).some(function (parentRelation) {
76102                     if (parentRelation.tags.type === 'route' && parentRelation.tags.route === 'ferry') return true; // allow connections to highway multipolygons
76103
76104                     return parentRelation.isMultipolygon() && osmRoutableHighwayTagValues[parentRelation.tags.highway];
76105                   });
76106                 } else if (wayType === 'waterway') {
76107                   // multiple waterways may start or end at a water body at the same node
76108                   if (parentWay.tags.natural === 'water' || parentWay.tags.natural === 'coastline') return true;
76109                 }
76110
76111                 return false;
76112               });
76113             }
76114
76115             function issuesForNode(way, nodeID) {
76116               var isFirst = nodeID === way.first();
76117               var wayType = typeForWay(way); // ignore if this way is self-connected at this node
76118
76119               if (nodeOccursMoreThanOnce(way, nodeID)) return [];
76120               var osm = services.osm;
76121               if (!osm) return [];
76122               var node = graph.hasEntity(nodeID); // ignore if this node or its tile are unloaded
76123
76124               if (!node || !osm.isDataLoaded(node.loc)) return [];
76125               if (isConnectedViaOtherTypes(way, node)) return [];
76126               var attachedWaysOfSameType = graph.parentWays(node).filter(function (parentWay) {
76127                 if (parentWay.id === way.id) return false;
76128                 return typeForWay(parentWay) === wayType;
76129               }); // assume it's okay for waterways to start or end disconnected for now
76130
76131               if (wayType === 'waterway' && attachedWaysOfSameType.length === 0) return [];
76132               var attachedOneways = attachedWaysOfSameType.filter(function (attachedWay) {
76133                 return isOneway(attachedWay);
76134               }); // ignore if the way is connected to some non-oneway features
76135
76136               if (attachedOneways.length < attachedWaysOfSameType.length) return [];
76137
76138               if (attachedOneways.length) {
76139                 var connectedEndpointsOkay = attachedOneways.some(function (attachedOneway) {
76140                   if ((isFirst ? attachedOneway.first() : attachedOneway.last()) !== nodeID) return true;
76141                   if (nodeOccursMoreThanOnce(attachedOneway, nodeID)) return true;
76142                   return false;
76143                 });
76144                 if (connectedEndpointsOkay) return [];
76145               }
76146
76147               var placement = isFirst ? 'start' : 'end',
76148                   messageID = wayType + '.',
76149                   referenceID = wayType + '.';
76150
76151               if (wayType === 'waterway') {
76152                 messageID += 'connected.' + placement;
76153                 referenceID += 'connected';
76154               } else {
76155                 messageID += placement;
76156                 referenceID += placement;
76157               }
76158
76159               return [new validationIssue({
76160                 type: type,
76161                 subtype: wayType,
76162                 severity: 'warning',
76163                 message: function message(context) {
76164                   var entity = context.hasEntity(this.entityIds[0]);
76165                   return entity ? _t.html('issues.impossible_oneway.' + messageID + '.message', {
76166                     feature: utilDisplayLabel(entity, context.graph())
76167                   }) : '';
76168                 },
76169                 reference: getReference(referenceID),
76170                 entityIds: [way.id, node.id],
76171                 dynamicFixes: function dynamicFixes() {
76172                   var fixes = [];
76173
76174                   if (attachedOneways.length) {
76175                     fixes.push(new validationIssueFix({
76176                       icon: 'iD-operation-reverse',
76177                       title: _t.html('issues.fix.reverse_feature.title'),
76178                       entityIds: [way.id],
76179                       onClick: function onClick(context) {
76180                         var id = this.issue.entityIds[0];
76181                         context.perform(actionReverse(id), _t('operations.reverse.annotation.line', {
76182                           n: 1
76183                         }));
76184                       }
76185                     }));
76186                   }
76187
76188                   if (node.tags.noexit !== 'yes') {
76189                     var textDirection = _mainLocalizer.textDirection();
76190                     var useLeftContinue = isFirst && textDirection === 'ltr' || !isFirst && textDirection === 'rtl';
76191                     fixes.push(new validationIssueFix({
76192                       icon: 'iD-operation-continue' + (useLeftContinue ? '-left' : ''),
76193                       title: _t.html('issues.fix.continue_from_' + (isFirst ? 'start' : 'end') + '.title'),
76194                       onClick: function onClick(context) {
76195                         var entityID = this.issue.entityIds[0];
76196                         var vertexID = this.issue.entityIds[1];
76197                         var way = context.entity(entityID);
76198                         var vertex = context.entity(vertexID);
76199                         continueDrawing(way, vertex, context);
76200                       }
76201                     }));
76202                   }
76203
76204                   return fixes;
76205                 },
76206                 loc: node.loc
76207               })];
76208
76209               function getReference(referenceID) {
76210                 return function showReference(selection) {
76211                   selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.impossible_oneway.' + referenceID + '.reference'));
76212                 };
76213               }
76214             }
76215           };
76216
76217           function continueDrawing(way, vertex, context) {
76218             // make sure the vertex is actually visible and editable
76219             var map = context.map();
76220
76221             if (!context.editable() || !map.trimmedExtent().contains(vertex.loc)) {
76222               map.zoomToEase(vertex);
76223             }
76224
76225             context.enter(modeDrawLine(context, way.id, context.graph(), 'line', way.affix(vertex.id), true));
76226           }
76227
76228           validation.type = type;
76229           return validation;
76230         }
76231
76232         function validationIncompatibleSource() {
76233           var type = 'incompatible_source';
76234           var incompatibleRules = [{
76235             id: 'amap',
76236             regex: /(^amap$|^amap\.com|autonavi|mapabc|高德)/i
76237           }, {
76238             id: 'baidu',
76239             regex: /(baidu|mapbar|百度)/i
76240           }, {
76241             id: 'google',
76242             regex: /google/i,
76243             exceptRegex: /((books|drive)\.google|google\s?(books|drive|plus))|(esri\/Google_Africa_Buildings)/i
76244           }];
76245
76246           var validation = function checkIncompatibleSource(entity) {
76247             var entitySources = entity.tags && entity.tags.source && entity.tags.source.split(';');
76248             if (!entitySources) return [];
76249             var entityID = entity.id;
76250             return entitySources.map(function (source) {
76251               var matchRule = incompatibleRules.find(function (rule) {
76252                 if (!rule.regex.test(source)) return false;
76253                 if (rule.exceptRegex && rule.exceptRegex.test(source)) return false;
76254                 return true;
76255               });
76256               if (!matchRule) return null;
76257               return new validationIssue({
76258                 type: type,
76259                 severity: 'warning',
76260                 message: function message(context) {
76261                   var entity = context.hasEntity(entityID);
76262                   return entity ? _t.html('issues.incompatible_source.feature.message', {
76263                     feature: utilDisplayLabel(entity, context.graph(), true
76264                     /* verbose */
76265                     ),
76266                     value: source
76267                   }) : '';
76268                 },
76269                 reference: getReference(matchRule.id),
76270                 entityIds: [entityID],
76271                 hash: source,
76272                 dynamicFixes: function dynamicFixes() {
76273                   return [new validationIssueFix({
76274                     title: _t.html('issues.fix.remove_proprietary_data.title')
76275                   })];
76276                 }
76277               });
76278             }).filter(Boolean);
76279
76280             function getReference(id) {
76281               return function showReference(selection) {
76282                 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append("issues.incompatible_source.reference.".concat(id)));
76283               };
76284             }
76285           };
76286
76287           validation.type = type;
76288           return validation;
76289         }
76290
76291         function validationMaprules() {
76292           var type = 'maprules';
76293
76294           var validation = function checkMaprules(entity, graph) {
76295             if (!services.maprules) return [];
76296             var rules = services.maprules.validationRules();
76297             var issues = [];
76298
76299             for (var i = 0; i < rules.length; i++) {
76300               var rule = rules[i];
76301               rule.findIssues(entity, graph, issues);
76302             }
76303
76304             return issues;
76305           };
76306
76307           validation.type = type;
76308           return validation;
76309         }
76310
76311         function validationMismatchedGeometry() {
76312           var type = 'mismatched_geometry';
76313
76314           function tagSuggestingLineIsArea(entity) {
76315             if (entity.type !== 'way' || entity.isClosed()) return null;
76316             var tagSuggestingArea = entity.tagSuggestingArea();
76317
76318             if (!tagSuggestingArea) {
76319               return null;
76320             }
76321
76322             var asLine = _mainPresetIndex.matchTags(tagSuggestingArea, 'line');
76323             var asArea = _mainPresetIndex.matchTags(tagSuggestingArea, 'area');
76324
76325             if (asLine && asArea && asLine === asArea) {
76326               // these tags also allow lines and making this an area wouldn't matter
76327               return null;
76328             }
76329
76330             return tagSuggestingArea;
76331           }
76332
76333           function makeConnectEndpointsFixOnClick(way, graph) {
76334             // must have at least three nodes to close this automatically
76335             if (way.nodes.length < 3) return null;
76336             var nodes = graph.childNodes(way),
76337                 testNodes;
76338             var firstToLastDistanceMeters = geoSphericalDistance(nodes[0].loc, nodes[nodes.length - 1].loc); // if the distance is very small, attempt to merge the endpoints
76339
76340             if (firstToLastDistanceMeters < 0.75) {
76341               testNodes = nodes.slice(); // shallow copy
76342
76343               testNodes.pop();
76344               testNodes.push(testNodes[0]); // make sure this will not create a self-intersection
76345
76346               if (!geoHasSelfIntersections(testNodes, testNodes[0].id)) {
76347                 return function (context) {
76348                   var way = context.entity(this.issue.entityIds[0]);
76349                   context.perform(actionMergeNodes([way.nodes[0], way.nodes[way.nodes.length - 1]], nodes[0].loc), _t('issues.fix.connect_endpoints.annotation'));
76350                 };
76351               }
76352             } // if the points were not merged, attempt to close the way
76353
76354
76355             testNodes = nodes.slice(); // shallow copy
76356
76357             testNodes.push(testNodes[0]); // make sure this will not create a self-intersection
76358
76359             if (!geoHasSelfIntersections(testNodes, testNodes[0].id)) {
76360               return function (context) {
76361                 var wayId = this.issue.entityIds[0];
76362                 var way = context.entity(wayId);
76363                 var nodeId = way.nodes[0];
76364                 var index = way.nodes.length;
76365                 context.perform(actionAddVertex(wayId, nodeId, index), _t('issues.fix.connect_endpoints.annotation'));
76366               };
76367             }
76368           }
76369
76370           function lineTaggedAsAreaIssue(entity) {
76371             var tagSuggestingArea = tagSuggestingLineIsArea(entity);
76372             if (!tagSuggestingArea) return null;
76373             return new validationIssue({
76374               type: type,
76375               subtype: 'area_as_line',
76376               severity: 'warning',
76377               message: function message(context) {
76378                 var entity = context.hasEntity(this.entityIds[0]);
76379                 return entity ? _t.html('issues.tag_suggests_area.message', {
76380                   feature: utilDisplayLabel(entity, 'area', true
76381                   /* verbose */
76382                   ),
76383                   tag: utilTagText({
76384                     tags: tagSuggestingArea
76385                   })
76386                 }) : '';
76387               },
76388               reference: showReference,
76389               entityIds: [entity.id],
76390               hash: JSON.stringify(tagSuggestingArea),
76391               dynamicFixes: function dynamicFixes(context) {
76392                 var fixes = [];
76393                 var entity = context.entity(this.entityIds[0]);
76394                 var connectEndsOnClick = makeConnectEndpointsFixOnClick(entity, context.graph());
76395                 fixes.push(new validationIssueFix({
76396                   title: _t.html('issues.fix.connect_endpoints.title'),
76397                   onClick: connectEndsOnClick
76398                 }));
76399                 fixes.push(new validationIssueFix({
76400                   icon: 'iD-operation-delete',
76401                   title: _t.html('issues.fix.remove_tag.title'),
76402                   onClick: function onClick(context) {
76403                     var entityId = this.issue.entityIds[0];
76404                     var entity = context.entity(entityId);
76405                     var tags = Object.assign({}, entity.tags); // shallow copy
76406
76407                     for (var key in tagSuggestingArea) {
76408                       delete tags[key];
76409                     }
76410
76411                     context.perform(actionChangeTags(entityId, tags), _t('issues.fix.remove_tag.annotation'));
76412                   }
76413                 }));
76414                 return fixes;
76415               }
76416             });
76417
76418             function showReference(selection) {
76419               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.tag_suggests_area.reference'));
76420             }
76421           }
76422
76423           function vertexPointIssue(entity, graph) {
76424             // we only care about nodes
76425             if (entity.type !== 'node') return null; // ignore tagless points
76426
76427             if (Object.keys(entity.tags).length === 0) return null; // address lines are special so just ignore them
76428
76429             if (entity.isOnAddressLine(graph)) return null;
76430             var geometry = entity.geometry(graph);
76431             var allowedGeometries = osmNodeGeometriesForTags(entity.tags);
76432
76433             if (geometry === 'point' && !allowedGeometries.point && allowedGeometries.vertex) {
76434               return new validationIssue({
76435                 type: type,
76436                 subtype: 'vertex_as_point',
76437                 severity: 'warning',
76438                 message: function message(context) {
76439                   var entity = context.hasEntity(this.entityIds[0]);
76440                   return entity ? _t.html('issues.vertex_as_point.message', {
76441                     feature: utilDisplayLabel(entity, 'vertex', true
76442                     /* verbose */
76443                     )
76444                   }) : '';
76445                 },
76446                 reference: function showReference(selection) {
76447                   selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.vertex_as_point.reference'));
76448                 },
76449                 entityIds: [entity.id]
76450               });
76451             } else if (geometry === 'vertex' && !allowedGeometries.vertex && allowedGeometries.point) {
76452               return new validationIssue({
76453                 type: type,
76454                 subtype: 'point_as_vertex',
76455                 severity: 'warning',
76456                 message: function message(context) {
76457                   var entity = context.hasEntity(this.entityIds[0]);
76458                   return entity ? _t.html('issues.point_as_vertex.message', {
76459                     feature: utilDisplayLabel(entity, 'point', true
76460                     /* verbose */
76461                     )
76462                   }) : '';
76463                 },
76464                 reference: function showReference(selection) {
76465                   selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.point_as_vertex.reference'));
76466                 },
76467                 entityIds: [entity.id],
76468                 dynamicFixes: extractPointDynamicFixes
76469               });
76470             }
76471
76472             return null;
76473           }
76474
76475           function otherMismatchIssue(entity, graph) {
76476             // ignore boring features
76477             if (!entity.hasInterestingTags()) return null;
76478             if (entity.type !== 'node' && entity.type !== 'way') return null; // address lines are special so just ignore them
76479
76480             if (entity.type === 'node' && entity.isOnAddressLine(graph)) return null;
76481             var sourceGeom = entity.geometry(graph);
76482             var targetGeoms = entity.type === 'way' ? ['point', 'vertex'] : ['line', 'area'];
76483             if (sourceGeom === 'area') targetGeoms.unshift('line');
76484             var asSource = _mainPresetIndex.match(entity, graph);
76485             var targetGeom = targetGeoms.find(function (nodeGeom) {
76486               var asTarget = _mainPresetIndex.matchTags(entity.tags, nodeGeom);
76487               if (!asSource || !asTarget || asSource === asTarget || // sometimes there are two presets with the same tags for different geometries
76488               fastDeepEqual(asSource.tags, asTarget.tags)) return false;
76489               if (asTarget.isFallback()) return false;
76490               var primaryKey = Object.keys(asTarget.tags)[0]; // special case: buildings-as-points are discouraged by iD, but common in OSM, so ignore them
76491
76492               if (primaryKey === 'building') return false;
76493               if (asTarget.tags[primaryKey] === '*') return false;
76494               return asSource.isFallback() || asSource.tags[primaryKey] === '*';
76495             });
76496             if (!targetGeom) return null;
76497             var subtype = targetGeom + '_as_' + sourceGeom;
76498             if (targetGeom === 'vertex') targetGeom = 'point';
76499             if (sourceGeom === 'vertex') sourceGeom = 'point';
76500             var referenceId = targetGeom + '_as_' + sourceGeom;
76501             var dynamicFixes;
76502
76503             if (targetGeom === 'point') {
76504               dynamicFixes = extractPointDynamicFixes;
76505             } else if (sourceGeom === 'area' && targetGeom === 'line') {
76506               dynamicFixes = lineToAreaDynamicFixes;
76507             }
76508
76509             return new validationIssue({
76510               type: type,
76511               subtype: subtype,
76512               severity: 'warning',
76513               message: function message(context) {
76514                 var entity = context.hasEntity(this.entityIds[0]);
76515                 return entity ? _t.html('issues.' + referenceId + '.message', {
76516                   feature: utilDisplayLabel(entity, targetGeom, true
76517                   /* verbose */
76518                   )
76519                 }) : '';
76520               },
76521               reference: function showReference(selection) {
76522                 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.mismatched_geometry.reference'));
76523               },
76524               entityIds: [entity.id],
76525               dynamicFixes: dynamicFixes
76526             });
76527           }
76528
76529           function lineToAreaDynamicFixes(context) {
76530             var convertOnClick;
76531             var entityId = this.entityIds[0];
76532             var entity = context.entity(entityId);
76533             var tags = Object.assign({}, entity.tags); // shallow copy
76534
76535             delete tags.area;
76536
76537             if (!osmTagSuggestingArea(tags)) {
76538               // if removing the area tag would make this a line, offer that as a quick fix
76539               convertOnClick = function convertOnClick(context) {
76540                 var entityId = this.issue.entityIds[0];
76541                 var entity = context.entity(entityId);
76542                 var tags = Object.assign({}, entity.tags); // shallow copy
76543
76544                 if (tags.area) {
76545                   delete tags.area;
76546                 }
76547
76548                 context.perform(actionChangeTags(entityId, tags), _t('issues.fix.convert_to_line.annotation'));
76549               };
76550             }
76551
76552             return [new validationIssueFix({
76553               icon: 'iD-icon-line',
76554               title: _t.html('issues.fix.convert_to_line.title'),
76555               onClick: convertOnClick
76556             })];
76557           }
76558
76559           function extractPointDynamicFixes(context) {
76560             var entityId = this.entityIds[0];
76561             var extractOnClick = null;
76562
76563             if (!context.hasHiddenConnections(entityId)) {
76564               extractOnClick = function extractOnClick(context) {
76565                 var entityId = this.issue.entityIds[0];
76566                 var action = actionExtract(entityId, context.projection);
76567                 context.perform(action, _t('operations.extract.annotation', {
76568                   n: 1
76569                 })); // re-enter mode to trigger updates
76570
76571                 context.enter(modeSelect(context, [action.getExtractedNodeID()]));
76572               };
76573             }
76574
76575             return [new validationIssueFix({
76576               icon: 'iD-operation-extract',
76577               title: _t.html('issues.fix.extract_point.title'),
76578               onClick: extractOnClick
76579             })];
76580           }
76581
76582           function unclosedMultipolygonPartIssues(entity, graph) {
76583             if (entity.type !== 'relation' || !entity.isMultipolygon() || entity.isDegenerate() || // cannot determine issues for incompletely-downloaded relations
76584             !entity.isComplete(graph)) return [];
76585             var sequences = osmJoinWays(entity.members, graph);
76586             var issues = [];
76587
76588             for (var i in sequences) {
76589               var sequence = sequences[i];
76590               if (!sequence.nodes) continue;
76591               var firstNode = sequence.nodes[0];
76592               var lastNode = sequence.nodes[sequence.nodes.length - 1]; // part is closed if the first and last nodes are the same
76593
76594               if (firstNode === lastNode) continue;
76595               var issue = new validationIssue({
76596                 type: type,
76597                 subtype: 'unclosed_multipolygon_part',
76598                 severity: 'warning',
76599                 message: function message(context) {
76600                   var entity = context.hasEntity(this.entityIds[0]);
76601                   return entity ? _t.html('issues.unclosed_multipolygon_part.message', {
76602                     feature: utilDisplayLabel(entity, context.graph(), true
76603                     /* verbose */
76604                     )
76605                   }) : '';
76606                 },
76607                 reference: showReference,
76608                 loc: sequence.nodes[0].loc,
76609                 entityIds: [entity.id],
76610                 hash: sequence.map(function (way) {
76611                   return way.id;
76612                 }).join()
76613               });
76614               issues.push(issue);
76615             }
76616
76617             return issues;
76618
76619             function showReference(selection) {
76620               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.unclosed_multipolygon_part.reference'));
76621             }
76622           }
76623
76624           var validation = function checkMismatchedGeometry(entity, graph) {
76625             var vertexPoint = vertexPointIssue(entity, graph);
76626             if (vertexPoint) return [vertexPoint];
76627             var lineAsArea = lineTaggedAsAreaIssue(entity);
76628             if (lineAsArea) return [lineAsArea];
76629             var mismatch = otherMismatchIssue(entity, graph);
76630             if (mismatch) return [mismatch];
76631             return unclosedMultipolygonPartIssues(entity, graph);
76632           };
76633
76634           validation.type = type;
76635           return validation;
76636         }
76637
76638         function validationMissingRole() {
76639           var type = 'missing_role';
76640
76641           var validation = function checkMissingRole(entity, graph) {
76642             var issues = [];
76643
76644             if (entity.type === 'way') {
76645               graph.parentRelations(entity).forEach(function (relation) {
76646                 if (!relation.isMultipolygon()) return;
76647                 var member = relation.memberById(entity.id);
76648
76649                 if (member && isMissingRole(member)) {
76650                   issues.push(makeIssue(entity, relation, member));
76651                 }
76652               });
76653             } else if (entity.type === 'relation' && entity.isMultipolygon()) {
76654               entity.indexedMembers().forEach(function (member) {
76655                 var way = graph.hasEntity(member.id);
76656
76657                 if (way && isMissingRole(member)) {
76658                   issues.push(makeIssue(way, entity, member));
76659                 }
76660               });
76661             }
76662
76663             return issues;
76664           };
76665
76666           function isMissingRole(member) {
76667             return !member.role || !member.role.trim().length;
76668           }
76669
76670           function makeIssue(way, relation, member) {
76671             return new validationIssue({
76672               type: type,
76673               severity: 'warning',
76674               message: function message(context) {
76675                 var member = context.hasEntity(this.entityIds[1]),
76676                     relation = context.hasEntity(this.entityIds[0]);
76677                 return member && relation ? _t.html('issues.missing_role.message', {
76678                   member: utilDisplayLabel(member, context.graph()),
76679                   relation: utilDisplayLabel(relation, context.graph())
76680                 }) : '';
76681               },
76682               reference: showReference,
76683               entityIds: [relation.id, way.id],
76684               data: {
76685                 member: member
76686               },
76687               hash: member.index.toString(),
76688               dynamicFixes: function dynamicFixes() {
76689                 return [makeAddRoleFix('inner'), makeAddRoleFix('outer'), new validationIssueFix({
76690                   icon: 'iD-operation-delete',
76691                   title: _t.html('issues.fix.remove_from_relation.title'),
76692                   onClick: function onClick(context) {
76693                     context.perform(actionDeleteMember(this.issue.entityIds[0], this.issue.data.member.index), _t('operations.delete_member.annotation', {
76694                       n: 1
76695                     }));
76696                   }
76697                 })];
76698               }
76699             });
76700
76701             function showReference(selection) {
76702               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.missing_role.multipolygon.reference'));
76703             }
76704           }
76705
76706           function makeAddRoleFix(role) {
76707             return new validationIssueFix({
76708               title: _t.html('issues.fix.set_as_' + role + '.title'),
76709               onClick: function onClick(context) {
76710                 var oldMember = this.issue.data.member;
76711                 var member = {
76712                   id: this.issue.entityIds[1],
76713                   type: oldMember.type,
76714                   role: role
76715                 };
76716                 context.perform(actionChangeMember(this.issue.entityIds[0], member, oldMember.index), _t('operations.change_role.annotation', {
76717                   n: 1
76718                 }));
76719               }
76720             });
76721           }
76722
76723           validation.type = type;
76724           return validation;
76725         }
76726
76727         function validationMissingTag(context) {
76728           var type = 'missing_tag';
76729
76730           function hasDescriptiveTags(entity, graph) {
76731             var onlyAttributeKeys = ['description', 'name', 'note', 'start_date'];
76732             var entityDescriptiveKeys = Object.keys(entity.tags).filter(function (k) {
76733               if (k === 'area' || !osmIsInterestingTag(k)) return false;
76734               return !onlyAttributeKeys.some(function (attributeKey) {
76735                 return k === attributeKey || k.indexOf(attributeKey + ':') === 0;
76736               });
76737             });
76738
76739             if (entity.type === 'relation' && entityDescriptiveKeys.length === 1 && entity.tags.type === 'multipolygon') {
76740               // this relation's only interesting tag just says its a multipolygon,
76741               // which is not descriptive enough
76742               // It's okay for a simple multipolygon to have no descriptive tags
76743               // if its outer way has them (old model, see `outdated_tags.js`)
76744               return osmOldMultipolygonOuterMemberOfRelation(entity, graph);
76745             }
76746
76747             return entityDescriptiveKeys.length > 0;
76748           }
76749
76750           function isUnknownRoad(entity) {
76751             return entity.type === 'way' && entity.tags.highway === 'road';
76752           }
76753
76754           function isUntypedRelation(entity) {
76755             return entity.type === 'relation' && !entity.tags.type;
76756           }
76757
76758           var validation = function checkMissingTag(entity, graph) {
76759             var subtype;
76760             var osm = context.connection();
76761             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
76762
76763             if (!isUnloadedNode && // allow untagged nodes that are part of ways
76764             entity.geometry(graph) !== 'vertex' && // allow untagged entities that are part of relations
76765             !entity.hasParentRelations(graph)) {
76766               if (Object.keys(entity.tags).length === 0) {
76767                 subtype = 'any';
76768               } else if (!hasDescriptiveTags(entity, graph)) {
76769                 subtype = 'descriptive';
76770               } else if (isUntypedRelation(entity)) {
76771                 subtype = 'relation_type';
76772               }
76773             } // flag an unknown road even if it's a member of a relation
76774
76775
76776             if (!subtype && isUnknownRoad(entity)) {
76777               subtype = 'highway_classification';
76778             }
76779
76780             if (!subtype) return [];
76781             var messageID = subtype === 'highway_classification' ? 'unknown_road' : 'missing_tag.' + subtype;
76782             var referenceID = subtype === 'highway_classification' ? 'unknown_road' : 'missing_tag'; // can always delete if the user created it in the first place..
76783
76784             var canDelete = entity.version === undefined || entity.v !== undefined;
76785             var severity = canDelete && subtype !== 'highway_classification' ? 'error' : 'warning';
76786             return [new validationIssue({
76787               type: type,
76788               subtype: subtype,
76789               severity: severity,
76790               message: function message(context) {
76791                 var entity = context.hasEntity(this.entityIds[0]);
76792                 return entity ? _t.html('issues.' + messageID + '.message', {
76793                   feature: utilDisplayLabel(entity, context.graph())
76794                 }) : '';
76795               },
76796               reference: showReference,
76797               entityIds: [entity.id],
76798               dynamicFixes: function dynamicFixes(context) {
76799                 var fixes = [];
76800                 var selectFixType = subtype === 'highway_classification' ? 'select_road_type' : 'select_preset';
76801                 fixes.push(new validationIssueFix({
76802                   icon: 'iD-icon-search',
76803                   title: _t.html('issues.fix.' + selectFixType + '.title'),
76804                   onClick: function onClick(context) {
76805                     context.ui().sidebar.showPresetList();
76806                   }
76807                 }));
76808                 var deleteOnClick;
76809                 var id = this.entityIds[0];
76810                 var operation = operationDelete(context, [id]);
76811                 var disabledReasonID = operation.disabled();
76812
76813                 if (!disabledReasonID) {
76814                   deleteOnClick = function deleteOnClick(context) {
76815                     var id = this.issue.entityIds[0];
76816                     var operation = operationDelete(context, [id]);
76817
76818                     if (!operation.disabled()) {
76819                       operation();
76820                     }
76821                   };
76822                 }
76823
76824                 fixes.push(new validationIssueFix({
76825                   icon: 'iD-operation-delete',
76826                   title: _t.html('issues.fix.delete_feature.title'),
76827                   disabledReason: disabledReasonID ? _t('operations.delete.' + disabledReasonID + '.single') : undefined,
76828                   onClick: deleteOnClick
76829                 }));
76830                 return fixes;
76831               }
76832             })];
76833
76834             function showReference(selection) {
76835               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.' + referenceID + '.reference'));
76836             }
76837           };
76838
76839           validation.type = type;
76840           return validation;
76841         }
76842
76843         function validationOutdatedTags() {
76844           var type = 'outdated_tags';
76845           var _waitingForDeprecated = true;
76846
76847           var _dataDeprecated; // fetch deprecated tags
76848
76849
76850           _mainFileFetcher.get('deprecated').then(function (d) {
76851             return _dataDeprecated = d;
76852           })["catch"](function () {
76853             /* ignore */
76854           })["finally"](function () {
76855             return _waitingForDeprecated = false;
76856           });
76857
76858           function oldTagIssues(entity, graph) {
76859             var oldTags = Object.assign({}, entity.tags); // shallow copy
76860
76861             var preset = _mainPresetIndex.match(entity, graph);
76862             var subtype = 'deprecated_tags';
76863             if (!preset) return [];
76864             if (!entity.hasInterestingTags()) return []; // Upgrade preset, if a replacement is available..
76865
76866             if (preset.replacement) {
76867               var newPreset = _mainPresetIndex.item(preset.replacement);
76868               graph = actionChangePreset(entity.id, preset, newPreset, true
76869               /* skip field defaults */
76870               )(graph);
76871               entity = graph.entity(entity.id);
76872               preset = newPreset;
76873             } // Upgrade deprecated tags..
76874
76875
76876             if (_dataDeprecated) {
76877               var deprecatedTags = entity.deprecatedTags(_dataDeprecated);
76878
76879               if (deprecatedTags.length) {
76880                 deprecatedTags.forEach(function (tag) {
76881                   graph = actionUpgradeTags(entity.id, tag.old, tag.replace)(graph);
76882                 });
76883                 entity = graph.entity(entity.id);
76884               }
76885             } // Add missing addTags from the detected preset
76886
76887
76888             var newTags = Object.assign({}, entity.tags); // shallow copy
76889
76890             if (preset.tags !== preset.addTags) {
76891               Object.keys(preset.addTags).forEach(function (k) {
76892                 if (!newTags[k]) {
76893                   if (preset.addTags[k] === '*') {
76894                     newTags[k] = 'yes';
76895                   } else {
76896                     newTags[k] = preset.addTags[k];
76897                   }
76898                 }
76899               });
76900             } // Attempt to match a canonical record in the name-suggestion-index.
76901
76902
76903             var nsi = services.nsi;
76904             var waitingForNsi = false;
76905             var nsiResult;
76906
76907             if (nsi) {
76908               waitingForNsi = nsi.status() === 'loading';
76909
76910               if (!waitingForNsi) {
76911                 var loc = entity.extent(graph).center();
76912                 nsiResult = nsi.upgradeTags(newTags, loc);
76913
76914                 if (nsiResult) {
76915                   newTags = nsiResult.newTags;
76916                   subtype = 'noncanonical_brand';
76917                 }
76918               }
76919             }
76920
76921             var issues = [];
76922             issues.provisional = _waitingForDeprecated || waitingForNsi; // determine diff
76923
76924             var tagDiff = utilTagDiff(oldTags, newTags);
76925             if (!tagDiff.length) return issues;
76926             var isOnlyAddingTags = tagDiff.every(function (d) {
76927               return d.type === '+';
76928             });
76929             var prefix = '';
76930
76931             if (nsiResult) {
76932               prefix = 'noncanonical_brand.';
76933             } else if (subtype === 'deprecated_tags' && isOnlyAddingTags) {
76934               subtype = 'incomplete_tags';
76935               prefix = 'incomplete.';
76936             } // don't allow autofixing brand tags
76937
76938
76939             var autoArgs = subtype !== 'noncanonical_brand' ? [doUpgrade, _t('issues.fix.upgrade_tags.annotation')] : null;
76940             issues.push(new validationIssue({
76941               type: type,
76942               subtype: subtype,
76943               severity: 'warning',
76944               message: showMessage,
76945               reference: showReference,
76946               entityIds: [entity.id],
76947               hash: utilHashcode(JSON.stringify(tagDiff)),
76948               dynamicFixes: function dynamicFixes() {
76949                 var fixes = [new validationIssueFix({
76950                   autoArgs: autoArgs,
76951                   title: _t.html('issues.fix.upgrade_tags.title'),
76952                   onClick: function onClick(context) {
76953                     context.perform(doUpgrade, _t('issues.fix.upgrade_tags.annotation'));
76954                   }
76955                 })];
76956                 var item = nsiResult && nsiResult.matched;
76957
76958                 if (item) {
76959                   fixes.push(new validationIssueFix({
76960                     title: _t.html('issues.fix.tag_as_not.title', {
76961                       name: item.displayName
76962                     }),
76963                     onClick: function onClick(context) {
76964                       context.perform(addNotTag, _t('issues.fix.tag_as_not.annotation'));
76965                     }
76966                   }));
76967                 }
76968
76969                 return fixes;
76970               }
76971             }));
76972             return issues;
76973
76974             function doUpgrade(graph) {
76975               var currEntity = graph.hasEntity(entity.id);
76976               if (!currEntity) return graph;
76977               var newTags = Object.assign({}, currEntity.tags); // shallow copy
76978
76979               tagDiff.forEach(function (diff) {
76980                 if (diff.type === '-') {
76981                   delete newTags[diff.key];
76982                 } else if (diff.type === '+') {
76983                   newTags[diff.key] = diff.newVal;
76984                 }
76985               });
76986               return actionChangeTags(currEntity.id, newTags)(graph);
76987             }
76988
76989             function addNotTag(graph) {
76990               var currEntity = graph.hasEntity(entity.id);
76991               if (!currEntity) return graph;
76992               var item = nsiResult && nsiResult.matched;
76993               if (!item) return graph;
76994               var newTags = Object.assign({}, currEntity.tags); // shallow copy
76995
76996               var wd = item.mainTag; // e.g. `brand:wikidata`
76997
76998               var notwd = "not:".concat(wd); // e.g. `not:brand:wikidata`
76999
77000               var qid = item.tags[wd];
77001               newTags[notwd] = qid;
77002
77003               if (newTags[wd] === qid) {
77004                 // if `brand:wikidata` was set to that qid
77005                 var wp = item.mainTag.replace('wikidata', 'wikipedia');
77006                 delete newTags[wd]; // remove `brand:wikidata`
77007
77008                 delete newTags[wp]; // remove `brand:wikipedia`
77009               }
77010
77011               return actionChangeTags(currEntity.id, newTags)(graph);
77012             }
77013
77014             function showMessage(context) {
77015               var currEntity = context.hasEntity(entity.id);
77016               if (!currEntity) return '';
77017               var messageID = "issues.outdated_tags.".concat(prefix, "message");
77018
77019               if (subtype === 'noncanonical_brand' && isOnlyAddingTags) {
77020                 messageID += '_incomplete';
77021               }
77022
77023               return _t.html(messageID, {
77024                 feature: utilDisplayLabel(currEntity, context.graph(), true
77025                 /* verbose */
77026                 )
77027               });
77028             }
77029
77030             function showReference(selection) {
77031               var enter = selection.selectAll('.issue-reference').data([0]).enter();
77032               enter.append('div').attr('class', 'issue-reference').call(_t.append("issues.outdated_tags.".concat(prefix, "reference")));
77033               enter.append('strong').call(_t.append('issues.suggested'));
77034               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) {
77035                 var klass = d.type === '+' ? 'add' : 'remove';
77036                 return "tagDiff-cell tagDiff-cell-".concat(klass);
77037               }).html(function (d) {
77038                 return d.display;
77039               });
77040             }
77041           }
77042
77043           function oldMultipolygonIssues(entity, graph) {
77044             var multipolygon, outerWay;
77045
77046             if (entity.type === 'relation') {
77047               outerWay = osmOldMultipolygonOuterMemberOfRelation(entity, graph);
77048               multipolygon = entity;
77049             } else if (entity.type === 'way') {
77050               multipolygon = osmIsOldMultipolygonOuterMember(entity, graph);
77051               outerWay = entity;
77052             } else {
77053               return [];
77054             }
77055
77056             if (!multipolygon || !outerWay) return [];
77057             return [new validationIssue({
77058               type: type,
77059               subtype: 'old_multipolygon',
77060               severity: 'warning',
77061               message: showMessage,
77062               reference: showReference,
77063               entityIds: [outerWay.id, multipolygon.id],
77064               dynamicFixes: function dynamicFixes() {
77065                 return [new validationIssueFix({
77066                   autoArgs: [doUpgrade, _t('issues.fix.move_tags.annotation')],
77067                   title: _t.html('issues.fix.move_tags.title'),
77068                   onClick: function onClick(context) {
77069                     context.perform(doUpgrade, _t('issues.fix.move_tags.annotation'));
77070                   }
77071                 })];
77072               }
77073             })];
77074
77075             function doUpgrade(graph) {
77076               var currMultipolygon = graph.hasEntity(multipolygon.id);
77077               var currOuterWay = graph.hasEntity(outerWay.id);
77078               if (!currMultipolygon || !currOuterWay) return graph;
77079               currMultipolygon = currMultipolygon.mergeTags(currOuterWay.tags);
77080               graph = graph.replace(currMultipolygon);
77081               return actionChangeTags(currOuterWay.id, {})(graph);
77082             }
77083
77084             function showMessage(context) {
77085               var currMultipolygon = context.hasEntity(multipolygon.id);
77086               if (!currMultipolygon) return '';
77087               return _t.html('issues.old_multipolygon.message', {
77088                 multipolygon: utilDisplayLabel(currMultipolygon, context.graph(), true
77089                 /* verbose */
77090                 )
77091               });
77092             }
77093
77094             function showReference(selection) {
77095               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.old_multipolygon.reference'));
77096             }
77097           }
77098
77099           var validation = function checkOutdatedTags(entity, graph) {
77100             var issues = oldMultipolygonIssues(entity, graph);
77101             if (!issues.length) issues = oldTagIssues(entity, graph);
77102             return issues;
77103           };
77104
77105           validation.type = type;
77106           return validation;
77107         }
77108
77109         function validationPrivateData() {
77110           var type = 'private_data'; // assume that some buildings are private
77111
77112           var privateBuildingValues = {
77113             detached: true,
77114             farm: true,
77115             house: true,
77116             houseboat: true,
77117             residential: true,
77118             semidetached_house: true,
77119             static_caravan: true
77120           }; // but they might be public if they have one of these other tags
77121
77122           var publicKeys = {
77123             amenity: true,
77124             craft: true,
77125             historic: true,
77126             leisure: true,
77127             office: true,
77128             shop: true,
77129             tourism: true
77130           }; // these tags may contain personally identifying info
77131
77132           var personalTags = {
77133             'contact:email': true,
77134             'contact:fax': true,
77135             'contact:phone': true,
77136             email: true,
77137             fax: true,
77138             phone: true
77139           };
77140
77141           var validation = function checkPrivateData(entity) {
77142             var tags = entity.tags;
77143             if (!tags.building || !privateBuildingValues[tags.building]) return [];
77144             var keepTags = {};
77145
77146             for (var k in tags) {
77147               if (publicKeys[k]) return []; // probably a public feature
77148
77149               if (!personalTags[k]) {
77150                 keepTags[k] = tags[k];
77151               }
77152             }
77153
77154             var tagDiff = utilTagDiff(tags, keepTags);
77155             if (!tagDiff.length) return [];
77156             var fixID = tagDiff.length === 1 ? 'remove_tag' : 'remove_tags';
77157             return [new validationIssue({
77158               type: type,
77159               severity: 'warning',
77160               message: showMessage,
77161               reference: showReference,
77162               entityIds: [entity.id],
77163               dynamicFixes: function dynamicFixes() {
77164                 return [new validationIssueFix({
77165                   icon: 'iD-operation-delete',
77166                   title: _t.html('issues.fix.' + fixID + '.title'),
77167                   onClick: function onClick(context) {
77168                     context.perform(doUpgrade, _t('issues.fix.upgrade_tags.annotation'));
77169                   }
77170                 })];
77171               }
77172             })];
77173
77174             function doUpgrade(graph) {
77175               var currEntity = graph.hasEntity(entity.id);
77176               if (!currEntity) return graph;
77177               var newTags = Object.assign({}, currEntity.tags); // shallow copy
77178
77179               tagDiff.forEach(function (diff) {
77180                 if (diff.type === '-') {
77181                   delete newTags[diff.key];
77182                 } else if (diff.type === '+') {
77183                   newTags[diff.key] = diff.newVal;
77184                 }
77185               });
77186               return actionChangeTags(currEntity.id, newTags)(graph);
77187             }
77188
77189             function showMessage(context) {
77190               var currEntity = context.hasEntity(this.entityIds[0]);
77191               if (!currEntity) return '';
77192               return _t.html('issues.private_data.contact.message', {
77193                 feature: utilDisplayLabel(currEntity, context.graph())
77194               });
77195             }
77196
77197             function showReference(selection) {
77198               var enter = selection.selectAll('.issue-reference').data([0]).enter();
77199               enter.append('div').attr('class', 'issue-reference').call(_t.append('issues.private_data.reference'));
77200               enter.append('strong').call(_t.append('issues.suggested'));
77201               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) {
77202                 var klass = d.type === '+' ? 'add' : 'remove';
77203                 return 'tagDiff-cell tagDiff-cell-' + klass;
77204               }).html(function (d) {
77205                 return d.display;
77206               });
77207             }
77208           };
77209
77210           validation.type = type;
77211           return validation;
77212         }
77213
77214         function validationSuspiciousName() {
77215           var type = 'suspicious_name';
77216           var keysToTestForGenericValues = ['aerialway', 'aeroway', 'amenity', 'building', 'craft', 'highway', 'leisure', 'railway', 'man_made', 'office', 'shop', 'tourism', 'waterway'];
77217           var _waitingForNsi = false; // Attempt to match a generic record in the name-suggestion-index.
77218
77219           function isGenericMatchInNsi(tags) {
77220             var nsi = services.nsi;
77221
77222             if (nsi) {
77223               _waitingForNsi = nsi.status() === 'loading';
77224
77225               if (!_waitingForNsi) {
77226                 return nsi.isGenericName(tags);
77227               }
77228             }
77229
77230             return false;
77231           } // Test if the name is just the key or tag value (e.g. "park")
77232
77233
77234           function nameMatchesRawTag(lowercaseName, tags) {
77235             for (var i = 0; i < keysToTestForGenericValues.length; i++) {
77236               var key = keysToTestForGenericValues[i];
77237               var val = tags[key];
77238
77239               if (val) {
77240                 val = val.toLowerCase();
77241
77242                 if (key === lowercaseName || val === lowercaseName || key.replace(/\_/g, ' ') === lowercaseName || val.replace(/\_/g, ' ') === lowercaseName) {
77243                   return true;
77244                 }
77245               }
77246             }
77247
77248             return false;
77249           }
77250
77251           function isGenericName(name, tags) {
77252             name = name.toLowerCase();
77253             return nameMatchesRawTag(name, tags) || isGenericMatchInNsi(tags);
77254           }
77255
77256           function makeGenericNameIssue(entityId, nameKey, genericName, langCode) {
77257             return new validationIssue({
77258               type: type,
77259               subtype: 'generic_name',
77260               severity: 'warning',
77261               message: function message(context) {
77262                 var entity = context.hasEntity(this.entityIds[0]);
77263                 if (!entity) return '';
77264                 var preset = _mainPresetIndex.match(entity, context.graph());
77265                 var langName = langCode && _mainLocalizer.languageName(langCode);
77266                 return _t.html('issues.generic_name.message' + (langName ? '_language' : ''), {
77267                   feature: preset.name(),
77268                   name: genericName,
77269                   language: langName
77270                 });
77271               },
77272               reference: showReference,
77273               entityIds: [entityId],
77274               hash: "".concat(nameKey, "=").concat(genericName),
77275               dynamicFixes: function dynamicFixes() {
77276                 return [new validationIssueFix({
77277                   icon: 'iD-operation-delete',
77278                   title: _t.html('issues.fix.remove_the_name.title'),
77279                   onClick: function onClick(context) {
77280                     var entityId = this.issue.entityIds[0];
77281                     var entity = context.entity(entityId);
77282                     var tags = Object.assign({}, entity.tags); // shallow copy
77283
77284                     delete tags[nameKey];
77285                     context.perform(actionChangeTags(entityId, tags), _t('issues.fix.remove_generic_name.annotation'));
77286                   }
77287                 })];
77288               }
77289             });
77290
77291             function showReference(selection) {
77292               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.generic_name.reference'));
77293             }
77294           }
77295
77296           function makeIncorrectNameIssue(entityId, nameKey, incorrectName, langCode) {
77297             return new validationIssue({
77298               type: type,
77299               subtype: 'not_name',
77300               severity: 'warning',
77301               message: function message(context) {
77302                 var entity = context.hasEntity(this.entityIds[0]);
77303                 if (!entity) return '';
77304                 var preset = _mainPresetIndex.match(entity, context.graph());
77305                 var langName = langCode && _mainLocalizer.languageName(langCode);
77306                 return _t.html('issues.incorrect_name.message' + (langName ? '_language' : ''), {
77307                   feature: preset.name(),
77308                   name: incorrectName,
77309                   language: langName
77310                 });
77311               },
77312               reference: showReference,
77313               entityIds: [entityId],
77314               hash: "".concat(nameKey, "=").concat(incorrectName),
77315               dynamicFixes: function dynamicFixes() {
77316                 return [new validationIssueFix({
77317                   icon: 'iD-operation-delete',
77318                   title: _t.html('issues.fix.remove_the_name.title'),
77319                   onClick: function onClick(context) {
77320                     var entityId = this.issue.entityIds[0];
77321                     var entity = context.entity(entityId);
77322                     var tags = Object.assign({}, entity.tags); // shallow copy
77323
77324                     delete tags[nameKey];
77325                     context.perform(actionChangeTags(entityId, tags), _t('issues.fix.remove_mistaken_name.annotation'));
77326                   }
77327                 })];
77328               }
77329             });
77330
77331             function showReference(selection) {
77332               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.generic_name.reference'));
77333             }
77334           }
77335
77336           var validation = function checkGenericName(entity) {
77337             var tags = entity.tags; // a generic name is allowed if it's a known brand or entity
77338
77339             var hasWikidata = !!tags.wikidata || !!tags['brand:wikidata'] || !!tags['operator:wikidata'];
77340             if (hasWikidata) return [];
77341             var issues = [];
77342             var notNames = (tags['not:name'] || '').split(';');
77343
77344             for (var key in tags) {
77345               var m = key.match(/^name(?:(?::)([a-zA-Z_-]+))?$/);
77346               if (!m) continue;
77347               var langCode = m.length >= 2 ? m[1] : null;
77348               var value = tags[key];
77349
77350               if (notNames.length) {
77351                 for (var i in notNames) {
77352                   var notName = notNames[i];
77353
77354                   if (notName && value === notName) {
77355                     issues.push(makeIncorrectNameIssue(entity.id, key, value, langCode));
77356                     continue;
77357                   }
77358                 }
77359               }
77360
77361               if (isGenericName(value, tags)) {
77362                 issues.provisional = _waitingForNsi; // retry later if we are waiting on NSI to finish loading
77363
77364                 issues.push(makeGenericNameIssue(entity.id, key, value, langCode));
77365               }
77366             }
77367
77368             return issues;
77369           };
77370
77371           validation.type = type;
77372           return validation;
77373         }
77374
77375         function validationUnsquareWay(context) {
77376           var type = 'unsquare_way';
77377           var DEFAULT_DEG_THRESHOLD = 5; // see also issues.js
77378           // use looser epsilon for detection to reduce warnings of buildings that are essentially square already
77379
77380           var epsilon = 0.05;
77381           var nodeThreshold = 10;
77382
77383           function isBuilding(entity, graph) {
77384             if (entity.type !== 'way' || entity.geometry(graph) !== 'area') return false;
77385             return entity.tags.building && entity.tags.building !== 'no';
77386           }
77387
77388           var validation = function checkUnsquareWay(entity, graph) {
77389             if (!isBuilding(entity, graph)) return []; // don't flag ways marked as physically unsquare
77390
77391             if (entity.tags.nonsquare === 'yes') return [];
77392             var isClosed = entity.isClosed();
77393             if (!isClosed) return []; // this building has bigger problems
77394             // don't flag ways with lots of nodes since they are likely detail-mapped
77395
77396             var nodes = graph.childNodes(entity).slice(); // shallow copy
77397
77398             if (nodes.length > nodeThreshold + 1) return []; // +1 because closing node appears twice
77399             // ignore if not all nodes are fully downloaded
77400
77401             var osm = services.osm;
77402             if (!osm || nodes.some(function (node) {
77403               return !osm.isDataLoaded(node.loc);
77404             })) return []; // don't flag connected ways to avoid unresolvable unsquare loops
77405
77406             var hasConnectedSquarableWays = nodes.some(function (node) {
77407               return graph.parentWays(node).some(function (way) {
77408                 if (way.id === entity.id) return false;
77409                 if (isBuilding(way, graph)) return true;
77410                 return graph.parentRelations(way).some(function (parentRelation) {
77411                   return parentRelation.isMultipolygon() && parentRelation.tags.building && parentRelation.tags.building !== 'no';
77412                 });
77413               });
77414             });
77415             if (hasConnectedSquarableWays) return []; // user-configurable square threshold
77416
77417             var storedDegreeThreshold = corePreferences('validate-square-degrees');
77418             var degreeThreshold = isNaN(storedDegreeThreshold) ? DEFAULT_DEG_THRESHOLD : parseFloat(storedDegreeThreshold);
77419             var points = nodes.map(function (node) {
77420               return context.projection(node.loc);
77421             });
77422             if (!geoOrthoCanOrthogonalize(points, isClosed, epsilon, degreeThreshold, true)) return [];
77423             var autoArgs; // don't allow autosquaring features linked to wikidata
77424
77425             if (!entity.tags.wikidata) {
77426               // use same degree threshold as for detection
77427               var autoAction = actionOrthogonalize(entity.id, context.projection, undefined, degreeThreshold);
77428               autoAction.transitionable = false; // when autofixing, do it instantly
77429
77430               autoArgs = [autoAction, _t('operations.orthogonalize.annotation.feature', {
77431                 n: 1
77432               })];
77433             }
77434
77435             return [new validationIssue({
77436               type: type,
77437               subtype: 'building',
77438               severity: 'warning',
77439               message: function message(context) {
77440                 var entity = context.hasEntity(this.entityIds[0]);
77441                 return entity ? _t.html('issues.unsquare_way.message', {
77442                   feature: utilDisplayLabel(entity, context.graph())
77443                 }) : '';
77444               },
77445               reference: showReference,
77446               entityIds: [entity.id],
77447               hash: degreeThreshold,
77448               dynamicFixes: function dynamicFixes() {
77449                 return [new validationIssueFix({
77450                   icon: 'iD-operation-orthogonalize',
77451                   title: _t.html('issues.fix.square_feature.title'),
77452                   autoArgs: autoArgs,
77453                   onClick: function onClick(context, completionHandler) {
77454                     var entityId = this.issue.entityIds[0]; // use same degree threshold as for detection
77455
77456                     context.perform(actionOrthogonalize(entityId, context.projection, undefined, degreeThreshold), _t('operations.orthogonalize.annotation.feature', {
77457                       n: 1
77458                     })); // run after the squaring transition (currently 150ms)
77459
77460                     window.setTimeout(function () {
77461                       completionHandler();
77462                     }, 175);
77463                   }
77464                 })
77465                 /*
77466                 new validationIssueFix({
77467                     title: t.html('issues.fix.tag_as_unsquare.title'),
77468                     onClick: function(context) {
77469                         var entityId = this.issue.entityIds[0];
77470                         var entity = context.entity(entityId);
77471                         var tags = Object.assign({}, entity.tags);  // shallow copy
77472                         tags.nonsquare = 'yes';
77473                         context.perform(
77474                             actionChangeTags(entityId, tags),
77475                             t('issues.fix.tag_as_unsquare.annotation')
77476                         );
77477                     }
77478                 })
77479                 */
77480                 ];
77481               }
77482             })];
77483
77484             function showReference(selection) {
77485               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.unsquare_way.buildings.reference'));
77486             }
77487           };
77488
77489           validation.type = type;
77490           return validation;
77491         }
77492
77493         var Validations = /*#__PURE__*/Object.freeze({
77494                 __proto__: null,
77495                 validationAlmostJunction: validationAlmostJunction,
77496                 validationCloseNodes: validationCloseNodes,
77497                 validationCrossingWays: validationCrossingWays,
77498                 validationDisconnectedWay: validationDisconnectedWay,
77499                 validationFormatting: validationFormatting,
77500                 validationHelpRequest: validationHelpRequest,
77501                 validationImpossibleOneway: validationImpossibleOneway,
77502                 validationIncompatibleSource: validationIncompatibleSource,
77503                 validationMaprules: validationMaprules,
77504                 validationMismatchedGeometry: validationMismatchedGeometry,
77505                 validationMissingRole: validationMissingRole,
77506                 validationMissingTag: validationMissingTag,
77507                 validationOutdatedTags: validationOutdatedTags,
77508                 validationPrivateData: validationPrivateData,
77509                 validationSuspiciousName: validationSuspiciousName,
77510                 validationUnsquareWay: validationUnsquareWay
77511         });
77512
77513         function coreValidator(context) {
77514           var _this = this;
77515
77516           var dispatch = dispatch$8('validated', 'focusedIssue');
77517           var validator = utilRebind({}, dispatch, 'on');
77518           var _rules = {};
77519           var _disabledRules = {};
77520
77521           var _ignoredIssueIDs = new Set();
77522
77523           var _resolvedIssueIDs = new Set();
77524
77525           var _baseCache = validationCache('base'); // issues before any user edits
77526
77527
77528           var _headCache = validationCache('head'); // issues after all user edits
77529
77530
77531           var _completeDiff = {}; // complete diff base -> head of what the user changed
77532
77533           var _headIsCurrent = false;
77534
77535           var _deferredRIC = new Set(); // Set( RequestIdleCallback handles )
77536
77537
77538           var _deferredST = new Set(); // Set( SetTimeout handles )
77539
77540
77541           var _headPromise; // Promise fulfilled when validation is performed up to headGraph snapshot
77542
77543
77544           var RETRY = 5000; // wait 5sec before revalidating provisional entities
77545           // Allow validation severity to be overridden by url queryparams...
77546           // See: https://github.com/openstreetmap/iD/pull/8243
77547           //
77548           // Each param should contain a urlencoded comma separated list of
77549           // `type/subtype` rules.  `*` may be used as a wildcard..
77550           // Examples:
77551           //  `validationError=disconnected_way/*`
77552           //  `validationError=disconnected_way/highway`
77553           //  `validationError=crossing_ways/bridge*`
77554           //  `validationError=crossing_ways/bridge*,crossing_ways/tunnel*`
77555
77556           var _errorOverrides = parseHashParam(context.initialHashParams.validationError);
77557
77558           var _warningOverrides = parseHashParam(context.initialHashParams.validationWarning);
77559
77560           var _disableOverrides = parseHashParam(context.initialHashParams.validationDisable); // `parseHashParam()`   (private)
77561           // Checks hash parameters for severity overrides
77562           // Arguments
77563           //   `param` - a url hash parameter (`validationError`, `validationWarning`, or `validationDisable`)
77564           // Returns
77565           //   Array of Objects like { type: RegExp, subtype: RegExp }
77566           //
77567
77568
77569           function parseHashParam(param) {
77570             var result = [];
77571             var rules = (param || '').split(',');
77572             rules.forEach(function (rule) {
77573               rule = rule.trim();
77574               var parts = rule.split('/', 2); // "type/subtype"
77575
77576               var type = parts[0];
77577               var subtype = parts[1] || '*';
77578               if (!type || !subtype) return;
77579               result.push({
77580                 type: makeRegExp(type),
77581                 subtype: makeRegExp(subtype)
77582               });
77583             });
77584             return result;
77585
77586             function makeRegExp(str) {
77587               var escaped = str.replace(/[-\/\\^$+?.()|[\]{}]/g, '\\$&') // escape all reserved chars except for the '*'
77588               .replace(/\*/g, '.*'); // treat a '*' like '.*'
77589
77590               return new RegExp('^' + escaped + '$');
77591             }
77592           } // `init()`
77593           // Initialize the validator, called once on iD startup
77594           //
77595
77596
77597           validator.init = function () {
77598             Object.values(Validations).forEach(function (validation) {
77599               if (typeof validation !== 'function') return;
77600               var fn = validation(context);
77601               var key = fn.type;
77602               _rules[key] = fn;
77603             });
77604             var disabledRules = corePreferences('validate-disabledRules');
77605
77606             if (disabledRules) {
77607               disabledRules.split(',').forEach(function (k) {
77608                 return _disabledRules[k] = true;
77609               });
77610             }
77611           }; // `reset()`   (private)
77612           // Cancels deferred work and resets all caches
77613           //
77614           // Arguments
77615           //   `resetIgnored` - `true` to clear the list of user-ignored issues
77616           //
77617
77618
77619           function reset(resetIgnored) {
77620             // cancel deferred work
77621             _deferredRIC.forEach(window.cancelIdleCallback);
77622
77623             _deferredRIC.clear();
77624
77625             _deferredST.forEach(window.clearTimeout);
77626
77627             _deferredST.clear(); // empty queues and resolve any pending promise
77628
77629
77630             _baseCache.queue = [];
77631             _headCache.queue = [];
77632             processQueue(_headCache);
77633             processQueue(_baseCache); // clear caches
77634
77635             if (resetIgnored) _ignoredIssueIDs.clear();
77636
77637             _resolvedIssueIDs.clear();
77638
77639             _baseCache = validationCache('base');
77640             _headCache = validationCache('head');
77641             _completeDiff = {};
77642             _headIsCurrent = false;
77643           } // `reset()`
77644           // clear caches, called whenever iD resets after a save or switches sources
77645           // (clears out the _ignoredIssueIDs set also)
77646           //
77647
77648
77649           validator.reset = function () {
77650             reset(true);
77651           }; // `resetIgnoredIssues()`
77652           // clears out the _ignoredIssueIDs Set
77653           //
77654
77655
77656           validator.resetIgnoredIssues = function () {
77657             _ignoredIssueIDs.clear();
77658
77659             dispatch.call('validated'); // redraw UI
77660           }; // `revalidateUnsquare()`
77661           // Called whenever the user changes the unsquare threshold
77662           // It reruns just the "unsquare_way" validation on all buildings.
77663           //
77664
77665
77666           validator.revalidateUnsquare = function () {
77667             revalidateUnsquare(_headCache);
77668             revalidateUnsquare(_baseCache);
77669             dispatch.call('validated');
77670           };
77671
77672           function revalidateUnsquare(cache) {
77673             var checkUnsquareWay = _rules.unsquare_way;
77674             if (!cache.graph || typeof checkUnsquareWay !== 'function') return; // uncache existing
77675
77676             cache.uncacheIssuesOfType('unsquare_way');
77677             var buildings = context.history().tree().intersects(geoExtent([-180, -90], [180, 90]), cache.graph) // everywhere
77678             .filter(function (entity) {
77679               return entity.type === 'way' && entity.tags.building && entity.tags.building !== 'no';
77680             }); // rerun for all buildings
77681
77682             buildings.forEach(function (entity) {
77683               var detected = checkUnsquareWay(entity, cache.graph);
77684               if (!detected.length) return;
77685               cache.cacheIssues(detected);
77686             });
77687           } // `getIssues()`
77688           // Gets all issues that match the given options
77689           // This is called by many other places
77690           //
77691           // Arguments
77692           //   `options` Object like:
77693           //   {
77694           //     what: 'all',                  // 'all' or 'edited'
77695           //     where: 'all',                 // 'all' or 'visible'
77696           //     includeIgnored: false,        // true, false, or 'only'
77697           //     includeDisabledRules: false   // true, false, or 'only'
77698           //   }
77699           //
77700           // Returns
77701           //   An Array containing the issues
77702           //
77703
77704
77705           validator.getIssues = function (options) {
77706             var opts = Object.assign({
77707               what: 'all',
77708               where: 'all',
77709               includeIgnored: false,
77710               includeDisabledRules: false
77711             }, options);
77712             var view = context.map().extent();
77713             var seen = new Set();
77714             var results = []; // collect head issues - present in the user edits
77715
77716             if (_headCache.graph && _headCache.graph !== _baseCache.graph) {
77717               Object.values(_headCache.issuesByIssueID).forEach(function (issue) {
77718                 // In the head cache, only count features that the user is responsible for - #8632
77719                 // For example, a user can undo some work and an issue will still present in the
77720                 // head graph, but we don't want to credit the user for causing that issue.
77721                 var userModified = (issue.entityIds || []).some(function (id) {
77722                   return _completeDiff.hasOwnProperty(id);
77723                 });
77724                 if (opts.what === 'edited' && !userModified) return; // present in head but user didn't touch it
77725
77726                 if (!filter(issue)) return;
77727                 seen.add(issue.id);
77728                 results.push(issue);
77729               });
77730             } // collect base issues - present before user edits
77731
77732
77733             if (opts.what === 'all') {
77734               Object.values(_baseCache.issuesByIssueID).forEach(function (issue) {
77735                 if (!filter(issue)) return;
77736                 seen.add(issue.id);
77737                 results.push(issue);
77738               });
77739             }
77740
77741             return results; // Filter the issue set to include only what the calling code wants to see.
77742             // Note that we use `context.graph()`/`context.hasEntity()` here, not `cache.graph`,
77743             // because that is the graph that the calling code will be using.
77744
77745             function filter(issue) {
77746               if (!issue) return false;
77747               if (seen.has(issue.id)) return false;
77748               if (_resolvedIssueIDs.has(issue.id)) return false;
77749               if (opts.includeDisabledRules === 'only' && !_disabledRules[issue.type]) return false;
77750               if (!opts.includeDisabledRules && _disabledRules[issue.type]) return false;
77751               if (opts.includeIgnored === 'only' && !_ignoredIssueIDs.has(issue.id)) return false;
77752               if (!opts.includeIgnored && _ignoredIssueIDs.has(issue.id)) return false; // This issue may involve an entity that doesn't exist in context.graph()
77753               // This can happen because validation is async and rendering the issue lists is async.
77754
77755               if ((issue.entityIds || []).some(function (id) {
77756                 return !context.hasEntity(id);
77757               })) return false;
77758
77759               if (opts.where === 'visible') {
77760                 var extent = issue.extent(context.graph());
77761                 if (!view.intersects(extent)) return false;
77762               }
77763
77764               return true;
77765             }
77766           }; // `getResolvedIssues()`
77767           // Gets the issues that have been fixed by the user.
77768           //
77769           // Resolved issues are tracked in the `_resolvedIssueIDs` Set,
77770           // and they should all be issues that exist in the _baseCache.
77771           //
77772           // Returns
77773           //   An Array containing the issues
77774           //
77775
77776
77777           validator.getResolvedIssues = function () {
77778             return Array.from(_resolvedIssueIDs).map(function (issueID) {
77779               return _baseCache.issuesByIssueID[issueID];
77780             }).filter(Boolean);
77781           }; // `focusIssue()`
77782           // Adjusts the map to focus on the given issue.
77783           // (requires the issue to have a reasonable extent defined)
77784           //
77785           // Arguments
77786           //   `issue` - the issue to focus on
77787           //
77788
77789
77790           validator.focusIssue = function (issue) {
77791             // Note that we use `context.graph()`/`context.hasEntity()` here, not `cache.graph`,
77792             // because that is the graph that the calling code will be using.
77793             var graph = context.graph();
77794             var selectID;
77795             var focusCenter; // Try to focus the map at the center of the issue..
77796
77797             var issueExtent = issue.extent(graph);
77798
77799             if (issueExtent) {
77800               focusCenter = issueExtent.center();
77801             } // Try to select the first entity in the issue..
77802
77803
77804             if (issue.entityIds && issue.entityIds.length) {
77805               selectID = issue.entityIds[0]; // If a relation, focus on one of its members instead.
77806               // Otherwise we might be focusing on a part of map where the relation is not visible.
77807
77808               if (selectID && selectID.charAt(0) === 'r') {
77809                 // relation
77810                 var ids = utilEntityAndDeepMemberIDs([selectID], graph);
77811                 var nodeID = ids.find(function (id) {
77812                   return id.charAt(0) === 'n' && graph.hasEntity(id);
77813                 });
77814
77815                 if (!nodeID) {
77816                   // relation has no downloaded nodes to focus on
77817                   var wayID = ids.find(function (id) {
77818                     return id.charAt(0) === 'w' && graph.hasEntity(id);
77819                   });
77820
77821                   if (wayID) {
77822                     nodeID = graph.entity(wayID).first(); // focus on the first node of this way
77823                   }
77824                 }
77825
77826                 if (nodeID) {
77827                   focusCenter = graph.entity(nodeID).loc;
77828                 }
77829               }
77830             }
77831
77832             if (focusCenter) {
77833               // Adjust the view
77834               var setZoom = Math.max(context.map().zoom(), 19);
77835               context.map().unobscuredCenterZoomEase(focusCenter, setZoom);
77836             }
77837
77838             if (selectID) {
77839               // Enter select mode
77840               window.setTimeout(function () {
77841                 context.enter(modeSelect(context, [selectID]));
77842                 dispatch.call('focusedIssue', _this, issue);
77843               }, 250); // after ease
77844             }
77845           }; // `getIssuesBySeverity()`
77846           // Gets the issues then groups them by error/warning
77847           // (This just calls getIssues, then puts issues in groups)
77848           //
77849           // Arguments
77850           //   `options` - (see `getIssues`)
77851           // Returns
77852           //   Object result like:
77853           //   {
77854           //     error:    Array of errors,
77855           //     warning:  Array of warnings
77856           //   }
77857           //
77858
77859
77860           validator.getIssuesBySeverity = function (options) {
77861             var groups = utilArrayGroupBy(validator.getIssues(options), 'severity');
77862             groups.error = groups.error || [];
77863             groups.warning = groups.warning || [];
77864             return groups;
77865           }; // `getEntityIssues()`
77866           // Gets the issues that the given entity IDs have in common, matching the given options
77867           // (This just calls getIssues, then filters for the given entity IDs)
77868           // The issues are sorted for relevance
77869           //
77870           // Arguments
77871           //   `entityIDs` - Array or Set of entityIDs to get issues for
77872           //   `options` - (see `getIssues`)
77873           // Returns
77874           //   An Array containing the issues
77875           //
77876
77877
77878           validator.getSharedEntityIssues = function (entityIDs, options) {
77879             var orderedIssueTypes = [// Show some issue types in a particular order:
77880             'missing_tag', 'missing_role', // - missing data first
77881             'outdated_tags', 'mismatched_geometry', // - identity issues
77882             'crossing_ways', 'almost_junction', // - geometry issues where fixing them might solve connectivity issues
77883             'disconnected_way', 'impossible_oneway' // - finally connectivity issues
77884             ];
77885             var allIssues = validator.getIssues(options);
77886             var forEntityIDs = new Set(entityIDs);
77887             return allIssues.filter(function (issue) {
77888               return (issue.entityIds || []).some(function (entityID) {
77889                 return forEntityIDs.has(entityID);
77890               });
77891             }).sort(function (issue1, issue2) {
77892               if (issue1.type === issue2.type) {
77893                 // issues of the same type, sort deterministically
77894                 return issue1.id < issue2.id ? -1 : 1;
77895               }
77896
77897               var index1 = orderedIssueTypes.indexOf(issue1.type);
77898               var index2 = orderedIssueTypes.indexOf(issue2.type);
77899
77900               if (index1 !== -1 && index2 !== -1) {
77901                 // both issue types have explicit sort orders
77902                 return index1 - index2;
77903               } else if (index1 === -1 && index2 === -1) {
77904                 // neither issue type has an explicit sort order, sort by type
77905                 return issue1.type < issue2.type ? -1 : 1;
77906               } else {
77907                 // order explicit types before everything else
77908                 return index1 !== -1 ? -1 : 1;
77909               }
77910             });
77911           }; // `getEntityIssues()`
77912           // Get an array of detected issues for the given entityID.
77913           // (This just calls getSharedEntityIssues for a single entity)
77914           //
77915           // Arguments
77916           //   `entityID` - the entity ID to get the issues for
77917           //   `options` - (see `getIssues`)
77918           // Returns
77919           //   An Array containing the issues
77920           //
77921
77922
77923           validator.getEntityIssues = function (entityID, options) {
77924             return validator.getSharedEntityIssues([entityID], options);
77925           }; // `getRuleKeys()`
77926           //
77927           // Returns
77928           //   An Array containing the rule keys
77929           //
77930
77931
77932           validator.getRuleKeys = function () {
77933             return Object.keys(_rules);
77934           }; // `isRuleEnabled()`
77935           //
77936           // Arguments
77937           //   `key` - the rule to check (e.g. 'crossing_ways')
77938           // Returns
77939           //   `true`/`false`
77940           //
77941
77942
77943           validator.isRuleEnabled = function (key) {
77944             return !_disabledRules[key];
77945           }; // `toggleRule()`
77946           // Toggles a single validation rule,
77947           // then reruns the validation so that the user sees something happen in the UI
77948           //
77949           // Arguments
77950           //   `key` - the rule to toggle (e.g. 'crossing_ways')
77951           //
77952
77953
77954           validator.toggleRule = function (key) {
77955             if (_disabledRules[key]) {
77956               delete _disabledRules[key];
77957             } else {
77958               _disabledRules[key] = true;
77959             }
77960
77961             corePreferences('validate-disabledRules', Object.keys(_disabledRules).join(','));
77962             validator.validate();
77963           }; // `disableRules()`
77964           // Disables given validation rules,
77965           // then reruns the validation so that the user sees something happen in the UI
77966           //
77967           // Arguments
77968           //   `keys` - Array or Set containing rule keys to disable
77969           //
77970
77971
77972           validator.disableRules = function (keys) {
77973             _disabledRules = {};
77974             keys.forEach(function (k) {
77975               return _disabledRules[k] = true;
77976             });
77977             corePreferences('validate-disabledRules', Object.keys(_disabledRules).join(','));
77978             validator.validate();
77979           }; // `ignoreIssue()`
77980           // Don't show the given issue in lists
77981           //
77982           // Arguments
77983           //   `issueID` - the issueID
77984           //
77985
77986
77987           validator.ignoreIssue = function (issueID) {
77988             _ignoredIssueIDs.add(issueID);
77989           }; // `validate()`
77990           // Validates anything that has changed in the head graph since the last time it was run.
77991           // (head graph contains user's edits)
77992           //
77993           // Returns
77994           //   A Promise fulfilled when the validation has completed and then dispatches a `validated` event.
77995           //   This may take time but happen in the background during browser idle time.
77996           //
77997
77998
77999           validator.validate = function () {
78000             // Make sure the caches have graphs assigned to them.
78001             // (we don't do this in `reset` because context is still resetting things and `history.base()` is unstable then)
78002             var baseGraph = context.history().base();
78003             if (!_headCache.graph) _headCache.graph = baseGraph;
78004             if (!_baseCache.graph) _baseCache.graph = baseGraph;
78005             var prevGraph = _headCache.graph;
78006             var currGraph = context.graph();
78007
78008             if (currGraph === prevGraph) {
78009               // _headCache.graph is current - we are caught up
78010               _headIsCurrent = true;
78011               dispatch.call('validated');
78012               return Promise.resolve();
78013             }
78014
78015             if (_headPromise) {
78016               // Validation already in process, but we aren't caught up to current
78017               _headIsCurrent = false; // We will need to catch up after the validation promise fulfills
78018
78019               return _headPromise;
78020             } // If we get here, its time to start validating stuff.
78021
78022
78023             _headCache.graph = currGraph; // take snapshot
78024
78025             _completeDiff = context.history().difference().complete();
78026             var incrementalDiff = coreDifference(prevGraph, currGraph);
78027             var entityIDs = Object.keys(incrementalDiff.complete());
78028             entityIDs = _headCache.withAllRelatedEntities(entityIDs); // expand set
78029
78030             if (!entityIDs.size) {
78031               dispatch.call('validated');
78032               return Promise.resolve();
78033             }
78034
78035             _headPromise = validateEntitiesAsync(entityIDs, _headCache).then(function () {
78036               return updateResolvedIssues(entityIDs);
78037             }).then(function () {
78038               return dispatch.call('validated');
78039             })["catch"](function () {
78040               /* ignore */
78041             }).then(function () {
78042               _headPromise = null;
78043
78044               if (!_headIsCurrent) {
78045                 validator.validate(); // run it again to catch up to current graph
78046               }
78047             });
78048             return _headPromise;
78049           }; // register event handlers:
78050           // WHEN TO RUN VALIDATION:
78051           // When history changes:
78052
78053
78054           context.history().on('restore.validator', validator.validate) // on restore saved history
78055           .on('undone.validator', validator.validate) // on undo
78056           .on('redone.validator', validator.validate) // on redo
78057           .on('reset.validator', function () {
78058             // on history reset - happens after save, or enter/exit walkthrough
78059             reset(false); // cached issues aren't valid any longer if the history has been reset
78060
78061             validator.validate();
78062           }); // but not on 'change' (e.g. while drawing)
78063           // When user changes editing modes (to catch recent changes e.g. drawing)
78064
78065           context.on('exit.validator', validator.validate); // When merging fetched data, validate base graph:
78066
78067           context.history().on('merge.validator', function (entities) {
78068             if (!entities) return; // Make sure the caches have graphs assigned to them.
78069             // (we don't do this in `reset` because context is still resetting things and `history.base()` is unstable then)
78070
78071             var baseGraph = context.history().base();
78072             if (!_headCache.graph) _headCache.graph = baseGraph;
78073             if (!_baseCache.graph) _baseCache.graph = baseGraph;
78074             var entityIDs = entities.map(function (entity) {
78075               return entity.id;
78076             });
78077             entityIDs = _baseCache.withAllRelatedEntities(entityIDs); // expand set
78078
78079             validateEntitiesAsync(entityIDs, _baseCache);
78080           }); // `validateEntity()`   (private)
78081           // Runs all validation rules on a single entity.
78082           // Some things to note:
78083           //  - Graph is passed in from whenever the validation was started.  Validators shouldn't use
78084           //   `context.graph()` because this all happens async, and the graph might have changed
78085           //   (for example, nodes getting deleted before the validation can run)
78086           //  - Validator functions may still be waiting on something and return a "provisional" result.
78087           //    In this situation, we will schedule to revalidate the entity sometime later.
78088           //
78089           // Arguments
78090           //   `entity` - The entity
78091           //   `graph` - graph containing the entity
78092           //
78093           // Returns
78094           //   Object result like:
78095           //   {
78096           //     issues:       Array of detected issues
78097           //     provisional:  `true` if provisional result, `false` if final result
78098           //   }
78099           //
78100
78101           function validateEntity(entity, graph) {
78102             var result = {
78103               issues: [],
78104               provisional: false
78105             };
78106             Object.keys(_rules).forEach(runValidation); // run all rules
78107
78108             return result; // runs validation and appends resulting issues
78109
78110             function runValidation(key) {
78111               var fn = _rules[key];
78112
78113               if (typeof fn !== 'function') {
78114                 console.error('no such validation rule = ' + key); // eslint-disable-line no-console
78115
78116                 return;
78117               }
78118
78119               var detected = fn(entity, graph);
78120
78121               if (detected.provisional) {
78122                 // this validation should be run again later
78123                 result.provisional = true;
78124               }
78125
78126               detected = detected.filter(applySeverityOverrides);
78127               result.issues = result.issues.concat(detected); // If there are any override rules that match the issue type/subtype,
78128               // adjust severity (or disable it) and keep/discard as quickly as possible.
78129
78130               function applySeverityOverrides(issue) {
78131                 var type = issue.type;
78132                 var subtype = issue.subtype || '';
78133                 var i;
78134
78135                 for (i = 0; i < _errorOverrides.length; i++) {
78136                   if (_errorOverrides[i].type.test(type) && _errorOverrides[i].subtype.test(subtype)) {
78137                     issue.severity = 'error';
78138                     return true;
78139                   }
78140                 }
78141
78142                 for (i = 0; i < _warningOverrides.length; i++) {
78143                   if (_warningOverrides[i].type.test(type) && _warningOverrides[i].subtype.test(subtype)) {
78144                     issue.severity = 'warning';
78145                     return true;
78146                   }
78147                 }
78148
78149                 for (i = 0; i < _disableOverrides.length; i++) {
78150                   if (_disableOverrides[i].type.test(type) && _disableOverrides[i].subtype.test(subtype)) {
78151                     return false;
78152                   }
78153                 }
78154
78155                 return true;
78156               }
78157             }
78158           } // `updateResolvedIssues()`   (private)
78159           // Determine if any issues were resolved for the given entities.
78160           // This is called by `validate()` after validation of the head graph
78161           //
78162           // Give the user credit for fixing an issue if:
78163           // - the issue is in the base cache
78164           // - the issue is not in the head cache
78165           // - the user did something to one of the entities involved in the issue
78166           //
78167           // Arguments
78168           //   `entityIDs` - Array or Set containing entity IDs.
78169           //
78170
78171
78172           function updateResolvedIssues(entityIDs) {
78173             entityIDs.forEach(function (entityID) {
78174               var baseIssues = _baseCache.issuesByEntityID[entityID];
78175               if (!baseIssues) return;
78176               baseIssues.forEach(function (issueID) {
78177                 // Check if the user did something to one of the entities involved in this issue.
78178                 // (This issue could involve multiple entities, e.g. disconnected routable features)
78179                 var issue = _baseCache.issuesByIssueID[issueID];
78180                 var userModified = (issue.entityIds || []).some(function (id) {
78181                   return _completeDiff.hasOwnProperty(id);
78182                 });
78183
78184                 if (userModified && !_headCache.issuesByIssueID[issueID]) {
78185                   // issue seems fixed
78186                   _resolvedIssueIDs.add(issueID);
78187                 } else {
78188                   // issue still not resolved
78189                   _resolvedIssueIDs["delete"](issueID); // (did undo, or possibly fixed and then re-caused the issue)
78190
78191                 }
78192               });
78193             });
78194           } // `validateEntitiesAsync()`   (private)
78195           // Schedule validation for many entities.
78196           //
78197           // Arguments
78198           //   `entityIDs` - Array or Set containing entityIDs.
78199           //   `graph` - the graph to validate that contains those entities
78200           //   `cache` - the cache to store results in (_headCache or _baseCache)
78201           //
78202           // Returns
78203           //   A Promise fulfilled when the validation has completed.
78204           //   This may take time but happen in the background during browser idle time.
78205           //
78206
78207
78208           function validateEntitiesAsync(entityIDs, cache) {
78209             // Enqueue the work
78210             var jobs = Array.from(entityIDs).map(function (entityID) {
78211               if (cache.queuedEntityIDs.has(entityID)) return null; // queued already
78212
78213               cache.queuedEntityIDs.add(entityID); // Clear caches for existing issues related to this entity
78214
78215               cache.uncacheEntityID(entityID);
78216               return function () {
78217                 cache.queuedEntityIDs["delete"](entityID);
78218                 var graph = cache.graph;
78219                 if (!graph) return; // was reset?
78220
78221                 var entity = graph.hasEntity(entityID); // Sanity check: don't validate deleted entities
78222
78223                 if (!entity) return; // detect new issues and update caches
78224
78225                 var result = validateEntity(entity, graph);
78226
78227                 if (result.provisional) {
78228                   // provisional result
78229                   cache.provisionalEntityIDs.add(entityID); // we'll need to revalidate this entity again later
78230                 }
78231
78232                 cache.cacheIssues(result.issues); // update cache
78233               };
78234             }).filter(Boolean); // Perform the work in chunks.
78235             // Because this will happen during idle callbacks, we want to choose a chunk size
78236             // that won't make the browser stutter too badly.
78237
78238             cache.queue = cache.queue.concat(utilArrayChunk(jobs, 100)); // Perform the work
78239
78240             if (cache.queuePromise) return cache.queuePromise;
78241             cache.queuePromise = processQueue(cache).then(function () {
78242               return revalidateProvisionalEntities(cache);
78243             })["catch"](function () {
78244               /* ignore */
78245             })["finally"](function () {
78246               return cache.queuePromise = null;
78247             });
78248             return cache.queuePromise;
78249           } // `revalidateProvisionalEntities()`   (private)
78250           // Sometimes a validator will return a "provisional" result.
78251           // In this situation, we'll need to revalidate the entity later.
78252           // This function waits a delay, then places them back into the validation queue.
78253           //
78254           // Arguments
78255           //   `cache` - The cache (_headCache or _baseCache)
78256           //
78257
78258
78259           function revalidateProvisionalEntities(cache) {
78260             if (!cache.provisionalEntityIDs.size) return; // nothing to do
78261
78262             var handle = window.setTimeout(function () {
78263               _deferredST["delete"](handle);
78264
78265               if (!cache.provisionalEntityIDs.size) return; // nothing to do
78266
78267               validateEntitiesAsync(Array.from(cache.provisionalEntityIDs), cache);
78268             }, RETRY);
78269
78270             _deferredST.add(handle);
78271           } // `processQueue(queue)`   (private)
78272           // Process the next chunk of deferred validation work
78273           //
78274           // Arguments
78275           //   `cache` - The cache (_headCache or _baseCache)
78276           //
78277           // Returns
78278           //   A Promise fulfilled when the validation has completed.
78279           //   This may take time but happen in the background during browser idle time.
78280           //
78281
78282
78283           function processQueue(cache) {
78284             // console.log(`${cache.which} queue length ${cache.queue.length}`);
78285             if (!cache.queue.length) return Promise.resolve(); // we're done
78286
78287             var chunk = cache.queue.pop();
78288             return new Promise(function (resolvePromise) {
78289               var handle = window.requestIdleCallback(function () {
78290                 _deferredRIC["delete"](handle); // const t0 = performance.now();
78291
78292
78293                 chunk.forEach(function (job) {
78294                   return job();
78295                 }); // const t1 = performance.now();
78296                 // console.log('chunk processed in ' + (t1 - t0) + ' ms');
78297
78298                 resolvePromise();
78299               });
78300
78301               _deferredRIC.add(handle);
78302             }).then(function () {
78303               // dispatch an event sometimes to redraw various UI things
78304               if (cache.queue.length % 25 === 0) dispatch.call('validated');
78305             }).then(function () {
78306               return processQueue(cache);
78307             });
78308           }
78309
78310           return validator;
78311         } // `validationCache()`   (private)
78312         // Creates a cache to store validation state
78313         // We create 2 of these:
78314         //   `_baseCache` for validation on the base graph (unedited)
78315         //   `_headCache` for validation on the head graph (user edits applied)
78316         //
78317         // Arguments
78318         //   `which` - just a String 'base' or 'head' to keep track of it
78319         //
78320
78321         function validationCache(which) {
78322           var cache = {
78323             which: which,
78324             graph: null,
78325             queue: [],
78326             queuePromise: null,
78327             queuedEntityIDs: new Set(),
78328             provisionalEntityIDs: new Set(),
78329             issuesByIssueID: {},
78330             // issue.id -> issue
78331             issuesByEntityID: {} // entity.id -> Set(issue.id)
78332
78333           };
78334
78335           cache.cacheIssue = function (issue) {
78336             (issue.entityIds || []).forEach(function (entityID) {
78337               if (!cache.issuesByEntityID[entityID]) {
78338                 cache.issuesByEntityID[entityID] = new Set();
78339               }
78340
78341               cache.issuesByEntityID[entityID].add(issue.id);
78342             });
78343             cache.issuesByIssueID[issue.id] = issue;
78344           };
78345
78346           cache.uncacheIssue = function (issue) {
78347             (issue.entityIds || []).forEach(function (entityID) {
78348               if (cache.issuesByEntityID[entityID]) {
78349                 cache.issuesByEntityID[entityID]["delete"](issue.id);
78350               }
78351             });
78352             delete cache.issuesByIssueID[issue.id];
78353           };
78354
78355           cache.cacheIssues = function (issues) {
78356             issues.forEach(cache.cacheIssue);
78357           };
78358
78359           cache.uncacheIssues = function (issues) {
78360             issues.forEach(cache.uncacheIssue);
78361           };
78362
78363           cache.uncacheIssuesOfType = function (type) {
78364             var issuesOfType = Object.values(cache.issuesByIssueID).filter(function (issue) {
78365               return issue.type === type;
78366             });
78367             cache.uncacheIssues(issuesOfType);
78368           }; // Remove a single entity and all its related issues from the caches
78369
78370
78371           cache.uncacheEntityID = function (entityID) {
78372             var entityIssueIDs = cache.issuesByEntityID[entityID];
78373
78374             if (entityIssueIDs) {
78375               entityIssueIDs.forEach(function (issueID) {
78376                 var issue = cache.issuesByIssueID[issueID];
78377
78378                 if (issue) {
78379                   cache.uncacheIssue(issue);
78380                 } else {
78381                   // shouldn't happen, clean up
78382                   delete cache.issuesByIssueID[issueID];
78383                 }
78384               });
78385             }
78386
78387             delete cache.issuesByEntityID[entityID];
78388             cache.provisionalEntityIDs["delete"](entityID);
78389           }; // Return the expandeded set of entityIDs related to issues for the given entityIDs
78390           //
78391           // Arguments
78392           //   `entityIDs` - Array or Set containing entityIDs.
78393           //
78394
78395
78396           cache.withAllRelatedEntities = function (entityIDs) {
78397             var result = new Set();
78398             (entityIDs || []).forEach(function (entityID) {
78399               result.add(entityID); // include self
78400
78401               var entityIssueIDs = cache.issuesByEntityID[entityID];
78402
78403               if (entityIssueIDs) {
78404                 entityIssueIDs.forEach(function (issueID) {
78405                   var issue = cache.issuesByIssueID[issueID];
78406
78407                   if (issue) {
78408                     (issue.entityIds || []).forEach(function (relatedID) {
78409                       return result.add(relatedID);
78410                     });
78411                   } else {
78412                     // shouldn't happen, clean up
78413                     delete cache.issuesByIssueID[issueID];
78414                   }
78415                 });
78416               }
78417             });
78418             return result;
78419           };
78420
78421           return cache;
78422         }
78423
78424         function coreUploader(context) {
78425           var dispatch = dispatch$8( // Start and end events are dispatched exactly once each per legitimate outside call to `save`
78426           'saveStarted', // dispatched as soon as a call to `save` has been deemed legitimate
78427           'saveEnded', // dispatched after the result event has been dispatched
78428           'willAttemptUpload', // dispatched before the actual upload call occurs, if it will
78429           'progressChanged', // Each save results in one of these outcomes:
78430           'resultNoChanges', // upload wasn't attempted since there were no edits
78431           'resultErrors', // upload failed due to errors
78432           'resultConflicts', // upload failed due to data conflicts
78433           'resultSuccess' // upload completed without errors
78434           );
78435           var _isSaving = false;
78436           var _conflicts = [];
78437           var _errors = [];
78438
78439           var _origChanges;
78440
78441           var _discardTags = {};
78442           _mainFileFetcher.get('discarded').then(function (d) {
78443             _discardTags = d;
78444           })["catch"](function () {
78445             /* ignore */
78446           });
78447           var uploader = utilRebind({}, dispatch, 'on');
78448
78449           uploader.isSaving = function () {
78450             return _isSaving;
78451           };
78452
78453           uploader.save = function (changeset, tryAgain, checkConflicts) {
78454             // Guard against accidentally entering save code twice - #4641
78455             if (_isSaving && !tryAgain) {
78456               return;
78457             }
78458
78459             var osm = context.connection();
78460             if (!osm) return; // If user somehow got logged out mid-save, try to reauthenticate..
78461             // This can happen if they were logged in from before, but the tokens are no longer valid.
78462
78463             if (!osm.authenticated()) {
78464               osm.authenticate(function (err) {
78465                 if (!err) {
78466                   uploader.save(changeset, tryAgain, checkConflicts); // continue where we left off..
78467                 }
78468               });
78469               return;
78470             }
78471
78472             if (!_isSaving) {
78473               _isSaving = true;
78474               dispatch.call('saveStarted', this);
78475             }
78476
78477             var history = context.history();
78478             _conflicts = [];
78479             _errors = []; // Store original changes, in case user wants to download them as an .osc file
78480
78481             _origChanges = history.changes(actionDiscardTags(history.difference(), _discardTags)); // First time, `history.perform` a no-op action.
78482             // Any conflict resolutions will be done as `history.replace`
78483             // Remember to pop this later if needed
78484
78485             if (!tryAgain) {
78486               history.perform(actionNoop());
78487             } // Attempt a fast upload.. If there are conflicts, re-enter with `checkConflicts = true`
78488
78489
78490             if (!checkConflicts) {
78491               upload(changeset); // Do the full (slow) conflict check..
78492             } else {
78493               performFullConflictCheck(changeset);
78494             }
78495           };
78496
78497           function performFullConflictCheck(changeset) {
78498             var osm = context.connection();
78499             if (!osm) return;
78500             var history = context.history();
78501             var localGraph = context.graph();
78502             var remoteGraph = coreGraph(history.base(), true);
78503             var summary = history.difference().summary();
78504             var _toCheck = [];
78505
78506             for (var i = 0; i < summary.length; i++) {
78507               var item = summary[i];
78508
78509               if (item.changeType === 'modified') {
78510                 _toCheck.push(item.entity.id);
78511               }
78512             }
78513
78514             var _toLoad = withChildNodes(_toCheck, localGraph);
78515
78516             var _loaded = {};
78517             var _toLoadCount = 0;
78518             var _toLoadTotal = _toLoad.length;
78519
78520             if (_toCheck.length) {
78521               dispatch.call('progressChanged', this, _toLoadCount, _toLoadTotal);
78522
78523               _toLoad.forEach(function (id) {
78524                 _loaded[id] = false;
78525               });
78526
78527               osm.loadMultiple(_toLoad, loaded);
78528             } else {
78529               upload(changeset);
78530             }
78531
78532             return;
78533
78534             function withChildNodes(ids, graph) {
78535               var s = new Set(ids);
78536               ids.forEach(function (id) {
78537                 var entity = graph.entity(id);
78538                 if (entity.type !== 'way') return;
78539                 graph.childNodes(entity).forEach(function (child) {
78540                   if (child.version !== undefined) {
78541                     s.add(child.id);
78542                   }
78543                 });
78544               });
78545               return Array.from(s);
78546             } // Reload modified entities into an alternate graph and check for conflicts..
78547
78548
78549             function loaded(err, result) {
78550               if (_errors.length) return;
78551
78552               if (err) {
78553                 _errors.push({
78554                   msg: err.message || err.responseText,
78555                   details: [_t('save.status_code', {
78556                     code: err.status
78557                   })]
78558                 });
78559
78560                 didResultInErrors();
78561               } else {
78562                 var loadMore = [];
78563                 result.data.forEach(function (entity) {
78564                   remoteGraph.replace(entity);
78565                   _loaded[entity.id] = true;
78566                   _toLoad = _toLoad.filter(function (val) {
78567                     return val !== entity.id;
78568                   });
78569                   if (!entity.visible) return; // Because loadMultiple doesn't download /full like loadEntity,
78570                   // need to also load children that aren't already being checked..
78571
78572                   var i, id;
78573
78574                   if (entity.type === 'way') {
78575                     for (i = 0; i < entity.nodes.length; i++) {
78576                       id = entity.nodes[i];
78577
78578                       if (_loaded[id] === undefined) {
78579                         _loaded[id] = false;
78580                         loadMore.push(id);
78581                       }
78582                     }
78583                   } else if (entity.type === 'relation' && entity.isMultipolygon()) {
78584                     for (i = 0; i < entity.members.length; i++) {
78585                       id = entity.members[i].id;
78586
78587                       if (_loaded[id] === undefined) {
78588                         _loaded[id] = false;
78589                         loadMore.push(id);
78590                       }
78591                     }
78592                   }
78593                 });
78594                 _toLoadCount += result.data.length;
78595                 _toLoadTotal += loadMore.length;
78596                 dispatch.call('progressChanged', this, _toLoadCount, _toLoadTotal);
78597
78598                 if (loadMore.length) {
78599                   _toLoad.push.apply(_toLoad, loadMore);
78600
78601                   osm.loadMultiple(loadMore, loaded);
78602                 }
78603
78604                 if (!_toLoad.length) {
78605                   detectConflicts();
78606                   upload(changeset);
78607                 }
78608               }
78609             }
78610
78611             function detectConflicts() {
78612               function choice(id, text, _action) {
78613                 return {
78614                   id: id,
78615                   text: text,
78616                   action: function action() {
78617                     history.replace(_action);
78618                   }
78619                 };
78620               }
78621
78622               function formatUser(d) {
78623                 return '<a href="' + osm.userURL(d) + '" target="_blank">' + escape$4(d) + '</a>';
78624               }
78625
78626               function entityName(entity) {
78627                 return utilDisplayName(entity) || utilDisplayType(entity.id) + ' ' + entity.id;
78628               }
78629
78630               function sameVersions(local, remote) {
78631                 if (local.version !== remote.version) return false;
78632
78633                 if (local.type === 'way') {
78634                   var children = utilArrayUnion(local.nodes, remote.nodes);
78635
78636                   for (var i = 0; i < children.length; i++) {
78637                     var a = localGraph.hasEntity(children[i]);
78638                     var b = remoteGraph.hasEntity(children[i]);
78639                     if (a && b && a.version !== b.version) return false;
78640                   }
78641                 }
78642
78643                 return true;
78644               }
78645
78646               _toCheck.forEach(function (id) {
78647                 var local = localGraph.entity(id);
78648                 var remote = remoteGraph.entity(id);
78649                 if (sameVersions(local, remote)) return;
78650                 var merge = actionMergeRemoteChanges(id, localGraph, remoteGraph, _discardTags, formatUser);
78651                 history.replace(merge);
78652                 var mergeConflicts = merge.conflicts();
78653                 if (!mergeConflicts.length) return; // merged safely
78654
78655                 var forceLocal = actionMergeRemoteChanges(id, localGraph, remoteGraph, _discardTags).withOption('force_local');
78656                 var forceRemote = actionMergeRemoteChanges(id, localGraph, remoteGraph, _discardTags).withOption('force_remote');
78657                 var keepMine = _t('save.conflict.' + (remote.visible ? 'keep_local' : 'restore'));
78658                 var keepTheirs = _t('save.conflict.' + (remote.visible ? 'keep_remote' : 'delete'));
78659
78660                 _conflicts.push({
78661                   id: id,
78662                   name: entityName(local),
78663                   details: mergeConflicts,
78664                   chosen: 1,
78665                   choices: [choice(id, keepMine, forceLocal), choice(id, keepTheirs, forceRemote)]
78666                 });
78667               });
78668             }
78669           }
78670
78671           function upload(changeset) {
78672             var osm = context.connection();
78673
78674             if (!osm) {
78675               _errors.push({
78676                 msg: 'No OSM Service'
78677               });
78678             }
78679
78680             if (_conflicts.length) {
78681               didResultInConflicts(changeset);
78682             } else if (_errors.length) {
78683               didResultInErrors();
78684             } else {
78685               var history = context.history();
78686               var changes = history.changes(actionDiscardTags(history.difference(), _discardTags));
78687
78688               if (changes.modified.length || changes.created.length || changes.deleted.length) {
78689                 dispatch.call('willAttemptUpload', this);
78690                 osm.putChangeset(changeset, changes, uploadCallback);
78691               } else {
78692                 // changes were insignificant or reverted by user
78693                 didResultInNoChanges();
78694               }
78695             }
78696           }
78697
78698           function uploadCallback(err, changeset) {
78699             if (err) {
78700               if (err.status === 409) {
78701                 // 409 Conflict
78702                 uploader.save(changeset, true, true); // tryAgain = true, checkConflicts = true
78703               } else {
78704                 _errors.push({
78705                   msg: err.message || err.responseText,
78706                   details: [_t('save.status_code', {
78707                     code: err.status
78708                   })]
78709                 });
78710
78711                 didResultInErrors();
78712               }
78713             } else {
78714               didResultInSuccess(changeset);
78715             }
78716           }
78717
78718           function didResultInNoChanges() {
78719             dispatch.call('resultNoChanges', this);
78720             endSave();
78721             context.flush(); // reset iD
78722           }
78723
78724           function didResultInErrors() {
78725             context.history().pop();
78726             dispatch.call('resultErrors', this, _errors);
78727             endSave();
78728           }
78729
78730           function didResultInConflicts(changeset) {
78731             _conflicts.sort(function (a, b) {
78732               return b.id.localeCompare(a.id);
78733             });
78734
78735             dispatch.call('resultConflicts', this, changeset, _conflicts, _origChanges);
78736             endSave();
78737           }
78738
78739           function didResultInSuccess(changeset) {
78740             // delete the edit stack cached to local storage
78741             context.history().clearSaved();
78742             dispatch.call('resultSuccess', this, changeset); // Add delay to allow for postgres replication #1646 #2678
78743
78744             window.setTimeout(function () {
78745               endSave();
78746               context.flush(); // reset iD
78747             }, 2500);
78748           }
78749
78750           function endSave() {
78751             _isSaving = false;
78752             dispatch.call('saveEnded', this);
78753           }
78754
78755           uploader.cancelConflictResolution = function () {
78756             context.history().pop();
78757           };
78758
78759           uploader.processResolvedConflicts = function (changeset) {
78760             var history = context.history();
78761
78762             for (var i = 0; i < _conflicts.length; i++) {
78763               if (_conflicts[i].chosen === 1) {
78764                 // user chose "use theirs"
78765                 var entity = context.hasEntity(_conflicts[i].id);
78766
78767                 if (entity && entity.type === 'way') {
78768                   var children = utilArrayUniq(entity.nodes);
78769
78770                   for (var j = 0; j < children.length; j++) {
78771                     history.replace(actionRevert(children[j]));
78772                   }
78773                 }
78774
78775                 history.replace(actionRevert(_conflicts[i].id));
78776               }
78777             }
78778
78779             uploader.save(changeset, true, false); // tryAgain = true, checkConflicts = false
78780           };
78781
78782           uploader.reset = function () {};
78783
78784           return uploader;
78785         }
78786
78787         var $$2 = _export;
78788         var fails = fails$S;
78789         var expm1 = mathExpm1;
78790
78791         var abs = Math.abs;
78792         var exp = Math.exp;
78793         var E = Math.E;
78794
78795         var FORCED = fails(function () {
78796           // eslint-disable-next-line es/no-math-sinh -- required for testing
78797           return Math.sinh(-2e-17) != -2e-17;
78798         });
78799
78800         // `Math.sinh` method
78801         // https://tc39.es/ecma262/#sec-math.sinh
78802         // V8 near Chromium 38 has a problem with very small numbers
78803         $$2({ target: 'Math', stat: true, forced: FORCED }, {
78804           sinh: function sinh(x) {
78805             return abs(x = +x) < 1 ? (expm1(x) - expm1(-x)) / 2 : (exp(x - 1) - exp(-x - 1)) * (E / 2);
78806           }
78807         });
78808
78809         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
78810
78811         window.matchMedia("\n        (-webkit-min-device-pixel-ratio: 2), /* Safari */\n        (min-resolution: 2dppx),             /* standard */\n        (min-resolution: 192dpi)             /* fallback */\n    ").addListener(function () {
78812           isRetina = window.devicePixelRatio && window.devicePixelRatio >= 2;
78813         });
78814
78815         function localeDateString(s) {
78816           if (!s) return null;
78817           var options = {
78818             day: 'numeric',
78819             month: 'short',
78820             year: 'numeric'
78821           };
78822           var d = new Date(s);
78823           if (isNaN(d.getTime())) return null;
78824           return d.toLocaleDateString(_mainLocalizer.localeCode(), options);
78825         }
78826
78827         function vintageRange(vintage) {
78828           var s;
78829
78830           if (vintage.start || vintage.end) {
78831             s = vintage.start || '?';
78832
78833             if (vintage.start !== vintage.end) {
78834               s += ' - ' + (vintage.end || '?');
78835             }
78836           }
78837
78838           return s;
78839         }
78840
78841         function rendererBackgroundSource(data) {
78842           var source = Object.assign({}, data); // shallow copy
78843
78844           var _offset = [0, 0];
78845           var _name = source.name;
78846           var _description = source.description;
78847
78848           var _best = !!source.best;
78849
78850           var _template = source.encrypted ? utilAesDecrypt(source.template) : source.template;
78851
78852           source.tileSize = data.tileSize || 256;
78853           source.zoomExtent = data.zoomExtent || [0, 22];
78854           source.overzoom = data.overzoom !== false;
78855
78856           source.offset = function (val) {
78857             if (!arguments.length) return _offset;
78858             _offset = val;
78859             return source;
78860           };
78861
78862           source.nudge = function (val, zoomlevel) {
78863             _offset[0] += val[0] / Math.pow(2, zoomlevel);
78864             _offset[1] += val[1] / Math.pow(2, zoomlevel);
78865             return source;
78866           };
78867
78868           source.name = function () {
78869             var id_safe = source.id.replace(/\./g, '<TX_DOT>');
78870             return _t('imagery.' + id_safe + '.name', {
78871               "default": lodash.exports.escape(_name)
78872             });
78873           };
78874
78875           source.label = function () {
78876             var id_safe = source.id.replace(/\./g, '<TX_DOT>');
78877             return _t.html('imagery.' + id_safe + '.name', {
78878               "default": lodash.exports.escape(_name)
78879             });
78880           };
78881
78882           source.description = function () {
78883             var id_safe = source.id.replace(/\./g, '<TX_DOT>');
78884             return _t.html('imagery.' + id_safe + '.description', {
78885               "default": lodash.exports.escape(_description)
78886             });
78887           };
78888
78889           source.best = function () {
78890             return _best;
78891           };
78892
78893           source.area = function () {
78894             if (!data.polygon) return Number.MAX_VALUE; // worldwide
78895
78896             var area = d3_geoArea({
78897               type: 'MultiPolygon',
78898               coordinates: [data.polygon]
78899             });
78900             return isNaN(area) ? 0 : area;
78901           };
78902
78903           source.imageryUsed = function () {
78904             return _name || source.id;
78905           };
78906
78907           source.template = function (val) {
78908             if (!arguments.length) return _template;
78909
78910             if (source.id === 'custom' || source.id === 'Bing') {
78911               _template = val;
78912             }
78913
78914             return source;
78915           };
78916
78917           source.url = function (coord) {
78918             var result = _template;
78919             if (result === '') return result; // source 'none'
78920             // Guess a type based on the tokens present in the template
78921             // (This is for 'custom' source, where we don't know)
78922
78923             if (!source.type || source.id === 'custom') {
78924               if (/SERVICE=WMS|\{(proj|wkid|bbox)\}/.test(_template)) {
78925                 source.type = 'wms';
78926                 source.projection = 'EPSG:3857'; // guess
78927               } else if (/\{(x|y)\}/.test(_template)) {
78928                 source.type = 'tms';
78929               } else if (/\{u\}/.test(_template)) {
78930                 source.type = 'bing';
78931               }
78932             }
78933
78934             if (source.type === 'wms') {
78935               var tileToProjectedCoords = function tileToProjectedCoords(x, y, z) {
78936                 //polyfill for IE11, PhantomJS
78937                 var sinh = Math.sinh || function (x) {
78938                   var y = Math.exp(x);
78939                   return (y - 1 / y) / 2;
78940                 };
78941
78942                 var zoomSize = Math.pow(2, z);
78943                 var lon = x / zoomSize * Math.PI * 2 - Math.PI;
78944                 var lat = Math.atan(sinh(Math.PI * (1 - 2 * y / zoomSize)));
78945
78946                 switch (source.projection) {
78947                   case 'EPSG:4326':
78948                     return {
78949                       x: lon * 180 / Math.PI,
78950                       y: lat * 180 / Math.PI
78951                     };
78952
78953                   default:
78954                     // EPSG:3857 and synonyms
78955                     var mercCoords = mercatorRaw(lon, lat);
78956                     return {
78957                       x: 20037508.34 / Math.PI * mercCoords[0],
78958                       y: 20037508.34 / Math.PI * mercCoords[1]
78959                     };
78960                 }
78961               };
78962
78963               var tileSize = source.tileSize;
78964               var projection = source.projection;
78965               var minXmaxY = tileToProjectedCoords(coord[0], coord[1], coord[2]);
78966               var maxXminY = tileToProjectedCoords(coord[0] + 1, coord[1] + 1, coord[2]);
78967               result = result.replace(/\{(\w+)\}/g, function (token, key) {
78968                 switch (key) {
78969                   case 'width':
78970                   case 'height':
78971                     return tileSize;
78972
78973                   case 'proj':
78974                     return projection;
78975
78976                   case 'wkid':
78977                     return projection.replace(/^EPSG:/, '');
78978
78979                   case 'bbox':
78980                     // WMS 1.3 flips x/y for some coordinate systems including EPSG:4326 - #7557
78981                     if (projection === 'EPSG:4326' && // The CRS parameter implies version 1.3 (prior versions use SRS)
78982                     /VERSION=1.3|CRS={proj}/.test(source.template().toUpperCase())) {
78983                       return maxXminY.y + ',' + minXmaxY.x + ',' + minXmaxY.y + ',' + maxXminY.x;
78984                     } else {
78985                       return minXmaxY.x + ',' + maxXminY.y + ',' + maxXminY.x + ',' + minXmaxY.y;
78986                     }
78987
78988                   case 'w':
78989                     return minXmaxY.x;
78990
78991                   case 's':
78992                     return maxXminY.y;
78993
78994                   case 'n':
78995                     return maxXminY.x;
78996
78997                   case 'e':
78998                     return minXmaxY.y;
78999
79000                   default:
79001                     return token;
79002                 }
79003               });
79004             } else if (source.type === 'tms') {
79005               result = result.replace('{x}', coord[0]).replace('{y}', coord[1]) // TMS-flipped y coordinate
79006               .replace(/\{[t-]y\}/, Math.pow(2, coord[2]) - coord[1] - 1).replace(/\{z(oom)?\}/, coord[2]) // only fetch retina tiles for retina screens
79007               .replace(/\{@2x\}|\{r\}/, isRetina ? '@2x' : '');
79008             } else if (source.type === 'bing') {
79009               result = result.replace('{u}', function () {
79010                 var u = '';
79011
79012                 for (var zoom = coord[2]; zoom > 0; zoom--) {
79013                   var b = 0;
79014                   var mask = 1 << zoom - 1;
79015                   if ((coord[0] & mask) !== 0) b++;
79016                   if ((coord[1] & mask) !== 0) b += 2;
79017                   u += b.toString();
79018                 }
79019
79020                 return u;
79021               });
79022             } // these apply to any type..
79023
79024
79025             result = result.replace(/\{switch:([^}]+)\}/, function (s, r) {
79026               var subdomains = r.split(',');
79027               return subdomains[(coord[0] + coord[1]) % subdomains.length];
79028             });
79029             return result;
79030           };
79031
79032           source.validZoom = function (z) {
79033             return source.zoomExtent[0] <= z && (source.overzoom || source.zoomExtent[1] > z);
79034           };
79035
79036           source.isLocatorOverlay = function () {
79037             return source.id === 'mapbox_locator_overlay';
79038           };
79039           /* hides a source from the list, but leaves it available for use */
79040
79041
79042           source.isHidden = function () {
79043             return source.id === 'DigitalGlobe-Premium-vintage' || source.id === 'DigitalGlobe-Standard-vintage';
79044           };
79045
79046           source.copyrightNotices = function () {};
79047
79048           source.getMetadata = function (center, tileCoord, callback) {
79049             var vintage = {
79050               start: localeDateString(source.startDate),
79051               end: localeDateString(source.endDate)
79052             };
79053             vintage.range = vintageRange(vintage);
79054             var metadata = {
79055               vintage: vintage
79056             };
79057             callback(null, metadata);
79058           };
79059
79060           return source;
79061         }
79062
79063         rendererBackgroundSource.Bing = function (data, dispatch) {
79064           // https://docs.microsoft.com/en-us/bingmaps/rest-services/imagery/get-imagery-metadata
79065           // https://docs.microsoft.com/en-us/bingmaps/rest-services/directly-accessing-the-bing-maps-tiles
79066           //fallback url template
79067           data.template = 'https://ecn.t{switch:0,1,2,3}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&n=z';
79068           var bing = rendererBackgroundSource(data); //var key = 'Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU'; // P2, JOSM, etc
79069
79070           var key = 'Ak5oTE46TUbjRp08OFVcGpkARErDobfpuyNKa-W2mQ8wbt1K1KL8p1bIRwWwcF-Q'; // iD
79071
79072           /*
79073           missing tile image strictness param (n=)
79074           •   n=f -> (Fail) returns a 404
79075           •   n=z -> (Empty) returns a 200 with 0 bytes (no content)
79076           •   n=t -> (Transparent) returns a 200 with a transparent (png) tile
79077           */
79078
79079           var strictParam = 'n';
79080           var url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial?include=ImageryProviders&uriScheme=https&key=' + key;
79081           var cache = {};
79082           var inflight = {};
79083           var providers = [];
79084           d3_json(url).then(function (json) {
79085             var imageryResource = json.resourceSets[0].resources[0]; //retrieve and prepare up to date imagery template
79086
79087             var template = imageryResource.imageUrl; //https://ecn.{subdomain}.tiles.virtualearth.net/tiles/a{quadkey}.jpeg?g=10339
79088
79089             var subDomains = imageryResource.imageUrlSubdomains; //["t0, t1, t2, t3"]
79090
79091             var subDomainNumbers = subDomains.map(function (subDomain) {
79092               return subDomain.substring(1);
79093             }).join(',');
79094             template = template.replace('{subdomain}', "t{switch:".concat(subDomainNumbers, "}")).replace('{quadkey}', '{u}');
79095
79096             if (!new URLSearchParams(template).has(strictParam)) {
79097               template += "&".concat(strictParam, "=z");
79098             }
79099
79100             bing.template(template);
79101             providers = imageryResource.imageryProviders.map(function (provider) {
79102               return {
79103                 attribution: provider.attribution,
79104                 areas: provider.coverageAreas.map(function (area) {
79105                   return {
79106                     zoom: [area.zoomMin, area.zoomMax],
79107                     extent: geoExtent([area.bbox[1], area.bbox[0]], [area.bbox[3], area.bbox[2]])
79108                   };
79109                 })
79110               };
79111             });
79112             dispatch.call('change');
79113           })["catch"](function () {
79114             /* ignore */
79115           });
79116
79117           bing.copyrightNotices = function (zoom, extent) {
79118             zoom = Math.min(zoom, 21);
79119             return providers.filter(function (provider) {
79120               return provider.areas.some(function (area) {
79121                 return extent.intersects(area.extent) && area.zoom[0] <= zoom && area.zoom[1] >= zoom;
79122               });
79123             }).map(function (provider) {
79124               return provider.attribution;
79125             }).join(', ');
79126           };
79127
79128           bing.getMetadata = function (center, tileCoord, callback) {
79129             var tileID = tileCoord.slice(0, 3).join('/');
79130             var zoom = Math.min(tileCoord[2], 21);
79131             var centerPoint = center[1] + ',' + center[0]; // lat,lng
79132
79133             var url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial/' + centerPoint + '?zl=' + zoom + '&key=' + key;
79134             if (inflight[tileID]) return;
79135
79136             if (!cache[tileID]) {
79137               cache[tileID] = {};
79138             }
79139
79140             if (cache[tileID] && cache[tileID].metadata) {
79141               return callback(null, cache[tileID].metadata);
79142             }
79143
79144             inflight[tileID] = true;
79145             d3_json(url).then(function (result) {
79146               delete inflight[tileID];
79147
79148               if (!result) {
79149                 throw new Error('Unknown Error');
79150               }
79151
79152               var vintage = {
79153                 start: localeDateString(result.resourceSets[0].resources[0].vintageStart),
79154                 end: localeDateString(result.resourceSets[0].resources[0].vintageEnd)
79155               };
79156               vintage.range = vintageRange(vintage);
79157               var metadata = {
79158                 vintage: vintage
79159               };
79160               cache[tileID].metadata = metadata;
79161               if (callback) callback(null, metadata);
79162             })["catch"](function (err) {
79163               delete inflight[tileID];
79164               if (callback) callback(err.message);
79165             });
79166           };
79167
79168           bing.terms_url = 'https://blog.openstreetmap.org/2010/11/30/microsoft-imagery-details';
79169           return bing;
79170         };
79171
79172         rendererBackgroundSource.Esri = function (data) {
79173           // in addition to using the tilemap at zoom level 20, overzoom real tiles - #4327 (deprecated technique, but it works)
79174           if (data.template.match(/blankTile/) === null) {
79175             data.template = data.template + '?blankTile=false';
79176           }
79177
79178           var esri = rendererBackgroundSource(data);
79179           var cache = {};
79180           var inflight = {};
79181
79182           var _prevCenter; // use a tilemap service to set maximum zoom for esri tiles dynamically
79183           // https://developers.arcgis.com/documentation/tiled-elevation-service/
79184
79185
79186           esri.fetchTilemap = function (center) {
79187             // skip if we have already fetched a tilemap within 5km
79188             if (_prevCenter && geoSphericalDistance(center, _prevCenter) < 5000) return;
79189             _prevCenter = center; // tiles are available globally to zoom level 19, afterward they may or may not be present
79190
79191             var z = 20; // first generate a random url using the template
79192
79193             var dummyUrl = esri.url([1, 2, 3]); // calculate url z/y/x from the lat/long of the center of the map
79194
79195             var x = Math.floor((center[0] + 180) / 360 * Math.pow(2, z));
79196             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
79197
79198             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
79199
79200             d3_json(tilemapUrl).then(function (tilemap) {
79201               if (!tilemap) {
79202                 throw new Error('Unknown Error');
79203               }
79204
79205               var hasTiles = true;
79206
79207               for (var i = 0; i < tilemap.data.length; i++) {
79208                 // 0 means an individual tile in the grid doesn't exist
79209                 if (!tilemap.data[i]) {
79210                   hasTiles = false;
79211                   break;
79212                 }
79213               } // if any tiles are missing at level 20 we restrict maxZoom to 19
79214
79215
79216               esri.zoomExtent[1] = hasTiles ? 22 : 19;
79217             })["catch"](function () {
79218               /* ignore */
79219             });
79220           };
79221
79222           esri.getMetadata = function (center, tileCoord, callback) {
79223             if (esri.id !== 'EsriWorldImagery') {
79224               // rest endpoint is not available for ESRI's "clarity" imagery
79225               return callback(null, {});
79226             }
79227
79228             var tileID = tileCoord.slice(0, 3).join('/');
79229             var zoom = Math.min(tileCoord[2], esri.zoomExtent[1]);
79230             var centerPoint = center[0] + ',' + center[1]; // long, lat (as it should be)
79231
79232             var unknown = _t('info_panels.background.unknown');
79233             var vintage = {};
79234             var metadata = {};
79235             if (inflight[tileID]) return; // build up query using the layer appropriate to the current zoom
79236
79237             var url = 'https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/4/query';
79238             url += '?returnGeometry=false&geometry=' + centerPoint + '&inSR=4326&geometryType=esriGeometryPoint&outFields=*&f=json';
79239
79240             if (!cache[tileID]) {
79241               cache[tileID] = {};
79242             }
79243
79244             if (cache[tileID] && cache[tileID].metadata) {
79245               return callback(null, cache[tileID].metadata);
79246             }
79247
79248             inflight[tileID] = true;
79249             d3_json(url).then(function (result) {
79250               delete inflight[tileID];
79251               result = result.features.map(function (f) {
79252                 return f.attributes;
79253               }).filter(function (a) {
79254                 return a.MinMapLevel <= zoom && a.MaxMapLevel >= zoom;
79255               })[0];
79256
79257               if (!result) {
79258                 throw new Error('Unknown Error');
79259               } else if (result.features && result.features.length < 1) {
79260                 throw new Error('No Results');
79261               } else if (result.error && result.error.message) {
79262                 throw new Error(result.error.message);
79263               } // pass through the discrete capture date from metadata
79264
79265
79266               var captureDate = localeDateString(result.SRC_DATE2);
79267               vintage = {
79268                 start: captureDate,
79269                 end: captureDate,
79270                 range: captureDate
79271               };
79272               metadata = {
79273                 vintage: vintage,
79274                 source: clean(result.NICE_NAME),
79275                 description: clean(result.NICE_DESC),
79276                 resolution: clean(+parseFloat(result.SRC_RES).toFixed(4)),
79277                 accuracy: clean(+parseFloat(result.SRC_ACC).toFixed(4))
79278               }; // append units - meters
79279
79280               if (isFinite(metadata.resolution)) {
79281                 metadata.resolution += ' m';
79282               }
79283
79284               if (isFinite(metadata.accuracy)) {
79285                 metadata.accuracy += ' m';
79286               }
79287
79288               cache[tileID].metadata = metadata;
79289               if (callback) callback(null, metadata);
79290             })["catch"](function (err) {
79291               delete inflight[tileID];
79292               if (callback) callback(err.message);
79293             });
79294
79295             function clean(val) {
79296               return String(val).trim() || unknown;
79297             }
79298           };
79299
79300           return esri;
79301         };
79302
79303         rendererBackgroundSource.None = function () {
79304           var source = rendererBackgroundSource({
79305             id: 'none',
79306             template: ''
79307           });
79308
79309           source.name = function () {
79310             return _t('background.none');
79311           };
79312
79313           source.label = function () {
79314             return _t.html('background.none');
79315           };
79316
79317           source.imageryUsed = function () {
79318             return null;
79319           };
79320
79321           source.area = function () {
79322             return -1; // sources in background pane are sorted by area
79323           };
79324
79325           return source;
79326         };
79327
79328         rendererBackgroundSource.Custom = function (template) {
79329           var source = rendererBackgroundSource({
79330             id: 'custom',
79331             template: template
79332           });
79333
79334           source.name = function () {
79335             return _t('background.custom');
79336           };
79337
79338           source.label = function () {
79339             return _t.html('background.custom');
79340           };
79341
79342           source.imageryUsed = function () {
79343             // sanitize personal connection tokens - #6801
79344             var cleaned = source.template(); // from query string parameters
79345
79346             if (cleaned.indexOf('?') !== -1) {
79347               var parts = cleaned.split('?', 2);
79348               var qs = utilStringQs(parts[1]);
79349               ['access_token', 'connectId', 'token'].forEach(function (param) {
79350                 if (qs[param]) {
79351                   qs[param] = '{apikey}';
79352                 }
79353               });
79354               cleaned = parts[0] + '?' + utilQsString(qs, true); // true = soft encode
79355             } // from wms/wmts api path parameters
79356
79357
79358             cleaned = cleaned.replace(/token\/(\w+)/, 'token/{apikey}');
79359             return 'Custom (' + cleaned + ' )';
79360           };
79361
79362           source.area = function () {
79363             return -2; // sources in background pane are sorted by area
79364           };
79365
79366           return source;
79367         };
79368
79369         function rendererTileLayer(context) {
79370           var transformProp = utilPrefixCSSProperty('Transform');
79371           var tiler = utilTiler();
79372           var _tileSize = 256;
79373
79374           var _projection;
79375
79376           var _cache = {};
79377
79378           var _tileOrigin;
79379
79380           var _zoom;
79381
79382           var _source;
79383
79384           function tileSizeAtZoom(d, z) {
79385             var EPSILON = 0.002; // close seams
79386
79387             return _tileSize * Math.pow(2, z - d[2]) / _tileSize + EPSILON;
79388           }
79389
79390           function atZoom(t, distance) {
79391             var power = Math.pow(2, distance);
79392             return [Math.floor(t[0] * power), Math.floor(t[1] * power), t[2] + distance];
79393           }
79394
79395           function lookUp(d) {
79396             for (var up = -1; up > -d[2]; up--) {
79397               var tile = atZoom(d, up);
79398
79399               if (_cache[_source.url(tile)] !== false) {
79400                 return tile;
79401               }
79402             }
79403           }
79404
79405           function uniqueBy(a, n) {
79406             var o = [];
79407             var seen = {};
79408
79409             for (var i = 0; i < a.length; i++) {
79410               if (seen[a[i][n]] === undefined) {
79411                 o.push(a[i]);
79412                 seen[a[i][n]] = true;
79413               }
79414             }
79415
79416             return o;
79417           }
79418
79419           function addSource(d) {
79420             d.push(_source.url(d));
79421             return d;
79422           } // Update tiles based on current state of `projection`.
79423
79424
79425           function background(selection) {
79426             _zoom = geoScaleToZoom(_projection.scale(), _tileSize);
79427             var pixelOffset;
79428
79429             if (_source) {
79430               pixelOffset = [_source.offset()[0] * Math.pow(2, _zoom), _source.offset()[1] * Math.pow(2, _zoom)];
79431             } else {
79432               pixelOffset = [0, 0];
79433             }
79434
79435             var translate = [_projection.translate()[0] + pixelOffset[0], _projection.translate()[1] + pixelOffset[1]];
79436             tiler.scale(_projection.scale() * 2 * Math.PI).translate(translate);
79437             _tileOrigin = [_projection.scale() * Math.PI - translate[0], _projection.scale() * Math.PI - translate[1]];
79438             render(selection);
79439           } // Derive the tiles onscreen, remove those offscreen and position them.
79440           // Important that this part not depend on `_projection` because it's
79441           // rentered when tiles load/error (see #644).
79442
79443
79444           function render(selection) {
79445             if (!_source) return;
79446             var requests = [];
79447             var showDebug = context.getDebug('tile') && !_source.overlay;
79448
79449             if (_source.validZoom(_zoom)) {
79450               tiler.skipNullIsland(!!_source.overlay);
79451               tiler().forEach(function (d) {
79452                 addSource(d);
79453                 if (d[3] === '') return;
79454                 if (typeof d[3] !== 'string') return; // Workaround for #2295
79455
79456                 requests.push(d);
79457
79458                 if (_cache[d[3]] === false && lookUp(d)) {
79459                   requests.push(addSource(lookUp(d)));
79460                 }
79461               });
79462               requests = uniqueBy(requests, 3).filter(function (r) {
79463                 // don't re-request tiles which have failed in the past
79464                 return _cache[r[3]] !== false;
79465               });
79466             }
79467
79468             function load(d3_event, d) {
79469               _cache[d[3]] = true;
79470               select(this).on('error', null).on('load', null).classed('tile-loaded', true);
79471               render(selection);
79472             }
79473
79474             function error(d3_event, d) {
79475               _cache[d[3]] = false;
79476               select(this).on('error', null).on('load', null).remove();
79477               render(selection);
79478             }
79479
79480             function imageTransform(d) {
79481               var ts = _tileSize * Math.pow(2, _zoom - d[2]);
79482
79483               var scale = tileSizeAtZoom(d, _zoom);
79484               return 'translate(' + (d[0] * ts - _tileOrigin[0]) + 'px,' + (d[1] * ts - _tileOrigin[1]) + 'px) ' + 'scale(' + scale + ',' + scale + ')';
79485             }
79486
79487             function tileCenter(d) {
79488               var ts = _tileSize * Math.pow(2, _zoom - d[2]);
79489
79490               return [d[0] * ts - _tileOrigin[0] + ts / 2, d[1] * ts - _tileOrigin[1] + ts / 2];
79491             }
79492
79493             function debugTransform(d) {
79494               var coord = tileCenter(d);
79495               return 'translate(' + coord[0] + 'px,' + coord[1] + 'px)';
79496             } // Pick a representative tile near the center of the viewport
79497             // (This is useful for sampling the imagery vintage)
79498
79499
79500             var dims = tiler.size();
79501             var mapCenter = [dims[0] / 2, dims[1] / 2];
79502             var minDist = Math.max(dims[0], dims[1]);
79503             var nearCenter;
79504             requests.forEach(function (d) {
79505               var c = tileCenter(d);
79506               var dist = geoVecLength(c, mapCenter);
79507
79508               if (dist < minDist) {
79509                 minDist = dist;
79510                 nearCenter = d;
79511               }
79512             });
79513             var image = selection.selectAll('img').data(requests, function (d) {
79514               return d[3];
79515             });
79516             image.exit().style(transformProp, imageTransform).classed('tile-removing', true).classed('tile-center', false).each(function () {
79517               var tile = select(this);
79518               window.setTimeout(function () {
79519                 if (tile.classed('tile-removing')) {
79520                   tile.remove();
79521                 }
79522               }, 300);
79523             });
79524             image.enter().append('img').attr('class', 'tile').attr('alt', '').attr('draggable', 'false').style('width', _tileSize + 'px').style('height', _tileSize + 'px').attr('src', function (d) {
79525               return d[3];
79526             }).on('error', error).on('load', load).merge(image).style(transformProp, imageTransform).classed('tile-debug', showDebug).classed('tile-removing', false).classed('tile-center', function (d) {
79527               return d === nearCenter;
79528             });
79529             var debug = selection.selectAll('.tile-label-debug').data(showDebug ? requests : [], function (d) {
79530               return d[3];
79531             });
79532             debug.exit().remove();
79533
79534             if (showDebug) {
79535               var debugEnter = debug.enter().append('div').attr('class', 'tile-label-debug');
79536               debugEnter.append('div').attr('class', 'tile-label-debug-coord');
79537               debugEnter.append('div').attr('class', 'tile-label-debug-vintage');
79538               debug = debug.merge(debugEnter);
79539               debug.style(transformProp, debugTransform);
79540               debug.selectAll('.tile-label-debug-coord').text(function (d) {
79541                 return d[2] + ' / ' + d[0] + ' / ' + d[1];
79542               });
79543               debug.selectAll('.tile-label-debug-vintage').each(function (d) {
79544                 var span = select(this);
79545                 var center = context.projection.invert(tileCenter(d));
79546
79547                 _source.getMetadata(center, d, function (err, result) {
79548                   if (result && result.vintage && result.vintage.range) {
79549                     span.text(result.vintage.range);
79550                   } else {
79551                     span.html(_t.html('info_panels.background.vintage') + ': ' + _t.html('info_panels.background.unknown'));
79552                   }
79553                 });
79554               });
79555             }
79556           }
79557
79558           background.projection = function (val) {
79559             if (!arguments.length) return _projection;
79560             _projection = val;
79561             return background;
79562           };
79563
79564           background.dimensions = function (val) {
79565             if (!arguments.length) return tiler.size();
79566             tiler.size(val);
79567             return background;
79568           };
79569
79570           background.source = function (val) {
79571             if (!arguments.length) return _source;
79572             _source = val;
79573             _tileSize = _source.tileSize;
79574             _cache = {};
79575             tiler.tileSize(_source.tileSize).zoomExtent(_source.zoomExtent);
79576             return background;
79577           };
79578
79579           return background;
79580         }
79581
79582         var _imageryIndex = null;
79583         function rendererBackground(context) {
79584           var dispatch = dispatch$8('change');
79585           var detected = utilDetect();
79586           var baseLayer = rendererTileLayer(context).projection(context.projection);
79587           var _checkedBlocklists = [];
79588           var _isValid = true;
79589           var _overlayLayers = [];
79590           var _brightness = 1;
79591           var _contrast = 1;
79592           var _saturation = 1;
79593           var _sharpness = 1;
79594
79595           function ensureImageryIndex() {
79596             return _mainFileFetcher.get('imagery').then(function (sources) {
79597               if (_imageryIndex) return _imageryIndex;
79598               _imageryIndex = {
79599                 imagery: sources,
79600                 features: {}
79601               }; // use which-polygon to support efficient index and querying for imagery
79602
79603               var features = sources.map(function (source) {
79604                 if (!source.polygon) return null; // workaround for editor-layer-index weirdness..
79605                 // Add an extra array nest to each element in `source.polygon`
79606                 // so the rings are not treated as a bunch of holes:
79607                 // what we have: [ [[outer],[hole],[hole]] ]
79608                 // what we want: [ [[outer]],[[outer]],[[outer]] ]
79609
79610                 var rings = source.polygon.map(function (ring) {
79611                   return [ring];
79612                 });
79613                 var feature = {
79614                   type: 'Feature',
79615                   properties: {
79616                     id: source.id
79617                   },
79618                   geometry: {
79619                     type: 'MultiPolygon',
79620                     coordinates: rings
79621                   }
79622                 };
79623                 _imageryIndex.features[source.id] = feature;
79624                 return feature;
79625               }).filter(Boolean);
79626               _imageryIndex.query = whichPolygon_1({
79627                 type: 'FeatureCollection',
79628                 features: features
79629               }); // Instantiate `rendererBackgroundSource` objects for each source
79630
79631               _imageryIndex.backgrounds = sources.map(function (source) {
79632                 if (source.type === 'bing') {
79633                   return rendererBackgroundSource.Bing(source, dispatch);
79634                 } else if (/^EsriWorldImagery/.test(source.id)) {
79635                   return rendererBackgroundSource.Esri(source);
79636                 } else {
79637                   return rendererBackgroundSource(source);
79638                 }
79639               }); // Add 'None'
79640
79641               _imageryIndex.backgrounds.unshift(rendererBackgroundSource.None()); // Add 'Custom'
79642
79643
79644               var template = corePreferences('background-custom-template') || '';
79645               var custom = rendererBackgroundSource.Custom(template);
79646
79647               _imageryIndex.backgrounds.unshift(custom);
79648
79649               return _imageryIndex;
79650             });
79651           }
79652
79653           function background(selection) {
79654             var currSource = baseLayer.source(); // If we are displaying an Esri basemap at high zoom,
79655             // check its tilemap to see how high the zoom can go
79656
79657             if (context.map().zoom() > 18) {
79658               if (currSource && /^EsriWorldImagery/.test(currSource.id)) {
79659                 var center = context.map().center();
79660                 currSource.fetchTilemap(center);
79661               }
79662             } // Is the imagery valid here? - #4827
79663
79664
79665             var sources = background.sources(context.map().extent());
79666             var wasValid = _isValid;
79667             _isValid = !!sources.filter(function (d) {
79668               return d === currSource;
79669             }).length;
79670
79671             if (wasValid !== _isValid) {
79672               // change in valid status
79673               background.updateImagery();
79674             }
79675
79676             var baseFilter = '';
79677
79678             if (detected.cssfilters) {
79679               if (_brightness !== 1) {
79680                 baseFilter += " brightness(".concat(_brightness, ")");
79681               }
79682
79683               if (_contrast !== 1) {
79684                 baseFilter += " contrast(".concat(_contrast, ")");
79685               }
79686
79687               if (_saturation !== 1) {
79688                 baseFilter += " saturate(".concat(_saturation, ")");
79689               }
79690
79691               if (_sharpness < 1) {
79692                 // gaussian blur
79693                 var blur = d3_interpolateNumber(0.5, 5)(1 - _sharpness);
79694                 baseFilter += " blur(".concat(blur, "px)");
79695               }
79696             }
79697
79698             var base = selection.selectAll('.layer-background').data([0]);
79699             base = base.enter().insert('div', '.layer-data').attr('class', 'layer layer-background').merge(base);
79700
79701             if (detected.cssfilters) {
79702               base.style('filter', baseFilter || null);
79703             } else {
79704               base.style('opacity', _brightness);
79705             }
79706
79707             var imagery = base.selectAll('.layer-imagery').data([0]);
79708             imagery.enter().append('div').attr('class', 'layer layer-imagery').merge(imagery).call(baseLayer);
79709             var maskFilter = '';
79710             var mixBlendMode = '';
79711
79712             if (detected.cssfilters && _sharpness > 1) {
79713               // apply unsharp mask
79714               mixBlendMode = 'overlay';
79715               maskFilter = 'saturate(0) blur(3px) invert(1)';
79716               var contrast = _sharpness - 1;
79717               maskFilter += " contrast(".concat(contrast, ")");
79718               var brightness = d3_interpolateNumber(1, 0.85)(_sharpness - 1);
79719               maskFilter += " brightness(".concat(brightness, ")");
79720             }
79721
79722             var mask = base.selectAll('.layer-unsharp-mask').data(detected.cssfilters && _sharpness > 1 ? [0] : []);
79723             mask.exit().remove();
79724             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);
79725             var overlays = selection.selectAll('.layer-overlay').data(_overlayLayers, function (d) {
79726               return d.source().name();
79727             });
79728             overlays.exit().remove();
79729             overlays.enter().insert('div', '.layer-data').attr('class', 'layer layer-overlay').merge(overlays).each(function (layer, i, nodes) {
79730               return select(nodes[i]).call(layer);
79731             });
79732           }
79733
79734           background.updateImagery = function () {
79735             var currSource = baseLayer.source();
79736             if (context.inIntro() || !currSource) return;
79737
79738             var o = _overlayLayers.filter(function (d) {
79739               return !d.source().isLocatorOverlay() && !d.source().isHidden();
79740             }).map(function (d) {
79741               return d.source().id;
79742             }).join(',');
79743
79744             var meters = geoOffsetToMeters(currSource.offset());
79745             var EPSILON = 0.01;
79746             var x = +meters[0].toFixed(2);
79747             var y = +meters[1].toFixed(2);
79748             var hash = utilStringQs(window.location.hash);
79749             var id = currSource.id;
79750
79751             if (id === 'custom') {
79752               id = "custom:".concat(currSource.template());
79753             }
79754
79755             if (id) {
79756               hash.background = id;
79757             } else {
79758               delete hash.background;
79759             }
79760
79761             if (o) {
79762               hash.overlays = o;
79763             } else {
79764               delete hash.overlays;
79765             }
79766
79767             if (Math.abs(x) > EPSILON || Math.abs(y) > EPSILON) {
79768               hash.offset = "".concat(x, ",").concat(y);
79769             } else {
79770               delete hash.offset;
79771             }
79772
79773             if (!window.mocha) {
79774               window.location.replace('#' + utilQsString(hash, true));
79775             }
79776
79777             var imageryUsed = [];
79778             var photoOverlaysUsed = [];
79779             var currUsed = currSource.imageryUsed();
79780
79781             if (currUsed && _isValid) {
79782               imageryUsed.push(currUsed);
79783             }
79784
79785             _overlayLayers.filter(function (d) {
79786               return !d.source().isLocatorOverlay() && !d.source().isHidden();
79787             }).forEach(function (d) {
79788               return imageryUsed.push(d.source().imageryUsed());
79789             });
79790
79791             var dataLayer = context.layers().layer('data');
79792
79793             if (dataLayer && dataLayer.enabled() && dataLayer.hasData()) {
79794               imageryUsed.push(dataLayer.getSrc());
79795             }
79796
79797             var photoOverlayLayers = {
79798               streetside: 'Bing Streetside',
79799               mapillary: 'Mapillary Images',
79800               'mapillary-map-features': 'Mapillary Map Features',
79801               'mapillary-signs': 'Mapillary Signs',
79802               kartaview: 'KartaView Images'
79803             };
79804
79805             for (var layerID in photoOverlayLayers) {
79806               var layer = context.layers().layer(layerID);
79807
79808               if (layer && layer.enabled()) {
79809                 photoOverlaysUsed.push(layerID);
79810                 imageryUsed.push(photoOverlayLayers[layerID]);
79811               }
79812             }
79813
79814             context.history().imageryUsed(imageryUsed);
79815             context.history().photoOverlaysUsed(photoOverlaysUsed);
79816           };
79817
79818           background.sources = function (extent, zoom, includeCurrent) {
79819             if (!_imageryIndex) return []; // called before init()?
79820
79821             var visible = {};
79822             (_imageryIndex.query.bbox(extent.rectangle(), true) || []).forEach(function (d) {
79823               return visible[d.id] = true;
79824             });
79825             var currSource = baseLayer.source(); // Recheck blocked sources only if we detect new blocklists pulled from the OSM API.
79826
79827             var osm = context.connection();
79828             var blocklists = osm && osm.imageryBlocklists() || [];
79829             var blocklistChanged = blocklists.length !== _checkedBlocklists.length || blocklists.some(function (regex, index) {
79830               return String(regex) !== _checkedBlocklists[index];
79831             });
79832
79833             if (blocklistChanged) {
79834               _imageryIndex.backgrounds.forEach(function (source) {
79835                 source.isBlocked = blocklists.some(function (regex) {
79836                   return regex.test(source.template());
79837                 });
79838               });
79839
79840               _checkedBlocklists = blocklists.map(function (regex) {
79841                 return String(regex);
79842               });
79843             }
79844
79845             return _imageryIndex.backgrounds.filter(function (source) {
79846               if (includeCurrent && currSource === source) return true; // optionally always include the current imagery
79847
79848               if (source.isBlocked) return false; // even bundled sources may be blocked - #7905
79849
79850               if (!source.polygon) return true; // always include imagery with worldwide coverage
79851
79852               if (zoom && zoom < 6) return false; // optionally exclude local imagery at low zooms
79853
79854               return visible[source.id]; // include imagery visible in given extent
79855             });
79856           };
79857
79858           background.dimensions = function (val) {
79859             if (!val) return;
79860             baseLayer.dimensions(val);
79861
79862             _overlayLayers.forEach(function (layer) {
79863               return layer.dimensions(val);
79864             });
79865           };
79866
79867           background.baseLayerSource = function (d) {
79868             if (!arguments.length) return baseLayer.source(); // test source against OSM imagery blocklists..
79869
79870             var osm = context.connection();
79871             if (!osm) return background;
79872             var blocklists = osm.imageryBlocklists();
79873             var template = d.template();
79874             var fail = false;
79875             var tested = 0;
79876             var regex;
79877
79878             for (var i = 0; i < blocklists.length; i++) {
79879               regex = blocklists[i];
79880               fail = regex.test(template);
79881               tested++;
79882               if (fail) break;
79883             } // ensure at least one test was run.
79884
79885
79886             if (!tested) {
79887               regex = /.*\.google(apis)?\..*\/(vt|kh)[\?\/].*([xyz]=.*){3}.*/;
79888               fail = regex.test(template);
79889             }
79890
79891             baseLayer.source(!fail ? d : background.findSource('none'));
79892             dispatch.call('change');
79893             background.updateImagery();
79894             return background;
79895           };
79896
79897           background.findSource = function (id) {
79898             if (!id || !_imageryIndex) return null; // called before init()?
79899
79900             return _imageryIndex.backgrounds.find(function (d) {
79901               return d.id && d.id === id;
79902             });
79903           };
79904
79905           background.bing = function () {
79906             background.baseLayerSource(background.findSource('Bing'));
79907           };
79908
79909           background.showsLayer = function (d) {
79910             var currSource = baseLayer.source();
79911             if (!d || !currSource) return false;
79912             return d.id === currSource.id || _overlayLayers.some(function (layer) {
79913               return d.id === layer.source().id;
79914             });
79915           };
79916
79917           background.overlayLayerSources = function () {
79918             return _overlayLayers.map(function (layer) {
79919               return layer.source();
79920             });
79921           };
79922
79923           background.toggleOverlayLayer = function (d) {
79924             var layer;
79925
79926             for (var i = 0; i < _overlayLayers.length; i++) {
79927               layer = _overlayLayers[i];
79928
79929               if (layer.source() === d) {
79930                 _overlayLayers.splice(i, 1);
79931
79932                 dispatch.call('change');
79933                 background.updateImagery();
79934                 return;
79935               }
79936             }
79937
79938             layer = rendererTileLayer(context).source(d).projection(context.projection).dimensions(baseLayer.dimensions());
79939
79940             _overlayLayers.push(layer);
79941
79942             dispatch.call('change');
79943             background.updateImagery();
79944           };
79945
79946           background.nudge = function (d, zoom) {
79947             var currSource = baseLayer.source();
79948
79949             if (currSource) {
79950               currSource.nudge(d, zoom);
79951               dispatch.call('change');
79952               background.updateImagery();
79953             }
79954
79955             return background;
79956           };
79957
79958           background.offset = function (d) {
79959             var currSource = baseLayer.source();
79960
79961             if (!arguments.length) {
79962               return currSource && currSource.offset() || [0, 0];
79963             }
79964
79965             if (currSource) {
79966               currSource.offset(d);
79967               dispatch.call('change');
79968               background.updateImagery();
79969             }
79970
79971             return background;
79972           };
79973
79974           background.brightness = function (d) {
79975             if (!arguments.length) return _brightness;
79976             _brightness = d;
79977             if (context.mode()) dispatch.call('change');
79978             return background;
79979           };
79980
79981           background.contrast = function (d) {
79982             if (!arguments.length) return _contrast;
79983             _contrast = d;
79984             if (context.mode()) dispatch.call('change');
79985             return background;
79986           };
79987
79988           background.saturation = function (d) {
79989             if (!arguments.length) return _saturation;
79990             _saturation = d;
79991             if (context.mode()) dispatch.call('change');
79992             return background;
79993           };
79994
79995           background.sharpness = function (d) {
79996             if (!arguments.length) return _sharpness;
79997             _sharpness = d;
79998             if (context.mode()) dispatch.call('change');
79999             return background;
80000           };
80001
80002           var _loadPromise;
80003
80004           background.ensureLoaded = function () {
80005             if (_loadPromise) return _loadPromise;
80006
80007             function parseMapParams(qmap) {
80008               if (!qmap) return false;
80009               var params = qmap.split('/').map(Number);
80010               if (params.length < 3 || params.some(isNaN)) return false;
80011               return geoExtent([params[2], params[1]]); // lon,lat
80012             }
80013
80014             var hash = utilStringQs(window.location.hash);
80015             var requested = hash.background || hash.layer;
80016             var extent = parseMapParams(hash.map);
80017             return _loadPromise = ensureImageryIndex().then(function (imageryIndex) {
80018               var first = imageryIndex.backgrounds.length && imageryIndex.backgrounds[0];
80019               var best;
80020
80021               if (!requested && extent) {
80022                 best = background.sources(extent).find(function (s) {
80023                   return s.best();
80024                 });
80025               } // Decide which background layer to display
80026
80027
80028               if (requested && requested.indexOf('custom:') === 0) {
80029                 var template = requested.replace(/^custom:/, '');
80030                 var custom = background.findSource('custom');
80031                 background.baseLayerSource(custom.template(template));
80032                 corePreferences('background-custom-template', template);
80033               } else {
80034                 background.baseLayerSource(background.findSource(requested) || best || background.findSource(corePreferences('background-last-used')) || background.findSource('Bing') || first || background.findSource('none'));
80035               }
80036
80037               var locator = imageryIndex.backgrounds.find(function (d) {
80038                 return d.overlay && d["default"];
80039               });
80040
80041               if (locator) {
80042                 background.toggleOverlayLayer(locator);
80043               }
80044
80045               var overlays = (hash.overlays || '').split(',');
80046               overlays.forEach(function (overlay) {
80047                 overlay = background.findSource(overlay);
80048
80049                 if (overlay) {
80050                   background.toggleOverlayLayer(overlay);
80051                 }
80052               });
80053
80054               if (hash.gpx) {
80055                 var gpx = context.layers().layer('data');
80056
80057                 if (gpx) {
80058                   gpx.url(hash.gpx, '.gpx');
80059                 }
80060               }
80061
80062               if (hash.offset) {
80063                 var offset = hash.offset.replace(/;/g, ',').split(',').map(function (n) {
80064                   return !isNaN(n) && n;
80065                 });
80066
80067                 if (offset.length === 2) {
80068                   background.offset(geoMetersToOffset(offset));
80069                 }
80070               }
80071             })["catch"](function () {
80072               /* ignore */
80073             });
80074           };
80075
80076           return utilRebind(background, dispatch, 'on');
80077         }
80078
80079         function rendererFeatures(context) {
80080           var dispatch = dispatch$8('change', 'redraw');
80081           var features = utilRebind({}, dispatch, 'on');
80082
80083           var _deferred = new Set();
80084
80085           var traffic_roads = {
80086             'motorway': true,
80087             'motorway_link': true,
80088             'trunk': true,
80089             'trunk_link': true,
80090             'primary': true,
80091             'primary_link': true,
80092             'secondary': true,
80093             'secondary_link': true,
80094             'tertiary': true,
80095             'tertiary_link': true,
80096             'residential': true,
80097             'unclassified': true,
80098             'living_street': true
80099           };
80100           var service_roads = {
80101             'service': true,
80102             'road': true,
80103             'track': true
80104           };
80105           var paths = {
80106             'path': true,
80107             'footway': true,
80108             'cycleway': true,
80109             'bridleway': true,
80110             'steps': true,
80111             'pedestrian': true
80112           };
80113           var past_futures = {
80114             'proposed': true,
80115             'construction': true,
80116             'abandoned': true,
80117             'dismantled': true,
80118             'disused': true,
80119             'razed': true,
80120             'demolished': true,
80121             'obliterated': true
80122           };
80123           var _cullFactor = 1;
80124           var _cache = {};
80125           var _rules = {};
80126           var _stats = {};
80127           var _keys = [];
80128           var _hidden = [];
80129           var _forceVisible = {};
80130
80131           function update() {
80132             if (!window.mocha) {
80133               var hash = utilStringQs(window.location.hash);
80134               var disabled = features.disabled();
80135
80136               if (disabled.length) {
80137                 hash.disable_features = disabled.join(',');
80138               } else {
80139                 delete hash.disable_features;
80140               }
80141
80142               window.location.replace('#' + utilQsString(hash, true));
80143               corePreferences('disabled-features', disabled.join(','));
80144             }
80145
80146             _hidden = features.hidden();
80147             dispatch.call('change');
80148             dispatch.call('redraw');
80149           }
80150
80151           function defineRule(k, filter, max) {
80152             var isEnabled = true;
80153
80154             _keys.push(k);
80155
80156             _rules[k] = {
80157               filter: filter,
80158               enabled: isEnabled,
80159               // whether the user wants it enabled..
80160               count: 0,
80161               currentMax: max || Infinity,
80162               defaultMax: max || Infinity,
80163               enable: function enable() {
80164                 this.enabled = true;
80165                 this.currentMax = this.defaultMax;
80166               },
80167               disable: function disable() {
80168                 this.enabled = false;
80169                 this.currentMax = 0;
80170               },
80171               hidden: function hidden() {
80172                 return this.count === 0 && !this.enabled || this.count > this.currentMax * _cullFactor;
80173               },
80174               autoHidden: function autoHidden() {
80175                 return this.hidden() && this.currentMax > 0;
80176               }
80177             };
80178           }
80179
80180           defineRule('points', function isPoint(tags, geometry) {
80181             return geometry === 'point';
80182           }, 200);
80183           defineRule('traffic_roads', function isTrafficRoad(tags) {
80184             return traffic_roads[tags.highway];
80185           });
80186           defineRule('service_roads', function isServiceRoad(tags) {
80187             return service_roads[tags.highway];
80188           });
80189           defineRule('paths', function isPath(tags) {
80190             return paths[tags.highway];
80191           });
80192           defineRule('buildings', function isBuilding(tags) {
80193             return !!tags.building && tags.building !== 'no' || tags.parking === 'multi-storey' || tags.parking === 'sheds' || tags.parking === 'carports' || tags.parking === 'garage_boxes';
80194           }, 250);
80195           defineRule('building_parts', function isBuildingPart(tags) {
80196             return tags['building:part'];
80197           });
80198           defineRule('indoor', function isIndoor(tags) {
80199             return tags.indoor;
80200           });
80201           defineRule('landuse', function isLanduse(tags, geometry) {
80202             return geometry === 'area' && !_rules.buildings.filter(tags) && !_rules.building_parts.filter(tags) && !_rules.indoor.filter(tags) && !_rules.water.filter(tags) && !_rules.pistes.filter(tags);
80203           });
80204           defineRule('boundaries', function isBoundary(tags) {
80205             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);
80206           });
80207           defineRule('water', function isWater(tags) {
80208             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';
80209           });
80210           defineRule('rail', function isRail(tags) {
80211             return (!!tags.railway || tags.landuse === 'railway') && !(traffic_roads[tags.highway] || service_roads[tags.highway] || paths[tags.highway]);
80212           });
80213           defineRule('pistes', function isPiste(tags) {
80214             return tags['piste:type'];
80215           });
80216           defineRule('aerialways', function isPiste(tags) {
80217             return tags.aerialway && tags.aerialway !== 'yes' && tags.aerialway !== 'station';
80218           });
80219           defineRule('power', function isPower(tags) {
80220             return !!tags.power;
80221           }); // contains a past/future tag, but not in active use as a road/path/cycleway/etc..
80222
80223           defineRule('past_future', function isPastFuture(tags) {
80224             if (traffic_roads[tags.highway] || service_roads[tags.highway] || paths[tags.highway]) {
80225               return false;
80226             }
80227
80228             var strings = Object.keys(tags);
80229
80230             for (var i = 0; i < strings.length; i++) {
80231               var s = strings[i];
80232
80233               if (past_futures[s] || past_futures[tags[s]]) {
80234                 return true;
80235               }
80236             }
80237
80238             return false;
80239           }); // Lines or areas that don't match another feature filter.
80240           // IMPORTANT: The 'others' feature must be the last one defined,
80241           //   so that code in getMatches can skip this test if `hasMatch = true`
80242
80243           defineRule('others', function isOther(tags, geometry) {
80244             return geometry === 'line' || geometry === 'area';
80245           });
80246
80247           features.features = function () {
80248             return _rules;
80249           };
80250
80251           features.keys = function () {
80252             return _keys;
80253           };
80254
80255           features.enabled = function (k) {
80256             if (!arguments.length) {
80257               return _keys.filter(function (k) {
80258                 return _rules[k].enabled;
80259               });
80260             }
80261
80262             return _rules[k] && _rules[k].enabled;
80263           };
80264
80265           features.disabled = function (k) {
80266             if (!arguments.length) {
80267               return _keys.filter(function (k) {
80268                 return !_rules[k].enabled;
80269               });
80270             }
80271
80272             return _rules[k] && !_rules[k].enabled;
80273           };
80274
80275           features.hidden = function (k) {
80276             if (!arguments.length) {
80277               return _keys.filter(function (k) {
80278                 return _rules[k].hidden();
80279               });
80280             }
80281
80282             return _rules[k] && _rules[k].hidden();
80283           };
80284
80285           features.autoHidden = function (k) {
80286             if (!arguments.length) {
80287               return _keys.filter(function (k) {
80288                 return _rules[k].autoHidden();
80289               });
80290             }
80291
80292             return _rules[k] && _rules[k].autoHidden();
80293           };
80294
80295           features.enable = function (k) {
80296             if (_rules[k] && !_rules[k].enabled) {
80297               _rules[k].enable();
80298
80299               update();
80300             }
80301           };
80302
80303           features.enableAll = function () {
80304             var didEnable = false;
80305
80306             for (var k in _rules) {
80307               if (!_rules[k].enabled) {
80308                 didEnable = true;
80309
80310                 _rules[k].enable();
80311               }
80312             }
80313
80314             if (didEnable) update();
80315           };
80316
80317           features.disable = function (k) {
80318             if (_rules[k] && _rules[k].enabled) {
80319               _rules[k].disable();
80320
80321               update();
80322             }
80323           };
80324
80325           features.disableAll = function () {
80326             var didDisable = false;
80327
80328             for (var k in _rules) {
80329               if (_rules[k].enabled) {
80330                 didDisable = true;
80331
80332                 _rules[k].disable();
80333               }
80334             }
80335
80336             if (didDisable) update();
80337           };
80338
80339           features.toggle = function (k) {
80340             if (_rules[k]) {
80341               (function (f) {
80342                 return f.enabled ? f.disable() : f.enable();
80343               })(_rules[k]);
80344
80345               update();
80346             }
80347           };
80348
80349           features.resetStats = function () {
80350             for (var i = 0; i < _keys.length; i++) {
80351               _rules[_keys[i]].count = 0;
80352             }
80353
80354             dispatch.call('change');
80355           };
80356
80357           features.gatherStats = function (d, resolver, dimensions) {
80358             var needsRedraw = false;
80359             var types = utilArrayGroupBy(d, 'type');
80360             var entities = [].concat(types.relation || [], types.way || [], types.node || []);
80361             var currHidden, geometry, matches, i, j;
80362
80363             for (i = 0; i < _keys.length; i++) {
80364               _rules[_keys[i]].count = 0;
80365             } // adjust the threshold for point/building culling based on viewport size..
80366             // a _cullFactor of 1 corresponds to a 1000x1000px viewport..
80367
80368
80369             _cullFactor = dimensions[0] * dimensions[1] / 1000000;
80370
80371             for (i = 0; i < entities.length; i++) {
80372               geometry = entities[i].geometry(resolver);
80373               matches = Object.keys(features.getMatches(entities[i], resolver, geometry));
80374
80375               for (j = 0; j < matches.length; j++) {
80376                 _rules[matches[j]].count++;
80377               }
80378             }
80379
80380             currHidden = features.hidden();
80381
80382             if (currHidden !== _hidden) {
80383               _hidden = currHidden;
80384               needsRedraw = true;
80385               dispatch.call('change');
80386             }
80387
80388             return needsRedraw;
80389           };
80390
80391           features.stats = function () {
80392             for (var i = 0; i < _keys.length; i++) {
80393               _stats[_keys[i]] = _rules[_keys[i]].count;
80394             }
80395
80396             return _stats;
80397           };
80398
80399           features.clear = function (d) {
80400             for (var i = 0; i < d.length; i++) {
80401               features.clearEntity(d[i]);
80402             }
80403           };
80404
80405           features.clearEntity = function (entity) {
80406             delete _cache[osmEntity.key(entity)];
80407           };
80408
80409           features.reset = function () {
80410             Array.from(_deferred).forEach(function (handle) {
80411               window.cancelIdleCallback(handle);
80412
80413               _deferred["delete"](handle);
80414             });
80415             _cache = {};
80416           }; // only certain relations are worth checking
80417
80418
80419           function relationShouldBeChecked(relation) {
80420             // multipolygon features have `area` geometry and aren't checked here
80421             return relation.tags.type === 'boundary';
80422           }
80423
80424           features.getMatches = function (entity, resolver, geometry) {
80425             if (geometry === 'vertex' || geometry === 'relation' && !relationShouldBeChecked(entity)) return {};
80426             var ent = osmEntity.key(entity);
80427
80428             if (!_cache[ent]) {
80429               _cache[ent] = {};
80430             }
80431
80432             if (!_cache[ent].matches) {
80433               var matches = {};
80434               var hasMatch = false;
80435
80436               for (var i = 0; i < _keys.length; i++) {
80437                 if (_keys[i] === 'others') {
80438                   if (hasMatch) continue; // If an entity...
80439                   //   1. is a way that hasn't matched other 'interesting' feature rules,
80440
80441                   if (entity.type === 'way') {
80442                     var parents = features.getParents(entity, resolver, geometry); //   2a. belongs only to a single multipolygon relation
80443
80444                     if (parents.length === 1 && parents[0].isMultipolygon() || // 2b. or belongs only to boundary relations
80445                     parents.length > 0 && parents.every(function (parent) {
80446                       return parent.tags.type === 'boundary';
80447                     })) {
80448                       // ...then match whatever feature rules the parent relation has matched.
80449                       // see #2548, #2887
80450                       //
80451                       // IMPORTANT:
80452                       // For this to work, getMatches must be called on relations before ways.
80453                       //
80454                       var pkey = osmEntity.key(parents[0]);
80455
80456                       if (_cache[pkey] && _cache[pkey].matches) {
80457                         matches = Object.assign({}, _cache[pkey].matches); // shallow copy
80458
80459                         continue;
80460                       }
80461                     }
80462                   }
80463                 }
80464
80465                 if (_rules[_keys[i]].filter(entity.tags, geometry)) {
80466                   matches[_keys[i]] = hasMatch = true;
80467                 }
80468               }
80469
80470               _cache[ent].matches = matches;
80471             }
80472
80473             return _cache[ent].matches;
80474           };
80475
80476           features.getParents = function (entity, resolver, geometry) {
80477             if (geometry === 'point') return [];
80478             var ent = osmEntity.key(entity);
80479
80480             if (!_cache[ent]) {
80481               _cache[ent] = {};
80482             }
80483
80484             if (!_cache[ent].parents) {
80485               var parents = [];
80486
80487               if (geometry === 'vertex') {
80488                 parents = resolver.parentWays(entity);
80489               } else {
80490                 // 'line', 'area', 'relation'
80491                 parents = resolver.parentRelations(entity);
80492               }
80493
80494               _cache[ent].parents = parents;
80495             }
80496
80497             return _cache[ent].parents;
80498           };
80499
80500           features.isHiddenPreset = function (preset, geometry) {
80501             if (!_hidden.length) return false;
80502             if (!preset.tags) return false;
80503             var test = preset.setTags({}, geometry);
80504
80505             for (var key in _rules) {
80506               if (_rules[key].filter(test, geometry)) {
80507                 if (_hidden.indexOf(key) !== -1) {
80508                   return key;
80509                 }
80510
80511                 return false;
80512               }
80513             }
80514
80515             return false;
80516           };
80517
80518           features.isHiddenFeature = function (entity, resolver, geometry) {
80519             if (!_hidden.length) return false;
80520             if (!entity.version) return false;
80521             if (_forceVisible[entity.id]) return false;
80522             var matches = Object.keys(features.getMatches(entity, resolver, geometry));
80523             return matches.length && matches.every(function (k) {
80524               return features.hidden(k);
80525             });
80526           };
80527
80528           features.isHiddenChild = function (entity, resolver, geometry) {
80529             if (!_hidden.length) return false;
80530             if (!entity.version || geometry === 'point') return false;
80531             if (_forceVisible[entity.id]) return false;
80532             var parents = features.getParents(entity, resolver, geometry);
80533             if (!parents.length) return false;
80534
80535             for (var i = 0; i < parents.length; i++) {
80536               if (!features.isHidden(parents[i], resolver, parents[i].geometry(resolver))) {
80537                 return false;
80538               }
80539             }
80540
80541             return true;
80542           };
80543
80544           features.hasHiddenConnections = function (entity, resolver) {
80545             if (!_hidden.length) return false;
80546             var childNodes, connections;
80547
80548             if (entity.type === 'midpoint') {
80549               childNodes = [resolver.entity(entity.edge[0]), resolver.entity(entity.edge[1])];
80550               connections = [];
80551             } else {
80552               childNodes = entity.nodes ? resolver.childNodes(entity) : [];
80553               connections = features.getParents(entity, resolver, entity.geometry(resolver));
80554             } // gather ways connected to child nodes..
80555
80556
80557             connections = childNodes.reduce(function (result, e) {
80558               return resolver.isShared(e) ? utilArrayUnion(result, resolver.parentWays(e)) : result;
80559             }, connections);
80560             return connections.some(function (e) {
80561               return features.isHidden(e, resolver, e.geometry(resolver));
80562             });
80563           };
80564
80565           features.isHidden = function (entity, resolver, geometry) {
80566             if (!_hidden.length) return false;
80567             if (!entity.version) return false;
80568             var fn = geometry === 'vertex' ? features.isHiddenChild : features.isHiddenFeature;
80569             return fn(entity, resolver, geometry);
80570           };
80571
80572           features.filter = function (d, resolver) {
80573             if (!_hidden.length) return d;
80574             var result = [];
80575
80576             for (var i = 0; i < d.length; i++) {
80577               var entity = d[i];
80578
80579               if (!features.isHidden(entity, resolver, entity.geometry(resolver))) {
80580                 result.push(entity);
80581               }
80582             }
80583
80584             return result;
80585           };
80586
80587           features.forceVisible = function (entityIDs) {
80588             if (!arguments.length) return Object.keys(_forceVisible);
80589             _forceVisible = {};
80590
80591             for (var i = 0; i < entityIDs.length; i++) {
80592               _forceVisible[entityIDs[i]] = true;
80593               var entity = context.hasEntity(entityIDs[i]);
80594
80595               if (entity && entity.type === 'relation') {
80596                 // also show relation members (one level deep)
80597                 for (var j in entity.members) {
80598                   _forceVisible[entity.members[j].id] = true;
80599                 }
80600               }
80601             }
80602
80603             return features;
80604           };
80605
80606           features.init = function () {
80607             var storage = corePreferences('disabled-features');
80608
80609             if (storage) {
80610               var storageDisabled = storage.replace(/;/g, ',').split(',');
80611               storageDisabled.forEach(features.disable);
80612             }
80613
80614             var hash = utilStringQs(window.location.hash);
80615
80616             if (hash.disable_features) {
80617               var hashDisabled = hash.disable_features.replace(/;/g, ',').split(',');
80618               hashDisabled.forEach(features.disable);
80619             }
80620           }; // warm up the feature matching cache upon merging fetched data
80621
80622
80623           context.history().on('merge.features', function (newEntities) {
80624             if (!newEntities) return;
80625             var handle = window.requestIdleCallback(function () {
80626               var graph = context.graph();
80627               var types = utilArrayGroupBy(newEntities, 'type'); // ensure that getMatches is called on relations before ways
80628
80629               var entities = [].concat(types.relation || [], types.way || [], types.node || []);
80630
80631               for (var i = 0; i < entities.length; i++) {
80632                 var geometry = entities[i].geometry(graph);
80633                 features.getMatches(entities[i], graph, geometry);
80634               }
80635             });
80636
80637             _deferred.add(handle);
80638           });
80639           return features;
80640         }
80641
80642         //
80643         // - the activeID - nope
80644         // - 1 away (adjacent) to the activeID - yes (vertices will be merged)
80645         // - 2 away from the activeID - nope (would create a self intersecting segment)
80646         // - all others on a linear way - yes
80647         // - all others on a closed way - nope (would create a self intersecting polygon)
80648         //
80649         // returns
80650         // 0 = active vertex - no touch/connect
80651         // 1 = passive vertex - yes touch/connect
80652         // 2 = adjacent vertex - yes but pay attention segmenting a line here
80653         //
80654
80655         function svgPassiveVertex(node, graph, activeID) {
80656           if (!activeID) return 1;
80657           if (activeID === node.id) return 0;
80658           var parents = graph.parentWays(node);
80659           var i, j, nodes, isClosed, ix1, ix2, ix3, ix4, max;
80660
80661           for (i = 0; i < parents.length; i++) {
80662             nodes = parents[i].nodes;
80663             isClosed = parents[i].isClosed();
80664
80665             for (j = 0; j < nodes.length; j++) {
80666               // find this vertex, look nearby
80667               if (nodes[j] === node.id) {
80668                 ix1 = j - 2;
80669                 ix2 = j - 1;
80670                 ix3 = j + 1;
80671                 ix4 = j + 2;
80672
80673                 if (isClosed) {
80674                   // wraparound if needed
80675                   max = nodes.length - 1;
80676                   if (ix1 < 0) ix1 = max + ix1;
80677                   if (ix2 < 0) ix2 = max + ix2;
80678                   if (ix3 > max) ix3 = ix3 - max;
80679                   if (ix4 > max) ix4 = ix4 - max;
80680                 }
80681
80682                 if (nodes[ix1] === activeID) return 0; // no - prevent self intersect
80683                 else if (nodes[ix2] === activeID) return 2; // ok - adjacent
80684                 else if (nodes[ix3] === activeID) return 2; // ok - adjacent
80685                 else if (nodes[ix4] === activeID) return 0; // no - prevent self intersect
80686                 else if (isClosed && nodes.indexOf(activeID) !== -1) return 0; // no - prevent self intersect
80687               }
80688             }
80689           }
80690
80691           return 1; // ok
80692         }
80693         function svgMarkerSegments(projection, graph, dt, shouldReverse, bothDirections) {
80694           return function (entity) {
80695             var i = 0;
80696             var offset = dt;
80697             var segments = [];
80698             var clip = d3_geoIdentity().clipExtent(projection.clipExtent()).stream;
80699             var coordinates = graph.childNodes(entity).map(function (n) {
80700               return n.loc;
80701             });
80702             var a, b;
80703
80704             if (shouldReverse(entity)) {
80705               coordinates.reverse();
80706             }
80707
80708             d3_geoStream({
80709               type: 'LineString',
80710               coordinates: coordinates
80711             }, projection.stream(clip({
80712               lineStart: function lineStart() {},
80713               lineEnd: function lineEnd() {
80714                 a = null;
80715               },
80716               point: function point(x, y) {
80717                 b = [x, y];
80718
80719                 if (a) {
80720                   var span = geoVecLength(a, b) - offset;
80721
80722                   if (span >= 0) {
80723                     var heading = geoVecAngle(a, b);
80724                     var dx = dt * Math.cos(heading);
80725                     var dy = dt * Math.sin(heading);
80726                     var p = [a[0] + offset * Math.cos(heading), a[1] + offset * Math.sin(heading)]; // gather coordinates
80727
80728                     var coord = [a, p];
80729
80730                     for (span -= dt; span >= 0; span -= dt) {
80731                       p = geoVecAdd(p, [dx, dy]);
80732                       coord.push(p);
80733                     }
80734
80735                     coord.push(b); // generate svg paths
80736
80737                     var segment = '';
80738                     var j;
80739
80740                     for (j = 0; j < coord.length; j++) {
80741                       segment += (j === 0 ? 'M' : 'L') + coord[j][0] + ',' + coord[j][1];
80742                     }
80743
80744                     segments.push({
80745                       id: entity.id,
80746                       index: i++,
80747                       d: segment
80748                     });
80749
80750                     if (bothDirections(entity)) {
80751                       segment = '';
80752
80753                       for (j = coord.length - 1; j >= 0; j--) {
80754                         segment += (j === coord.length - 1 ? 'M' : 'L') + coord[j][0] + ',' + coord[j][1];
80755                       }
80756
80757                       segments.push({
80758                         id: entity.id,
80759                         index: i++,
80760                         d: segment
80761                       });
80762                     }
80763                   }
80764
80765                   offset = -span;
80766                 }
80767
80768                 a = b;
80769               }
80770             })));
80771             return segments;
80772           };
80773         }
80774         function svgPath(projection, graph, isArea) {
80775           // Explanation of magic numbers:
80776           // "padding" here allows space for strokes to extend beyond the viewport,
80777           // so that the stroke isn't drawn along the edge of the viewport when
80778           // the shape is clipped.
80779           //
80780           // When drawing lines, pad viewport by 5px.
80781           // When drawing areas, pad viewport by 65px in each direction to allow
80782           // for 60px area fill stroke (see ".fill-partial path.fill" css rule)
80783           var cache = {};
80784           var padding = isArea ? 65 : 5;
80785           var viewport = projection.clipExtent();
80786           var paddedExtent = [[viewport[0][0] - padding, viewport[0][1] - padding], [viewport[1][0] + padding, viewport[1][1] + padding]];
80787           var clip = d3_geoIdentity().clipExtent(paddedExtent).stream;
80788           var project = projection.stream;
80789           var path = d3_geoPath().projection({
80790             stream: function stream(output) {
80791               return project(clip(output));
80792             }
80793           });
80794
80795           var svgpath = function svgpath(entity) {
80796             if (entity.id in cache) {
80797               return cache[entity.id];
80798             } else {
80799               return cache[entity.id] = path(entity.asGeoJSON(graph));
80800             }
80801           };
80802
80803           svgpath.geojson = function (d) {
80804             if (d.__featurehash__ !== undefined) {
80805               if (d.__featurehash__ in cache) {
80806                 return cache[d.__featurehash__];
80807               } else {
80808                 return cache[d.__featurehash__] = path(d);
80809               }
80810             } else {
80811               return path(d);
80812             }
80813           };
80814
80815           return svgpath;
80816         }
80817         function svgPointTransform(projection) {
80818           var svgpoint = function svgpoint(entity) {
80819             // http://jsperf.com/short-array-join
80820             var pt = projection(entity.loc);
80821             return 'translate(' + pt[0] + ',' + pt[1] + ')';
80822           };
80823
80824           svgpoint.geojson = function (d) {
80825             return svgpoint(d.properties.entity);
80826           };
80827
80828           return svgpoint;
80829         }
80830         function svgRelationMemberTags(graph) {
80831           return function (entity) {
80832             var tags = entity.tags;
80833             var shouldCopyMultipolygonTags = !entity.hasInterestingTags();
80834             graph.parentRelations(entity).forEach(function (relation) {
80835               var type = relation.tags.type;
80836
80837               if (type === 'multipolygon' && shouldCopyMultipolygonTags || type === 'boundary') {
80838                 tags = Object.assign({}, relation.tags, tags);
80839               }
80840             });
80841             return tags;
80842           };
80843         }
80844         function svgSegmentWay(way, graph, activeID) {
80845           // When there is no activeID, we can memoize this expensive computation
80846           if (activeID === undefined) {
80847             return graph["transient"](way, 'waySegments', getWaySegments);
80848           } else {
80849             return getWaySegments();
80850           }
80851
80852           function getWaySegments() {
80853             var isActiveWay = way.nodes.indexOf(activeID) !== -1;
80854             var features = {
80855               passive: [],
80856               active: []
80857             };
80858             var start = {};
80859             var end = {};
80860             var node, type;
80861
80862             for (var i = 0; i < way.nodes.length; i++) {
80863               node = graph.entity(way.nodes[i]);
80864               type = svgPassiveVertex(node, graph, activeID);
80865               end = {
80866                 node: node,
80867                 type: type
80868               };
80869
80870               if (start.type !== undefined) {
80871                 if (start.node.id === activeID || end.node.id === activeID) ; else if (isActiveWay && (start.type === 2 || end.type === 2)) {
80872                   // one adjacent vertex
80873                   pushActive(start, end, i);
80874                 } else if (start.type === 0 && end.type === 0) {
80875                   // both active vertices
80876                   pushActive(start, end, i);
80877                 } else {
80878                   pushPassive(start, end, i);
80879                 }
80880               }
80881
80882               start = end;
80883             }
80884
80885             return features;
80886
80887             function pushActive(start, end, index) {
80888               features.active.push({
80889                 type: 'Feature',
80890                 id: way.id + '-' + index + '-nope',
80891                 properties: {
80892                   nope: true,
80893                   target: true,
80894                   entity: way,
80895                   nodes: [start.node, end.node],
80896                   index: index
80897                 },
80898                 geometry: {
80899                   type: 'LineString',
80900                   coordinates: [start.node.loc, end.node.loc]
80901                 }
80902               });
80903             }
80904
80905             function pushPassive(start, end, index) {
80906               features.passive.push({
80907                 type: 'Feature',
80908                 id: way.id + '-' + index,
80909                 properties: {
80910                   target: true,
80911                   entity: way,
80912                   nodes: [start.node, end.node],
80913                   index: index
80914                 },
80915                 geometry: {
80916                   type: 'LineString',
80917                   coordinates: [start.node.loc, end.node.loc]
80918                 }
80919               });
80920             }
80921           }
80922         }
80923
80924         function svgTagClasses() {
80925           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'];
80926           var statuses = [// nonexistent, might be built
80927           'proposed', 'planned', // under maintentance or between groundbreaking and opening
80928           'construction', // existent but not functional
80929           'disused', // dilapidated to nonexistent
80930           'abandoned', // nonexistent, still may appear in imagery
80931           'dismantled', 'razed', 'demolished', 'obliterated', // existent occasionally, e.g. stormwater drainage basin
80932           'intermittent'];
80933           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'];
80934
80935           var _tags = function _tags(entity) {
80936             return entity.tags;
80937           };
80938
80939           var tagClasses = function tagClasses(selection) {
80940             selection.each(function tagClassesEach(entity) {
80941               var value = this.className;
80942
80943               if (value.baseVal !== undefined) {
80944                 value = value.baseVal;
80945               }
80946
80947               var t = _tags(entity);
80948
80949               var computed = tagClasses.getClassesString(t, value);
80950
80951               if (computed !== value) {
80952                 select(this).attr('class', computed);
80953               }
80954             });
80955           };
80956
80957           tagClasses.getClassesString = function (t, value) {
80958             var primary, status;
80959             var i, j, k, v; // in some situations we want to render perimeter strokes a certain way
80960
80961             var overrideGeometry;
80962
80963             if (/\bstroke\b/.test(value)) {
80964               if (!!t.barrier && t.barrier !== 'no') {
80965                 overrideGeometry = 'line';
80966               }
80967             } // preserve base classes (nothing with `tag-`)
80968
80969
80970             var classes = value.trim().split(/\s+/).filter(function (klass) {
80971               return klass.length && !/^tag-/.test(klass);
80972             }).map(function (klass) {
80973               // special overrides for some perimeter strokes
80974               return klass === 'line' || klass === 'area' ? overrideGeometry || klass : klass;
80975             }); // pick at most one primary classification tag..
80976
80977             for (i = 0; i < primaries.length; i++) {
80978               k = primaries[i];
80979               v = t[k];
80980               if (!v || v === 'no') continue;
80981
80982               if (k === 'piste:type') {
80983                 // avoid a ':' in the class name
80984                 k = 'piste';
80985               } else if (k === 'building:part') {
80986                 // avoid a ':' in the class name
80987                 k = 'building_part';
80988               }
80989
80990               primary = k;
80991
80992               if (statuses.indexOf(v) !== -1) {
80993                 // e.g. `railway=abandoned`
80994                 status = v;
80995                 classes.push('tag-' + k);
80996               } else {
80997                 classes.push('tag-' + k);
80998                 classes.push('tag-' + k + '-' + v);
80999               }
81000
81001               break;
81002             }
81003
81004             if (!primary) {
81005               for (i = 0; i < statuses.length; i++) {
81006                 for (j = 0; j < primaries.length; j++) {
81007                   k = statuses[i] + ':' + primaries[j]; // e.g. `demolished:building=yes`
81008
81009                   v = t[k];
81010                   if (!v || v === 'no') continue;
81011                   status = statuses[i];
81012                   break;
81013                 }
81014               }
81015             } // add at most one status tag, only if relates to primary tag..
81016
81017
81018             if (!status) {
81019               for (i = 0; i < statuses.length; i++) {
81020                 k = statuses[i];
81021                 v = t[k];
81022                 if (!v || v === 'no') continue;
81023
81024                 if (v === 'yes') {
81025                   // e.g. `railway=rail + abandoned=yes`
81026                   status = k;
81027                 } else if (primary && primary === v) {
81028                   // e.g. `railway=rail + abandoned=railway`
81029                   status = k;
81030                 } else if (!primary && primaries.indexOf(v) !== -1) {
81031                   // e.g. `abandoned=railway`
81032                   status = k;
81033                   primary = v;
81034                   classes.push('tag-' + v);
81035                 } // else ignore e.g.  `highway=path + abandoned=railway`
81036
81037
81038                 if (status) break;
81039               }
81040             }
81041
81042             if (status) {
81043               classes.push('tag-status');
81044               classes.push('tag-status-' + status);
81045             } // add any secondary tags
81046
81047
81048             for (i = 0; i < secondaries.length; i++) {
81049               k = secondaries[i];
81050               v = t[k];
81051               if (!v || v === 'no' || k === primary) continue;
81052               classes.push('tag-' + k);
81053               classes.push('tag-' + k + '-' + v);
81054             } // For highways, look for surface tagging..
81055
81056
81057             if (primary === 'highway' && !osmPathHighwayTagValues[t.highway] || primary === 'aeroway') {
81058               var surface = t.highway === 'track' ? 'unpaved' : 'paved';
81059
81060               for (k in t) {
81061                 v = t[k];
81062
81063                 if (k in osmPavedTags) {
81064                   surface = osmPavedTags[k][v] ? 'paved' : 'unpaved';
81065                 }
81066
81067                 if (k in osmSemipavedTags && !!osmSemipavedTags[k][v]) {
81068                   surface = 'semipaved';
81069                 }
81070               }
81071
81072               classes.push('tag-' + surface);
81073             } // If this is a wikidata-tagged item, add a class for that..
81074
81075
81076             var qid = t.wikidata || t['flag:wikidata'] || t['brand:wikidata'] || t['network:wikidata'] || t['operator:wikidata'];
81077
81078             if (qid) {
81079               classes.push('tag-wikidata');
81080             }
81081
81082             return classes.join(' ').trim();
81083           };
81084
81085           tagClasses.tags = function (val) {
81086             if (!arguments.length) return _tags;
81087             _tags = val;
81088             return tagClasses;
81089           };
81090
81091           return tagClasses;
81092         }
81093
81094         // Patterns only work in Firefox when set directly on element.
81095         // (This is not a bug: https://bugzilla.mozilla.org/show_bug.cgi?id=750632)
81096         var patterns = {
81097           // tag - pattern name
81098           // -or-
81099           // tag - value - pattern name
81100           // -or-
81101           // tag - value - rules (optional tag-values, pattern name)
81102           // (matches earlier rules first, so fallback should be last entry)
81103           amenity: {
81104             grave_yard: 'cemetery',
81105             fountain: 'water_standing'
81106           },
81107           landuse: {
81108             cemetery: [{
81109               religion: 'christian',
81110               pattern: 'cemetery_christian'
81111             }, {
81112               religion: 'buddhist',
81113               pattern: 'cemetery_buddhist'
81114             }, {
81115               religion: 'muslim',
81116               pattern: 'cemetery_muslim'
81117             }, {
81118               religion: 'jewish',
81119               pattern: 'cemetery_jewish'
81120             }, {
81121               pattern: 'cemetery'
81122             }],
81123             construction: 'construction',
81124             farmland: 'farmland',
81125             farmyard: 'farmyard',
81126             forest: [{
81127               leaf_type: 'broadleaved',
81128               pattern: 'forest_broadleaved'
81129             }, {
81130               leaf_type: 'needleleaved',
81131               pattern: 'forest_needleleaved'
81132             }, {
81133               leaf_type: 'leafless',
81134               pattern: 'forest_leafless'
81135             }, {
81136               pattern: 'forest'
81137             } // same as 'leaf_type:mixed'
81138             ],
81139             grave_yard: 'cemetery',
81140             grass: [{
81141               golf: 'green',
81142               pattern: 'golf_green'
81143             }, {
81144               pattern: 'grass'
81145             }],
81146             landfill: 'landfill',
81147             meadow: 'meadow',
81148             military: 'construction',
81149             orchard: 'orchard',
81150             quarry: 'quarry',
81151             vineyard: 'vineyard'
81152           },
81153           natural: {
81154             beach: 'beach',
81155             grassland: 'grass',
81156             sand: 'beach',
81157             scrub: 'scrub',
81158             water: [{
81159               water: 'pond',
81160               pattern: 'pond'
81161             }, {
81162               water: 'reservoir',
81163               pattern: 'water_standing'
81164             }, {
81165               pattern: 'waves'
81166             }],
81167             wetland: [{
81168               wetland: 'marsh',
81169               pattern: 'wetland_marsh'
81170             }, {
81171               wetland: 'swamp',
81172               pattern: 'wetland_swamp'
81173             }, {
81174               wetland: 'bog',
81175               pattern: 'wetland_bog'
81176             }, {
81177               wetland: 'reedbed',
81178               pattern: 'wetland_reedbed'
81179             }, {
81180               pattern: 'wetland'
81181             }],
81182             wood: [{
81183               leaf_type: 'broadleaved',
81184               pattern: 'forest_broadleaved'
81185             }, {
81186               leaf_type: 'needleleaved',
81187               pattern: 'forest_needleleaved'
81188             }, {
81189               leaf_type: 'leafless',
81190               pattern: 'forest_leafless'
81191             }, {
81192               pattern: 'forest'
81193             } // same as 'leaf_type:mixed'
81194             ]
81195           },
81196           traffic_calming: {
81197             island: [{
81198               surface: 'grass',
81199               pattern: 'grass'
81200             }],
81201             chicane: [{
81202               surface: 'grass',
81203               pattern: 'grass'
81204             }],
81205             choker: [{
81206               surface: 'grass',
81207               pattern: 'grass'
81208             }]
81209           }
81210         };
81211         function svgTagPattern(tags) {
81212           // Skip pattern filling if this is a building (buildings don't get patterns applied)
81213           if (tags.building && tags.building !== 'no') {
81214             return null;
81215           }
81216
81217           for (var tag in patterns) {
81218             var entityValue = tags[tag];
81219             if (!entityValue) continue;
81220
81221             if (typeof patterns[tag] === 'string') {
81222               // extra short syntax (just tag) - pattern name
81223               return 'pattern-' + patterns[tag];
81224             } else {
81225               var values = patterns[tag];
81226
81227               for (var value in values) {
81228                 if (entityValue !== value) continue;
81229                 var rules = values[value];
81230
81231                 if (typeof rules === 'string') {
81232                   // short syntax - pattern name
81233                   return 'pattern-' + rules;
81234                 } // long syntax - rule array
81235
81236
81237                 for (var ruleKey in rules) {
81238                   var rule = rules[ruleKey];
81239                   var pass = true;
81240
81241                   for (var criterion in rule) {
81242                     if (criterion !== 'pattern') {
81243                       // reserved for pattern name
81244                       // The only rule is a required tag-value pair
81245                       var v = tags[criterion];
81246
81247                       if (!v || v !== rule[criterion]) {
81248                         pass = false;
81249                         break;
81250                       }
81251                     }
81252                   }
81253
81254                   if (pass) {
81255                     return 'pattern-' + rule.pattern;
81256                   }
81257                 }
81258               }
81259             }
81260           }
81261
81262           return null;
81263         }
81264
81265         function svgAreas(projection, context) {
81266           function getPatternStyle(tags) {
81267             var imageID = svgTagPattern(tags);
81268
81269             if (imageID) {
81270               return 'url("#ideditor-' + imageID + '")';
81271             }
81272
81273             return '';
81274           }
81275
81276           function drawTargets(selection, graph, entities, filter) {
81277             var targetClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
81278             var nopeClass = context.getDebug('target') ? 'red ' : 'nocolor ';
81279             var getPath = svgPath(projection).geojson;
81280             var activeID = context.activeID();
81281             var base = context.history().base(); // The targets and nopes will be MultiLineString sub-segments of the ways
81282
81283             var data = {
81284               targets: [],
81285               nopes: []
81286             };
81287             entities.forEach(function (way) {
81288               var features = svgSegmentWay(way, graph, activeID);
81289               data.targets.push.apply(data.targets, features.passive);
81290               data.nopes.push.apply(data.nopes, features.active);
81291             }); // Targets allow hover and vertex snapping
81292
81293             var targetData = data.targets.filter(getPath);
81294             var targets = selection.selectAll('.area.target-allowed').filter(function (d) {
81295               return filter(d.properties.entity);
81296             }).data(targetData, function key(d) {
81297               return d.id;
81298             }); // exit
81299
81300             targets.exit().remove();
81301
81302             var segmentWasEdited = function segmentWasEdited(d) {
81303               var wayID = d.properties.entity.id; // if the whole line was edited, don't draw segment changes
81304
81305               if (!base.entities[wayID] || !fastDeepEqual(graph.entities[wayID].nodes, base.entities[wayID].nodes)) {
81306                 return false;
81307               }
81308
81309               return d.properties.nodes.some(function (n) {
81310                 return !base.entities[n.id] || !fastDeepEqual(graph.entities[n.id].loc, base.entities[n.id].loc);
81311               });
81312             }; // enter/update
81313
81314
81315             targets.enter().append('path').merge(targets).attr('d', getPath).attr('class', function (d) {
81316               return 'way area target target-allowed ' + targetClass + d.id;
81317             }).classed('segment-edited', segmentWasEdited); // NOPE
81318
81319             var nopeData = data.nopes.filter(getPath);
81320             var nopes = selection.selectAll('.area.target-nope').filter(function (d) {
81321               return filter(d.properties.entity);
81322             }).data(nopeData, function key(d) {
81323               return d.id;
81324             }); // exit
81325
81326             nopes.exit().remove(); // enter/update
81327
81328             nopes.enter().append('path').merge(nopes).attr('d', getPath).attr('class', function (d) {
81329               return 'way area target target-nope ' + nopeClass + d.id;
81330             }).classed('segment-edited', segmentWasEdited);
81331           }
81332
81333           function drawAreas(selection, graph, entities, filter) {
81334             var path = svgPath(projection, graph, true);
81335             var areas = {};
81336             var multipolygon;
81337             var base = context.history().base();
81338
81339             for (var i = 0; i < entities.length; i++) {
81340               var entity = entities[i];
81341               if (entity.geometry(graph) !== 'area') continue;
81342               multipolygon = osmIsOldMultipolygonOuterMember(entity, graph);
81343
81344               if (multipolygon) {
81345                 areas[multipolygon.id] = {
81346                   entity: multipolygon.mergeTags(entity.tags),
81347                   area: Math.abs(entity.area(graph))
81348                 };
81349               } else if (!areas[entity.id]) {
81350                 areas[entity.id] = {
81351                   entity: entity,
81352                   area: Math.abs(entity.area(graph))
81353                 };
81354               }
81355             }
81356
81357             var fills = Object.values(areas).filter(function hasPath(a) {
81358               return path(a.entity);
81359             });
81360             fills.sort(function areaSort(a, b) {
81361               return b.area - a.area;
81362             });
81363             fills = fills.map(function (a) {
81364               return a.entity;
81365             });
81366             var strokes = fills.filter(function (area) {
81367               return area.type === 'way';
81368             });
81369             var data = {
81370               clip: fills,
81371               shadow: strokes,
81372               stroke: strokes,
81373               fill: fills
81374             };
81375             var clipPaths = context.surface().selectAll('defs').selectAll('.clipPath-osm').filter(filter).data(data.clip, osmEntity.key);
81376             clipPaths.exit().remove();
81377             var clipPathsEnter = clipPaths.enter().append('clipPath').attr('class', 'clipPath-osm').attr('id', function (entity) {
81378               return 'ideditor-' + entity.id + '-clippath';
81379             });
81380             clipPathsEnter.append('path');
81381             clipPaths.merge(clipPathsEnter).selectAll('path').attr('d', path);
81382             var drawLayer = selection.selectAll('.layer-osm.areas');
81383             var touchLayer = selection.selectAll('.layer-touch.areas'); // Draw areas..
81384
81385             var areagroup = drawLayer.selectAll('g.areagroup').data(['fill', 'shadow', 'stroke']);
81386             areagroup = areagroup.enter().append('g').attr('class', function (d) {
81387               return 'areagroup area-' + d;
81388             }).merge(areagroup);
81389             var paths = areagroup.selectAll('path').filter(filter).data(function (layer) {
81390               return data[layer];
81391             }, osmEntity.key);
81392             paths.exit().remove();
81393             var fillpaths = selection.selectAll('.area-fill path.area').nodes();
81394             var bisect = d3_bisector(function (node) {
81395               return -node.__data__.area(graph);
81396             }).left;
81397
81398             function sortedByArea(entity) {
81399               if (this._parent.__data__ === 'fill') {
81400                 return fillpaths[bisect(fillpaths, -entity.area(graph))];
81401               }
81402             }
81403
81404             paths = paths.enter().insert('path', sortedByArea).merge(paths).each(function (entity) {
81405               var layer = this.parentNode.__data__;
81406               this.setAttribute('class', entity.type + ' area ' + layer + ' ' + entity.id);
81407
81408               if (layer === 'fill') {
81409                 this.setAttribute('clip-path', 'url(#ideditor-' + entity.id + '-clippath)');
81410                 this.style.fill = this.style.stroke = getPatternStyle(entity.tags);
81411               }
81412             }).classed('added', function (d) {
81413               return !base.entities[d.id];
81414             }).classed('geometry-edited', function (d) {
81415               return graph.entities[d.id] && base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].nodes, base.entities[d.id].nodes);
81416             }).classed('retagged', function (d) {
81417               return graph.entities[d.id] && base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].tags, base.entities[d.id].tags);
81418             }).call(svgTagClasses()).attr('d', path); // Draw touch targets..
81419
81420             touchLayer.call(drawTargets, graph, data.stroke, filter);
81421           }
81422
81423           return drawAreas;
81424         }
81425
81426         var fastJsonStableStringify = function fastJsonStableStringify(data, opts) {
81427           if (!opts) opts = {};
81428           if (typeof opts === 'function') opts = {
81429             cmp: opts
81430           };
81431           var cycles = typeof opts.cycles === 'boolean' ? opts.cycles : false;
81432
81433           var cmp = opts.cmp && function (f) {
81434             return function (node) {
81435               return function (a, b) {
81436                 var aobj = {
81437                   key: a,
81438                   value: node[a]
81439                 };
81440                 var bobj = {
81441                   key: b,
81442                   value: node[b]
81443                 };
81444                 return f(aobj, bobj);
81445               };
81446             };
81447           }(opts.cmp);
81448
81449           var seen = [];
81450           return function stringify(node) {
81451             if (node && node.toJSON && typeof node.toJSON === 'function') {
81452               node = node.toJSON();
81453             }
81454
81455             if (node === undefined) return;
81456             if (typeof node == 'number') return isFinite(node) ? '' + node : 'null';
81457             if (_typeof(node) !== 'object') return JSON.stringify(node);
81458             var i, out;
81459
81460             if (Array.isArray(node)) {
81461               out = '[';
81462
81463               for (i = 0; i < node.length; i++) {
81464                 if (i) out += ',';
81465                 out += stringify(node[i]) || 'null';
81466               }
81467
81468               return out + ']';
81469             }
81470
81471             if (node === null) return 'null';
81472
81473             if (seen.indexOf(node) !== -1) {
81474               if (cycles) return JSON.stringify('__cycle__');
81475               throw new TypeError('Converting circular structure to JSON');
81476             }
81477
81478             var seenIndex = seen.push(node) - 1;
81479             var keys = Object.keys(node).sort(cmp && cmp(node));
81480             out = '';
81481
81482             for (i = 0; i < keys.length; i++) {
81483               var key = keys[i];
81484               var value = stringify(node[key]);
81485               if (!value) continue;
81486               if (out) out += ',';
81487               out += JSON.stringify(key) + ':' + value;
81488             }
81489
81490             seen.splice(seenIndex, 1);
81491             return '{' + out + '}';
81492           }(data);
81493         };
81494
81495         var $$1 = _export;
81496         var $entries = objectToArray.entries;
81497
81498         // `Object.entries` method
81499         // https://tc39.es/ecma262/#sec-object.entries
81500         $$1({ target: 'Object', stat: true }, {
81501           entries: function entries(O) {
81502             return $entries(O);
81503           }
81504         });
81505
81506         var _marked = /*#__PURE__*/regeneratorRuntime.mark(gpxGen),
81507             _marked3 = /*#__PURE__*/regeneratorRuntime.mark(kmlGen);
81508
81509         // cast array x into numbers
81510         // get the content of a text node, if any
81511         function nodeVal(x) {
81512           if (x && x.normalize) {
81513             x.normalize();
81514           }
81515
81516           return x && x.textContent || "";
81517         } // one Y child of X, if any, otherwise null
81518
81519
81520         function get1(x, y) {
81521           var n = x.getElementsByTagName(y);
81522           return n.length ? n[0] : null;
81523         }
81524
81525         function getLineStyle(extensions) {
81526           var style = {};
81527
81528           if (extensions) {
81529             var lineStyle = get1(extensions, "line");
81530
81531             if (lineStyle) {
81532               var color = nodeVal(get1(lineStyle, "color")),
81533                   opacity = parseFloat(nodeVal(get1(lineStyle, "opacity"))),
81534                   width = parseFloat(nodeVal(get1(lineStyle, "width")));
81535               if (color) style.stroke = color;
81536               if (!isNaN(opacity)) style["stroke-opacity"] = opacity; // GPX width is in mm, convert to px with 96 px per inch
81537
81538               if (!isNaN(width)) style["stroke-width"] = width * 96 / 25.4;
81539             }
81540           }
81541
81542           return style;
81543         } // get the contents of multiple text nodes, if present
81544
81545
81546         function getMulti(x, ys) {
81547           var o = {};
81548           var n;
81549           var k;
81550
81551           for (k = 0; k < ys.length; k++) {
81552             n = get1(x, ys[k]);
81553             if (n) o[ys[k]] = nodeVal(n);
81554           }
81555
81556           return o;
81557         }
81558
81559         function getProperties$1(node) {
81560           var prop = getMulti(node, ["name", "cmt", "desc", "type", "time", "keywords"]); // Parse additional data from our Garmin extension(s)
81561
81562           var extensions = node.getElementsByTagNameNS("http://www.garmin.com/xmlschemas/GpxExtensions/v3", "*");
81563
81564           for (var i = 0; i < extensions.length; i++) {
81565             var extension = extensions[i]; // Ignore nested extensions, like those on routepoints or trackpoints
81566
81567             if (extension.parentNode.parentNode === node) {
81568               prop[extension.tagName.replace(":", "_")] = nodeVal(extension);
81569             }
81570           }
81571
81572           var links = node.getElementsByTagName("link");
81573           if (links.length) prop.links = [];
81574
81575           for (var _i = 0; _i < links.length; _i++) {
81576             prop.links.push(Object.assign({
81577               href: links[_i].getAttribute("href")
81578             }, getMulti(links[_i], ["text", "type"])));
81579           }
81580
81581           return prop;
81582         }
81583
81584         function coordPair$1(x) {
81585           var ll = [parseFloat(x.getAttribute("lon")), parseFloat(x.getAttribute("lat"))];
81586           var ele = get1(x, "ele"); // handle namespaced attribute in browser
81587
81588           var heart = get1(x, "gpxtpx:hr") || get1(x, "hr");
81589           var time = get1(x, "time");
81590           var e;
81591
81592           if (ele) {
81593             e = parseFloat(nodeVal(ele));
81594
81595             if (!isNaN(e)) {
81596               ll.push(e);
81597             }
81598           }
81599
81600           var result = {
81601             coordinates: ll,
81602             time: time ? nodeVal(time) : null,
81603             extendedValues: []
81604           };
81605
81606           if (heart) {
81607             result.extendedValues.push(["heart", parseFloat(nodeVal(heart))]);
81608           }
81609
81610           var extensions = get1(x, "extensions");
81611
81612           if (extensions !== null) {
81613             for (var _i2 = 0, _arr = ["speed", "course", "hAcc", "vAcc"]; _i2 < _arr.length; _i2++) {
81614               var name = _arr[_i2];
81615               var v = parseFloat(nodeVal(get1(extensions, name)));
81616
81617               if (!isNaN(v)) {
81618                 result.extendedValues.push([name, v]);
81619               }
81620             }
81621           }
81622
81623           return result;
81624         }
81625
81626         function getRoute(node) {
81627           var line = getPoints$1(node, "rtept");
81628           if (!line) return;
81629           return {
81630             type: "Feature",
81631             properties: Object.assign(getProperties$1(node), getLineStyle(get1(node, "extensions")), {
81632               _gpxType: "rte"
81633             }),
81634             geometry: {
81635               type: "LineString",
81636               coordinates: line.line
81637             }
81638           };
81639         }
81640
81641         function getPoints$1(node, pointname) {
81642           var pts = node.getElementsByTagName(pointname);
81643           if (pts.length < 2) return; // Invalid line in GeoJSON
81644
81645           var line = [];
81646           var times = [];
81647           var extendedValues = {};
81648
81649           for (var i = 0; i < pts.length; i++) {
81650             var c = coordPair$1(pts[i]);
81651             line.push(c.coordinates);
81652             if (c.time) times.push(c.time);
81653
81654             for (var j = 0; j < c.extendedValues.length; j++) {
81655               var _c$extendedValues$j = _slicedToArray(c.extendedValues[j], 2),
81656                   name = _c$extendedValues$j[0],
81657                   val = _c$extendedValues$j[1];
81658
81659               var plural = name === "heart" ? name : name + "s";
81660
81661               if (!extendedValues[plural]) {
81662                 extendedValues[plural] = Array(pts.length).fill(null);
81663               }
81664
81665               extendedValues[plural][i] = val;
81666             }
81667           }
81668
81669           return {
81670             line: line,
81671             times: times,
81672             extendedValues: extendedValues
81673           };
81674         }
81675
81676         function getTrack(node) {
81677           var segments = node.getElementsByTagName("trkseg");
81678           var track = [];
81679           var times = [];
81680           var extractedLines = [];
81681
81682           for (var i = 0; i < segments.length; i++) {
81683             var line = getPoints$1(segments[i], "trkpt");
81684
81685             if (line) {
81686               extractedLines.push(line);
81687               if (line.times && line.times.length) times.push(line.times);
81688             }
81689           }
81690
81691           if (extractedLines.length === 0) return;
81692           var multi = extractedLines.length > 1;
81693           var properties = Object.assign(getProperties$1(node), getLineStyle(get1(node, "extensions")), {
81694             _gpxType: "trk"
81695           }, times.length ? {
81696             coordinateProperties: {
81697               times: multi ? times : times[0]
81698             }
81699           } : {});
81700
81701           for (var _i3 = 0; _i3 < extractedLines.length; _i3++) {
81702             var _line = extractedLines[_i3];
81703             track.push(_line.line);
81704
81705             for (var _i4 = 0, _Object$entries = Object.entries(_line.extendedValues); _i4 < _Object$entries.length; _i4++) {
81706               var _Object$entries$_i = _slicedToArray(_Object$entries[_i4], 2),
81707                   name = _Object$entries$_i[0],
81708                   val = _Object$entries$_i[1];
81709
81710               var props = properties;
81711
81712               if (name === "heart") {
81713                 if (!properties.coordinateProperties) {
81714                   properties.coordinateProperties = {};
81715                 }
81716
81717                 props = properties.coordinateProperties;
81718               }
81719
81720               if (multi) {
81721                 if (!props[name]) props[name] = extractedLines.map(function (line) {
81722                   return new Array(line.line.length).fill(null);
81723                 });
81724                 props[name][_i3] = val;
81725               } else {
81726                 props[name] = val;
81727               }
81728             }
81729           }
81730
81731           return {
81732             type: "Feature",
81733             properties: properties,
81734             geometry: multi ? {
81735               type: "MultiLineString",
81736               coordinates: track
81737             } : {
81738               type: "LineString",
81739               coordinates: track[0]
81740             }
81741           };
81742         }
81743
81744         function getPoint(node) {
81745           return {
81746             type: "Feature",
81747             properties: Object.assign(getProperties$1(node), getMulti(node, ["sym"])),
81748             geometry: {
81749               type: "Point",
81750               coordinates: coordPair$1(node).coordinates
81751             }
81752           };
81753         }
81754
81755         function gpxGen(doc) {
81756           var tracks, routes, waypoints, i, feature, _i5, _feature, _i6;
81757
81758           return regeneratorRuntime.wrap(function gpxGen$(_context) {
81759             while (1) {
81760               switch (_context.prev = _context.next) {
81761                 case 0:
81762                   tracks = doc.getElementsByTagName("trk");
81763                   routes = doc.getElementsByTagName("rte");
81764                   waypoints = doc.getElementsByTagName("wpt");
81765                   i = 0;
81766
81767                 case 4:
81768                   if (!(i < tracks.length)) {
81769                     _context.next = 12;
81770                     break;
81771                   }
81772
81773                   feature = getTrack(tracks[i]);
81774
81775                   if (!feature) {
81776                     _context.next = 9;
81777                     break;
81778                   }
81779
81780                   _context.next = 9;
81781                   return feature;
81782
81783                 case 9:
81784                   i++;
81785                   _context.next = 4;
81786                   break;
81787
81788                 case 12:
81789                   _i5 = 0;
81790
81791                 case 13:
81792                   if (!(_i5 < routes.length)) {
81793                     _context.next = 21;
81794                     break;
81795                   }
81796
81797                   _feature = getRoute(routes[_i5]);
81798
81799                   if (!_feature) {
81800                     _context.next = 18;
81801                     break;
81802                   }
81803
81804                   _context.next = 18;
81805                   return _feature;
81806
81807                 case 18:
81808                   _i5++;
81809                   _context.next = 13;
81810                   break;
81811
81812                 case 21:
81813                   _i6 = 0;
81814
81815                 case 22:
81816                   if (!(_i6 < waypoints.length)) {
81817                     _context.next = 28;
81818                     break;
81819                   }
81820
81821                   _context.next = 25;
81822                   return getPoint(waypoints[_i6]);
81823
81824                 case 25:
81825                   _i6++;
81826                   _context.next = 22;
81827                   break;
81828
81829                 case 28:
81830                 case "end":
81831                   return _context.stop();
81832               }
81833             }
81834           }, _marked);
81835         }
81836
81837         function gpx(doc) {
81838           return {
81839             type: "FeatureCollection",
81840             features: Array.from(gpxGen(doc))
81841           };
81842         }
81843
81844         var removeSpace = /\s*/g;
81845         var trimSpace = /^\s*|\s*$/g;
81846         var splitSpace = /\s+/; // generate a short, numeric hash of a string
81847
81848         function okhash(x) {
81849           if (!x || !x.length) return 0;
81850           var h = 0;
81851
81852           for (var i = 0; i < x.length; i++) {
81853             h = (h << 5) - h + x.charCodeAt(i) | 0;
81854           }
81855
81856           return h;
81857         } // get one coordinate from a coordinate array, if any
81858
81859
81860         function coord1(v) {
81861           return v.replace(removeSpace, "").split(",").map(parseFloat);
81862         } // get all coordinates from a coordinate array as [[],[]]
81863
81864
81865         function coord(v) {
81866           return v.replace(trimSpace, "").split(splitSpace).map(coord1);
81867         }
81868
81869         function xml2str(node) {
81870           if (node.xml !== undefined) return node.xml;
81871
81872           if (node.tagName) {
81873             var output = node.tagName;
81874
81875             for (var i = 0; i < node.attributes.length; i++) {
81876               output += node.attributes[i].name + node.attributes[i].value;
81877             }
81878
81879             for (var _i9 = 0; _i9 < node.childNodes.length; _i9++) {
81880               output += xml2str(node.childNodes[_i9]);
81881             }
81882
81883             return output;
81884           }
81885
81886           if (node.nodeName === "#text") {
81887             return (node.nodeValue || node.value || "").trim();
81888           }
81889
81890           if (node.nodeName === "#cdata-section") {
81891             return node.nodeValue;
81892           }
81893
81894           return "";
81895         }
81896
81897         var geotypes = ["Polygon", "LineString", "Point", "Track", "gx:Track"];
81898
81899         function kmlColor(properties, elem, prefix) {
81900           var v = nodeVal(get1(elem, "color")) || "";
81901           var colorProp = prefix == "stroke" || prefix === "fill" ? prefix : prefix + "-color";
81902
81903           if (v.substr(0, 1) === "#") {
81904             v = v.substr(1);
81905           }
81906
81907           if (v.length === 6 || v.length === 3) {
81908             properties[colorProp] = v;
81909           } else if (v.length === 8) {
81910             properties[prefix + "-opacity"] = parseInt(v.substr(0, 2), 16) / 255;
81911             properties[colorProp] = "#" + v.substr(6, 2) + v.substr(4, 2) + v.substr(2, 2);
81912           }
81913         }
81914
81915         function numericProperty(properties, elem, source, target) {
81916           var val = parseFloat(nodeVal(get1(elem, source)));
81917           if (!isNaN(val)) properties[target] = val;
81918         }
81919
81920         function gxCoords(root) {
81921           var elems = root.getElementsByTagName("coord");
81922           var coords = [];
81923           var times = [];
81924           if (elems.length === 0) elems = root.getElementsByTagName("gx:coord");
81925
81926           for (var i = 0; i < elems.length; i++) {
81927             coords.push(nodeVal(elems[i]).split(" ").map(parseFloat));
81928           }
81929
81930           var timeElems = root.getElementsByTagName("when");
81931
81932           for (var j = 0; j < timeElems.length; j++) {
81933             times.push(nodeVal(timeElems[j]));
81934           }
81935
81936           return {
81937             coords: coords,
81938             times: times
81939           };
81940         }
81941
81942         function getGeometry(root) {
81943           var geomNode;
81944           var geomNodes;
81945           var i;
81946           var j;
81947           var k;
81948           var geoms = [];
81949           var coordTimes = [];
81950
81951           if (get1(root, "MultiGeometry")) {
81952             return getGeometry(get1(root, "MultiGeometry"));
81953           }
81954
81955           if (get1(root, "MultiTrack")) {
81956             return getGeometry(get1(root, "MultiTrack"));
81957           }
81958
81959           if (get1(root, "gx:MultiTrack")) {
81960             return getGeometry(get1(root, "gx:MultiTrack"));
81961           }
81962
81963           for (i = 0; i < geotypes.length; i++) {
81964             geomNodes = root.getElementsByTagName(geotypes[i]);
81965
81966             if (geomNodes) {
81967               for (j = 0; j < geomNodes.length; j++) {
81968                 geomNode = geomNodes[j];
81969
81970                 if (geotypes[i] === "Point") {
81971                   geoms.push({
81972                     type: "Point",
81973                     coordinates: coord1(nodeVal(get1(geomNode, "coordinates")))
81974                   });
81975                 } else if (geotypes[i] === "LineString") {
81976                   geoms.push({
81977                     type: "LineString",
81978                     coordinates: coord(nodeVal(get1(geomNode, "coordinates")))
81979                   });
81980                 } else if (geotypes[i] === "Polygon") {
81981                   var rings = geomNode.getElementsByTagName("LinearRing"),
81982                       coords = [];
81983
81984                   for (k = 0; k < rings.length; k++) {
81985                     coords.push(coord(nodeVal(get1(rings[k], "coordinates"))));
81986                   }
81987
81988                   geoms.push({
81989                     type: "Polygon",
81990                     coordinates: coords
81991                   });
81992                 } else if (geotypes[i] === "Track" || geotypes[i] === "gx:Track") {
81993                   var track = gxCoords(geomNode);
81994                   geoms.push({
81995                     type: "LineString",
81996                     coordinates: track.coords
81997                   });
81998                   if (track.times.length) coordTimes.push(track.times);
81999                 }
82000               }
82001             }
82002           }
82003
82004           return {
82005             geoms: geoms,
82006             coordTimes: coordTimes
82007           };
82008         }
82009
82010         function getPlacemark(root, styleIndex, styleMapIndex, styleByHash) {
82011           var geomsAndTimes = getGeometry(root);
82012           var i;
82013           var properties = {};
82014           var name = nodeVal(get1(root, "name"));
82015           var address = nodeVal(get1(root, "address"));
82016           var styleUrl = nodeVal(get1(root, "styleUrl"));
82017           var description = nodeVal(get1(root, "description"));
82018           var timeSpan = get1(root, "TimeSpan");
82019           var timeStamp = get1(root, "TimeStamp");
82020           var extendedData = get1(root, "ExtendedData");
82021           var iconStyle = get1(root, "IconStyle");
82022           var labelStyle = get1(root, "LabelStyle");
82023           var lineStyle = get1(root, "LineStyle");
82024           var polyStyle = get1(root, "PolyStyle");
82025           var visibility = get1(root, "visibility");
82026           if (name) properties.name = name;
82027           if (address) properties.address = address;
82028
82029           if (styleUrl) {
82030             if (styleUrl[0] !== "#") {
82031               styleUrl = "#" + styleUrl;
82032             }
82033
82034             properties.styleUrl = styleUrl;
82035
82036             if (styleIndex[styleUrl]) {
82037               properties.styleHash = styleIndex[styleUrl];
82038             }
82039
82040             if (styleMapIndex[styleUrl]) {
82041               properties.styleMapHash = styleMapIndex[styleUrl];
82042               properties.styleHash = styleIndex[styleMapIndex[styleUrl].normal];
82043             } // Try to populate the lineStyle or polyStyle since we got the style hash
82044
82045
82046             var style = styleByHash[properties.styleHash];
82047
82048             if (style) {
82049               if (!iconStyle) iconStyle = get1(style, "IconStyle");
82050               if (!labelStyle) labelStyle = get1(style, "LabelStyle");
82051               if (!lineStyle) lineStyle = get1(style, "LineStyle");
82052               if (!polyStyle) polyStyle = get1(style, "PolyStyle");
82053             }
82054           }
82055
82056           if (description) properties.description = description;
82057
82058           if (timeSpan) {
82059             var begin = nodeVal(get1(timeSpan, "begin"));
82060             var end = nodeVal(get1(timeSpan, "end"));
82061             properties.timespan = {
82062               begin: begin,
82063               end: end
82064             };
82065           }
82066
82067           if (timeStamp) {
82068             properties.timestamp = nodeVal(get1(timeStamp, "when"));
82069           }
82070
82071           if (iconStyle) {
82072             kmlColor(properties, iconStyle, "icon");
82073             numericProperty(properties, iconStyle, "scale", "icon-scale");
82074             numericProperty(properties, iconStyle, "heading", "icon-heading");
82075             var hotspot = get1(iconStyle, "hotSpot");
82076
82077             if (hotspot) {
82078               var left = parseFloat(hotspot.getAttribute("x"));
82079               var top = parseFloat(hotspot.getAttribute("y"));
82080               if (!isNaN(left) && !isNaN(top)) properties["icon-offset"] = [left, top];
82081             }
82082
82083             var icon = get1(iconStyle, "Icon");
82084
82085             if (icon) {
82086               var href = nodeVal(get1(icon, "href"));
82087               if (href) properties.icon = href;
82088             }
82089           }
82090
82091           if (labelStyle) {
82092             kmlColor(properties, labelStyle, "label");
82093             numericProperty(properties, labelStyle, "scale", "label-scale");
82094           }
82095
82096           if (lineStyle) {
82097             kmlColor(properties, lineStyle, "stroke");
82098             numericProperty(properties, lineStyle, "width", "stroke-width");
82099           }
82100
82101           if (polyStyle) {
82102             kmlColor(properties, polyStyle, "fill");
82103             var fill = nodeVal(get1(polyStyle, "fill"));
82104             var outline = nodeVal(get1(polyStyle, "outline"));
82105             if (fill) properties["fill-opacity"] = fill === "1" ? properties["fill-opacity"] || 1 : 0;
82106             if (outline) properties["stroke-opacity"] = outline === "1" ? properties["stroke-opacity"] || 1 : 0;
82107           }
82108
82109           if (extendedData) {
82110             var datas = extendedData.getElementsByTagName("Data"),
82111                 simpleDatas = extendedData.getElementsByTagName("SimpleData");
82112
82113             for (i = 0; i < datas.length; i++) {
82114               properties[datas[i].getAttribute("name")] = nodeVal(get1(datas[i], "value"));
82115             }
82116
82117             for (i = 0; i < simpleDatas.length; i++) {
82118               properties[simpleDatas[i].getAttribute("name")] = nodeVal(simpleDatas[i]);
82119             }
82120           }
82121
82122           if (visibility) {
82123             properties.visibility = nodeVal(visibility);
82124           }
82125
82126           if (geomsAndTimes.coordTimes.length) {
82127             properties.coordinateProperties = {
82128               times: geomsAndTimes.coordTimes.length === 1 ? geomsAndTimes.coordTimes[0] : geomsAndTimes.coordTimes
82129             };
82130           }
82131
82132           var feature = {
82133             type: "Feature",
82134             geometry: geomsAndTimes.geoms.length === 0 ? null : geomsAndTimes.geoms.length === 1 ? geomsAndTimes.geoms[0] : {
82135               type: "GeometryCollection",
82136               geometries: geomsAndTimes.geoms
82137             },
82138             properties: properties
82139           };
82140           if (root.getAttribute("id")) feature.id = root.getAttribute("id");
82141           return feature;
82142         }
82143
82144         function kmlGen(doc) {
82145           var styleIndex, styleByHash, styleMapIndex, placemarks, styles, styleMaps, k, hash, l, pairs, pairsMap, m, j, feature;
82146           return regeneratorRuntime.wrap(function kmlGen$(_context3) {
82147             while (1) {
82148               switch (_context3.prev = _context3.next) {
82149                 case 0:
82150                   // styleindex keeps track of hashed styles in order to match feature
82151                   styleIndex = {};
82152                   styleByHash = {}; // stylemapindex keeps track of style maps to expose in properties
82153
82154                   styleMapIndex = {}; // atomic geospatial types supported by KML - MultiGeometry is
82155                   // handled separately
82156                   // all root placemarks in the file
82157
82158                   placemarks = doc.getElementsByTagName("Placemark");
82159                   styles = doc.getElementsByTagName("Style");
82160                   styleMaps = doc.getElementsByTagName("StyleMap");
82161
82162                   for (k = 0; k < styles.length; k++) {
82163                     hash = okhash(xml2str(styles[k])).toString(16);
82164                     styleIndex["#" + styles[k].getAttribute("id")] = hash;
82165                     styleByHash[hash] = styles[k];
82166                   }
82167
82168                   for (l = 0; l < styleMaps.length; l++) {
82169                     styleIndex["#" + styleMaps[l].getAttribute("id")] = okhash(xml2str(styleMaps[l])).toString(16);
82170                     pairs = styleMaps[l].getElementsByTagName("Pair");
82171                     pairsMap = {};
82172
82173                     for (m = 0; m < pairs.length; m++) {
82174                       pairsMap[nodeVal(get1(pairs[m], "key"))] = nodeVal(get1(pairs[m], "styleUrl"));
82175                     }
82176
82177                     styleMapIndex["#" + styleMaps[l].getAttribute("id")] = pairsMap;
82178                   }
82179
82180                   j = 0;
82181
82182                 case 9:
82183                   if (!(j < placemarks.length)) {
82184                     _context3.next = 17;
82185                     break;
82186                   }
82187
82188                   feature = getPlacemark(placemarks[j], styleIndex, styleMapIndex, styleByHash);
82189
82190                   if (!feature) {
82191                     _context3.next = 14;
82192                     break;
82193                   }
82194
82195                   _context3.next = 14;
82196                   return feature;
82197
82198                 case 14:
82199                   j++;
82200                   _context3.next = 9;
82201                   break;
82202
82203                 case 17:
82204                 case "end":
82205                   return _context3.stop();
82206               }
82207             }
82208           }, _marked3);
82209         }
82210
82211         function kml(doc) {
82212           return {
82213             type: "FeatureCollection",
82214             features: Array.from(kmlGen(doc))
82215           };
82216         }
82217
82218         var _initialized = false;
82219         var _enabled = false;
82220
82221         var _geojson;
82222
82223         function svgData(projection, context, dispatch) {
82224           var throttledRedraw = throttle(function () {
82225             dispatch.call('change');
82226           }, 1000);
82227
82228           var _showLabels = true;
82229           var detected = utilDetect();
82230           var layer = select(null);
82231
82232           var _vtService;
82233
82234           var _fileList;
82235
82236           var _template;
82237
82238           var _src;
82239
82240           function init() {
82241             if (_initialized) return; // run once
82242
82243             _geojson = {};
82244             _enabled = true;
82245
82246             function over(d3_event) {
82247               d3_event.stopPropagation();
82248               d3_event.preventDefault();
82249               d3_event.dataTransfer.dropEffect = 'copy';
82250             }
82251
82252             context.container().attr('dropzone', 'copy').on('drop.svgData', function (d3_event) {
82253               d3_event.stopPropagation();
82254               d3_event.preventDefault();
82255               if (!detected.filedrop) return;
82256               drawData.fileList(d3_event.dataTransfer.files);
82257             }).on('dragenter.svgData', over).on('dragexit.svgData', over).on('dragover.svgData', over);
82258             _initialized = true;
82259           }
82260
82261           function getService() {
82262             if (services.vectorTile && !_vtService) {
82263               _vtService = services.vectorTile;
82264
82265               _vtService.event.on('loadedData', throttledRedraw);
82266             } else if (!services.vectorTile && _vtService) {
82267               _vtService = null;
82268             }
82269
82270             return _vtService;
82271           }
82272
82273           function showLayer() {
82274             layerOn();
82275             layer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end', function () {
82276               dispatch.call('change');
82277             });
82278           }
82279
82280           function hideLayer() {
82281             throttledRedraw.cancel();
82282             layer.transition().duration(250).style('opacity', 0).on('end', layerOff);
82283           }
82284
82285           function layerOn() {
82286             layer.style('display', 'block');
82287           }
82288
82289           function layerOff() {
82290             layer.selectAll('.viewfield-group').remove();
82291             layer.style('display', 'none');
82292           } // ensure that all geojson features in a collection have IDs
82293
82294
82295           function ensureIDs(gj) {
82296             if (!gj) return null;
82297
82298             if (gj.type === 'FeatureCollection') {
82299               for (var i = 0; i < gj.features.length; i++) {
82300                 ensureFeatureID(gj.features[i]);
82301               }
82302             } else {
82303               ensureFeatureID(gj);
82304             }
82305
82306             return gj;
82307           } // ensure that each single Feature object has a unique ID
82308
82309
82310           function ensureFeatureID(feature) {
82311             if (!feature) return;
82312             feature.__featurehash__ = utilHashcode(fastJsonStableStringify(feature));
82313             return feature;
82314           } // Prefer an array of Features instead of a FeatureCollection
82315
82316
82317           function getFeatures(gj) {
82318             if (!gj) return [];
82319
82320             if (gj.type === 'FeatureCollection') {
82321               return gj.features;
82322             } else {
82323               return [gj];
82324             }
82325           }
82326
82327           function featureKey(d) {
82328             return d.__featurehash__;
82329           }
82330
82331           function isPolygon(d) {
82332             return d.geometry.type === 'Polygon' || d.geometry.type === 'MultiPolygon';
82333           }
82334
82335           function clipPathID(d) {
82336             return 'ideditor-data-' + d.__featurehash__ + '-clippath';
82337           }
82338
82339           function featureClasses(d) {
82340             return ['data' + d.__featurehash__, d.geometry.type, isPolygon(d) ? 'area' : '', d.__layerID__ || ''].filter(Boolean).join(' ');
82341           }
82342
82343           function drawData(selection) {
82344             var vtService = getService();
82345             var getPath = svgPath(projection).geojson;
82346             var getAreaPath = svgPath(projection, null, true).geojson;
82347             var hasData = drawData.hasData();
82348             layer = selection.selectAll('.layer-mapdata').data(_enabled && hasData ? [0] : []);
82349             layer.exit().remove();
82350             layer = layer.enter().append('g').attr('class', 'layer-mapdata').merge(layer);
82351             var surface = context.surface();
82352             if (!surface || surface.empty()) return; // not ready to draw yet, starting up
82353             // Gather data
82354
82355             var geoData, polygonData;
82356
82357             if (_template && vtService) {
82358               // fetch data from vector tile service
82359               var sourceID = _template;
82360               vtService.loadTiles(sourceID, _template, projection);
82361               geoData = vtService.data(sourceID, projection);
82362             } else {
82363               geoData = getFeatures(_geojson);
82364             }
82365
82366             geoData = geoData.filter(getPath);
82367             polygonData = geoData.filter(isPolygon); // Draw clip paths for polygons
82368
82369             var clipPaths = surface.selectAll('defs').selectAll('.clipPath-data').data(polygonData, featureKey);
82370             clipPaths.exit().remove();
82371             var clipPathsEnter = clipPaths.enter().append('clipPath').attr('class', 'clipPath-data').attr('id', clipPathID);
82372             clipPathsEnter.append('path');
82373             clipPaths.merge(clipPathsEnter).selectAll('path').attr('d', getAreaPath); // Draw fill, shadow, stroke layers
82374
82375             var datagroups = layer.selectAll('g.datagroup').data(['fill', 'shadow', 'stroke']);
82376             datagroups = datagroups.enter().append('g').attr('class', function (d) {
82377               return 'datagroup datagroup-' + d;
82378             }).merge(datagroups); // Draw paths
82379
82380             var pathData = {
82381               fill: polygonData,
82382               shadow: geoData,
82383               stroke: geoData
82384             };
82385             var paths = datagroups.selectAll('path').data(function (layer) {
82386               return pathData[layer];
82387             }, featureKey); // exit
82388
82389             paths.exit().remove(); // enter/update
82390
82391             paths = paths.enter().append('path').attr('class', function (d) {
82392               var datagroup = this.parentNode.__data__;
82393               return 'pathdata ' + datagroup + ' ' + featureClasses(d);
82394             }).attr('clip-path', function (d) {
82395               var datagroup = this.parentNode.__data__;
82396               return datagroup === 'fill' ? 'url(#' + clipPathID(d) + ')' : null;
82397             }).merge(paths).attr('d', function (d) {
82398               var datagroup = this.parentNode.__data__;
82399               return datagroup === 'fill' ? getAreaPath(d) : getPath(d);
82400             }); // Draw labels
82401
82402             layer.call(drawLabels, 'label-halo', geoData).call(drawLabels, 'label', geoData);
82403
82404             function drawLabels(selection, textClass, data) {
82405               var labelPath = d3_geoPath(projection);
82406               var labelData = data.filter(function (d) {
82407                 return _showLabels && d.properties && (d.properties.desc || d.properties.name);
82408               });
82409               var labels = selection.selectAll('text.' + textClass).data(labelData, featureKey); // exit
82410
82411               labels.exit().remove(); // enter/update
82412
82413               labels = labels.enter().append('text').attr('class', function (d) {
82414                 return textClass + ' ' + featureClasses(d);
82415               }).merge(labels).text(function (d) {
82416                 return d.properties.desc || d.properties.name;
82417               }).attr('x', function (d) {
82418                 var centroid = labelPath.centroid(d);
82419                 return centroid[0] + 11;
82420               }).attr('y', function (d) {
82421                 var centroid = labelPath.centroid(d);
82422                 return centroid[1];
82423               });
82424             }
82425           }
82426
82427           function getExtension(fileName) {
82428             if (!fileName) return;
82429             var re = /\.(gpx|kml|(geo)?json)$/i;
82430             var match = fileName.toLowerCase().match(re);
82431             return match && match.length && match[0];
82432           }
82433
82434           function xmlToDom(textdata) {
82435             return new DOMParser().parseFromString(textdata, 'text/xml');
82436           }
82437
82438           function stringifyGeojsonProperties(feature) {
82439             var properties = feature.properties;
82440
82441             for (var key in properties) {
82442               var property = properties[key];
82443
82444               if (typeof property === 'number' || typeof property === 'boolean' || Array.isArray(property)) {
82445                 properties[key] = property.toString();
82446               } else if (property === null) {
82447                 properties[key] = 'null';
82448               } else if (_typeof(property) === 'object') {
82449                 properties[key] = JSON.stringify(property);
82450               }
82451             }
82452           }
82453
82454           drawData.setFile = function (extension, data) {
82455             _template = null;
82456             _fileList = null;
82457             _geojson = null;
82458             _src = null;
82459             var gj;
82460
82461             switch (extension) {
82462               case '.gpx':
82463                 gj = gpx(xmlToDom(data));
82464                 break;
82465
82466               case '.kml':
82467                 gj = kml(xmlToDom(data));
82468                 break;
82469
82470               case '.geojson':
82471               case '.json':
82472                 gj = JSON.parse(data);
82473
82474                 if (gj.type === 'FeatureCollection') {
82475                   gj.features.forEach(stringifyGeojsonProperties);
82476                 } else if (gj.type === 'Feature') {
82477                   stringifyGeojsonProperties(gj);
82478                 }
82479
82480                 break;
82481             }
82482
82483             gj = gj || {};
82484
82485             if (Object.keys(gj).length) {
82486               _geojson = ensureIDs(gj);
82487               _src = extension + ' data file';
82488               this.fitZoom();
82489             }
82490
82491             dispatch.call('change');
82492             return this;
82493           };
82494
82495           drawData.showLabels = function (val) {
82496             if (!arguments.length) return _showLabels;
82497             _showLabels = val;
82498             return this;
82499           };
82500
82501           drawData.enabled = function (val) {
82502             if (!arguments.length) return _enabled;
82503             _enabled = val;
82504
82505             if (_enabled) {
82506               showLayer();
82507             } else {
82508               hideLayer();
82509             }
82510
82511             dispatch.call('change');
82512             return this;
82513           };
82514
82515           drawData.hasData = function () {
82516             var gj = _geojson || {};
82517             return !!(_template || Object.keys(gj).length);
82518           };
82519
82520           drawData.template = function (val, src) {
82521             if (!arguments.length) return _template; // test source against OSM imagery blocklists..
82522
82523             var osm = context.connection();
82524
82525             if (osm) {
82526               var blocklists = osm.imageryBlocklists();
82527               var fail = false;
82528               var tested = 0;
82529               var regex;
82530
82531               for (var i = 0; i < blocklists.length; i++) {
82532                 regex = blocklists[i];
82533                 fail = regex.test(val);
82534                 tested++;
82535                 if (fail) break;
82536               } // ensure at least one test was run.
82537
82538
82539               if (!tested) {
82540                 regex = /.*\.google(apis)?\..*\/(vt|kh)[\?\/].*([xyz]=.*){3}.*/;
82541                 fail = regex.test(val);
82542               }
82543             }
82544
82545             _template = val;
82546             _fileList = null;
82547             _geojson = null; // strip off the querystring/hash from the template,
82548             // it often includes the access token
82549
82550             _src = src || 'vectortile:' + val.split(/[?#]/)[0];
82551             dispatch.call('change');
82552             return this;
82553           };
82554
82555           drawData.geojson = function (gj, src) {
82556             if (!arguments.length) return _geojson;
82557             _template = null;
82558             _fileList = null;
82559             _geojson = null;
82560             _src = null;
82561             gj = gj || {};
82562
82563             if (Object.keys(gj).length) {
82564               _geojson = ensureIDs(gj);
82565               _src = src || 'unknown.geojson';
82566             }
82567
82568             dispatch.call('change');
82569             return this;
82570           };
82571
82572           drawData.fileList = function (fileList) {
82573             if (!arguments.length) return _fileList;
82574             _template = null;
82575             _fileList = fileList;
82576             _geojson = null;
82577             _src = null;
82578             if (!fileList || !fileList.length) return this;
82579             var f = fileList[0];
82580             var extension = getExtension(f.name);
82581             var reader = new FileReader();
82582
82583             reader.onload = function () {
82584               return function (e) {
82585                 drawData.setFile(extension, e.target.result);
82586               };
82587             }();
82588
82589             reader.readAsText(f);
82590             return this;
82591           };
82592
82593           drawData.url = function (url, defaultExtension) {
82594             _template = null;
82595             _fileList = null;
82596             _geojson = null;
82597             _src = null; // strip off any querystring/hash from the url before checking extension
82598
82599             var testUrl = url.split(/[?#]/)[0];
82600             var extension = getExtension(testUrl) || defaultExtension;
82601
82602             if (extension) {
82603               _template = null;
82604               d3_text(url).then(function (data) {
82605                 drawData.setFile(extension, data);
82606               })["catch"](function () {
82607                 /* ignore */
82608               });
82609             } else {
82610               drawData.template(url);
82611             }
82612
82613             return this;
82614           };
82615
82616           drawData.getSrc = function () {
82617             return _src || '';
82618           };
82619
82620           drawData.fitZoom = function () {
82621             var features = getFeatures(_geojson);
82622             if (!features.length) return;
82623             var map = context.map();
82624             var viewport = map.trimmedExtent().polygon();
82625             var coords = features.reduce(function (coords, feature) {
82626               var geom = feature.geometry;
82627               if (!geom) return coords;
82628               var c = geom.coordinates;
82629               /* eslint-disable no-fallthrough */
82630
82631               switch (geom.type) {
82632                 case 'Point':
82633                   c = [c];
82634
82635                 case 'MultiPoint':
82636                 case 'LineString':
82637                   break;
82638
82639                 case 'MultiPolygon':
82640                   c = utilArrayFlatten(c);
82641
82642                 case 'Polygon':
82643                 case 'MultiLineString':
82644                   c = utilArrayFlatten(c);
82645                   break;
82646               }
82647               /* eslint-enable no-fallthrough */
82648
82649
82650               return utilArrayUnion(coords, c);
82651             }, []);
82652
82653             if (!geoPolygonIntersectsPolygon(viewport, coords, true)) {
82654               var extent = geoExtent(d3_geoBounds({
82655                 type: 'LineString',
82656                 coordinates: coords
82657               }));
82658               map.centerZoom(extent.center(), map.trimmedExtentZoom(extent));
82659             }
82660
82661             return this;
82662           };
82663
82664           init();
82665           return drawData;
82666         }
82667
82668         function svgDebug(projection, context) {
82669           function drawDebug(selection) {
82670             var showTile = context.getDebug('tile');
82671             var showCollision = context.getDebug('collision');
82672             var showImagery = context.getDebug('imagery');
82673             var showTouchTargets = context.getDebug('target');
82674             var showDownloaded = context.getDebug('downloaded');
82675             var debugData = [];
82676
82677             if (showTile) {
82678               debugData.push({
82679                 "class": 'red',
82680                 label: 'tile'
82681               });
82682             }
82683
82684             if (showCollision) {
82685               debugData.push({
82686                 "class": 'yellow',
82687                 label: 'collision'
82688               });
82689             }
82690
82691             if (showImagery) {
82692               debugData.push({
82693                 "class": 'orange',
82694                 label: 'imagery'
82695               });
82696             }
82697
82698             if (showTouchTargets) {
82699               debugData.push({
82700                 "class": 'pink',
82701                 label: 'touchTargets'
82702               });
82703             }
82704
82705             if (showDownloaded) {
82706               debugData.push({
82707                 "class": 'purple',
82708                 label: 'downloaded'
82709               });
82710             }
82711
82712             var legend = context.container().select('.main-content').selectAll('.debug-legend').data(debugData.length ? [0] : []);
82713             legend.exit().remove();
82714             legend = legend.enter().append('div').attr('class', 'fillD debug-legend').merge(legend);
82715             var legendItems = legend.selectAll('.debug-legend-item').data(debugData, function (d) {
82716               return d.label;
82717             });
82718             legendItems.exit().remove();
82719             legendItems.enter().append('span').attr('class', function (d) {
82720               return "debug-legend-item ".concat(d["class"]);
82721             }).text(function (d) {
82722               return d.label;
82723             });
82724             var layer = selection.selectAll('.layer-debug').data(showImagery || showDownloaded ? [0] : []);
82725             layer.exit().remove();
82726             layer = layer.enter().append('g').attr('class', 'layer-debug').merge(layer); // imagery
82727
82728             var extent = context.map().extent();
82729             _mainFileFetcher.get('imagery').then(function (d) {
82730               var hits = showImagery && d.query.bbox(extent.rectangle(), true) || [];
82731               var features = hits.map(function (d) {
82732                 return d.features[d.id];
82733               });
82734               var imagery = layer.selectAll('path.debug-imagery').data(features);
82735               imagery.exit().remove();
82736               imagery.enter().append('path').attr('class', 'debug-imagery debug orange');
82737             })["catch"](function () {
82738               /* ignore */
82739             }); // downloaded
82740
82741             var osm = context.connection();
82742             var dataDownloaded = [];
82743
82744             if (osm && showDownloaded) {
82745               var rtree = osm.caches('get').tile.rtree;
82746               dataDownloaded = rtree.all().map(function (bbox) {
82747                 return {
82748                   type: 'Feature',
82749                   properties: {
82750                     id: bbox.id
82751                   },
82752                   geometry: {
82753                     type: 'Polygon',
82754                     coordinates: [[[bbox.minX, bbox.minY], [bbox.minX, bbox.maxY], [bbox.maxX, bbox.maxY], [bbox.maxX, bbox.minY], [bbox.minX, bbox.minY]]]
82755                   }
82756                 };
82757               });
82758             }
82759
82760             var downloaded = layer.selectAll('path.debug-downloaded').data(showDownloaded ? dataDownloaded : []);
82761             downloaded.exit().remove();
82762             downloaded.enter().append('path').attr('class', 'debug-downloaded debug purple'); // update
82763
82764             layer.selectAll('path').attr('d', svgPath(projection).geojson);
82765           } // This looks strange because `enabled` methods on other layers are
82766           // chainable getter/setters, and this one is just a getter.
82767
82768
82769           drawDebug.enabled = function () {
82770             if (!arguments.length) {
82771               return context.getDebug('tile') || context.getDebug('collision') || context.getDebug('imagery') || context.getDebug('target') || context.getDebug('downloaded');
82772             } else {
82773               return this;
82774             }
82775           };
82776
82777           return drawDebug;
82778         }
82779
82780         /*
82781             A standalone SVG element that contains only a `defs` sub-element. To be
82782             used once globally, since defs IDs must be unique within a document.
82783         */
82784
82785         function svgDefs(context) {
82786           var _defsSelection = select(null);
82787
82788           var _spritesheetIds = ['iD-sprite', 'maki-sprite', 'temaki-sprite', 'fa-sprite', 'community-sprite'];
82789
82790           function drawDefs(selection) {
82791             _defsSelection = selection.append('defs'); // add markers
82792
82793             _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
82794             // (they can't inherit it from the line they're attached to),
82795             // so we need to manually define markers for each color of tag
82796             // (also, it's slightly nicer if we can control the
82797             // positioning for different tags)
82798
82799
82800             function addSidedMarker(name, color, offset) {
82801               _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);
82802             }
82803
82804             addSidedMarker('natural', 'rgb(170, 170, 170)', 0); // for a coastline, the arrows are (somewhat unintuitively) on
82805             // the water side, so let's color them blue (with a gap) to
82806             // give a stronger indication
82807
82808             addSidedMarker('coastline', '#77dede', 1);
82809             addSidedMarker('waterway', '#77dede', 1); // barriers have a dashed line, and separating the triangle
82810             // from the line visually suits that
82811
82812             addSidedMarker('barrier', '#ddd', 1);
82813             addSidedMarker('man_made', '#fff', 0);
82814
82815             _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');
82816
82817             _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
82818
82819
82820             var patterns = _defsSelection.selectAll('pattern').data([// pattern name, pattern image name
82821             ['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) {
82822               return 'ideditor-pattern-' + d[0];
82823             }).attr('width', 32).attr('height', 32).attr('patternUnits', 'userSpaceOnUse');
82824
82825             patterns.append('rect').attr('x', 0).attr('y', 0).attr('width', 32).attr('height', 32).attr('class', function (d) {
82826               return 'pattern-color-' + d[0];
82827             });
82828             patterns.append('image').attr('x', 0).attr('y', 0).attr('width', 32).attr('height', 32).attr('xlink:href', function (d) {
82829               return context.imagePath('pattern/' + d[1] + '.png');
82830             }); // add clip paths
82831
82832             _defsSelection.selectAll('clipPath').data([12, 18, 20, 32, 45]).enter().append('clipPath').attr('id', function (d) {
82833               return 'ideditor-clip-square-' + d;
82834             }).append('rect').attr('x', 0).attr('y', 0).attr('width', function (d) {
82835               return d;
82836             }).attr('height', function (d) {
82837               return d;
82838             }); // add symbol spritesheets
82839
82840
82841             addSprites(_spritesheetIds, true);
82842           }
82843
82844           function addSprites(ids, overrideColors) {
82845             _spritesheetIds = utilArrayUniq(_spritesheetIds.concat(ids));
82846
82847             var spritesheets = _defsSelection.selectAll('.spritesheet').data(_spritesheetIds);
82848
82849             spritesheets.enter().append('g').attr('class', function (d) {
82850               return 'spritesheet spritesheet-' + d;
82851             }).each(function (d) {
82852               var url = context.imagePath(d + '.svg');
82853               var node = select(this).node();
82854               svg(url).then(function (svg) {
82855                 node.appendChild(select(svg.documentElement).attr('id', 'ideditor-' + d).node());
82856
82857                 if (overrideColors && d !== 'iD-sprite') {
82858                   // allow icon colors to be overridden..
82859                   select(node).selectAll('path').attr('fill', 'currentColor');
82860                 }
82861               })["catch"](function () {
82862                 /* ignore */
82863               });
82864             });
82865             spritesheets.exit().remove();
82866           }
82867
82868           drawDefs.addSprites = addSprites;
82869           return drawDefs;
82870         }
82871
82872         var _layerEnabled$2 = false;
82873
82874         var _qaService$2;
82875
82876         function svgKeepRight(projection, context, dispatch) {
82877           var throttledRedraw = throttle(function () {
82878             return dispatch.call('change');
82879           }, 1000);
82880
82881           var minZoom = 12;
82882           var touchLayer = select(null);
82883           var drawLayer = select(null);
82884           var layerVisible = false;
82885
82886           function markerPath(selection, klass) {
82887             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');
82888           } // Loosely-coupled keepRight service for fetching issues.
82889
82890
82891           function getService() {
82892             if (services.keepRight && !_qaService$2) {
82893               _qaService$2 = services.keepRight;
82894
82895               _qaService$2.on('loaded', throttledRedraw);
82896             } else if (!services.keepRight && _qaService$2) {
82897               _qaService$2 = null;
82898             }
82899
82900             return _qaService$2;
82901           } // Show the markers
82902
82903
82904           function editOn() {
82905             if (!layerVisible) {
82906               layerVisible = true;
82907               drawLayer.style('display', 'block');
82908             }
82909           } // Immediately remove the markers and their touch targets
82910
82911
82912           function editOff() {
82913             if (layerVisible) {
82914               layerVisible = false;
82915               drawLayer.style('display', 'none');
82916               drawLayer.selectAll('.qaItem.keepRight').remove();
82917               touchLayer.selectAll('.qaItem.keepRight').remove();
82918             }
82919           } // Enable the layer.  This shows the markers and transitions them to visible.
82920
82921
82922           function layerOn() {
82923             editOn();
82924             drawLayer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end interrupt', function () {
82925               return dispatch.call('change');
82926             });
82927           } // Disable the layer.  This transitions the layer invisible and then hides the markers.
82928
82929
82930           function layerOff() {
82931             throttledRedraw.cancel();
82932             drawLayer.interrupt();
82933             touchLayer.selectAll('.qaItem.keepRight').remove();
82934             drawLayer.transition().duration(250).style('opacity', 0).on('end interrupt', function () {
82935               editOff();
82936               dispatch.call('change');
82937             });
82938           } // Update the issue markers
82939
82940
82941           function updateMarkers() {
82942             if (!layerVisible || !_layerEnabled$2) return;
82943             var service = getService();
82944             var selectedID = context.selectedErrorID();
82945             var data = service ? service.getItems(projection) : [];
82946             var getTransform = svgPointTransform(projection); // Draw markers..
82947
82948             var markers = drawLayer.selectAll('.qaItem.keepRight').data(data, function (d) {
82949               return d.id;
82950             }); // exit
82951
82952             markers.exit().remove(); // enter
82953
82954             var markersEnter = markers.enter().append('g').attr('class', function (d) {
82955               return "qaItem ".concat(d.service, " itemId-").concat(d.id, " itemType-").concat(d.parentIssueType);
82956             });
82957             markersEnter.append('ellipse').attr('cx', 0.5).attr('cy', 1).attr('rx', 6.5).attr('ry', 3).attr('class', 'stroke');
82958             markersEnter.append('path').call(markerPath, 'shadow');
82959             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
82960
82961             markers.merge(markersEnter).sort(sortY).classed('selected', function (d) {
82962               return d.id === selectedID;
82963             }).attr('transform', getTransform); // Draw targets..
82964
82965             if (touchLayer.empty()) return;
82966             var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
82967             var targets = touchLayer.selectAll('.qaItem.keepRight').data(data, function (d) {
82968               return d.id;
82969             }); // exit
82970
82971             targets.exit().remove(); // enter/update
82972
82973             targets.enter().append('rect').attr('width', '20px').attr('height', '20px').attr('x', '-8px').attr('y', '-22px').merge(targets).sort(sortY).attr('class', function (d) {
82974               return "qaItem ".concat(d.service, " target ").concat(fillClass, " itemId-").concat(d.id);
82975             }).attr('transform', getTransform);
82976
82977             function sortY(a, b) {
82978               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];
82979             }
82980           } // Draw the keepRight layer and schedule loading issues and updating markers.
82981
82982
82983           function drawKeepRight(selection) {
82984             var service = getService();
82985             var surface = context.surface();
82986
82987             if (surface && !surface.empty()) {
82988               touchLayer = surface.selectAll('.data-layer.touch .layer-touch.markers');
82989             }
82990
82991             drawLayer = selection.selectAll('.layer-keepRight').data(service ? [0] : []);
82992             drawLayer.exit().remove();
82993             drawLayer = drawLayer.enter().append('g').attr('class', 'layer-keepRight').style('display', _layerEnabled$2 ? 'block' : 'none').merge(drawLayer);
82994
82995             if (_layerEnabled$2) {
82996               if (service && ~~context.map().zoom() >= minZoom) {
82997                 editOn();
82998                 service.loadIssues(projection);
82999                 updateMarkers();
83000               } else {
83001                 editOff();
83002               }
83003             }
83004           } // Toggles the layer on and off
83005
83006
83007           drawKeepRight.enabled = function (val) {
83008             if (!arguments.length) return _layerEnabled$2;
83009             _layerEnabled$2 = val;
83010
83011             if (_layerEnabled$2) {
83012               layerOn();
83013             } else {
83014               layerOff();
83015
83016               if (context.selectedErrorID()) {
83017                 context.enter(modeBrowse(context));
83018               }
83019             }
83020
83021             dispatch.call('change');
83022             return this;
83023           };
83024
83025           drawKeepRight.supported = function () {
83026             return !!getService();
83027           };
83028
83029           return drawKeepRight;
83030         }
83031
83032         function svgGeolocate(projection) {
83033           var layer = select(null);
83034
83035           var _position;
83036
83037           function init() {
83038             if (svgGeolocate.initialized) return; // run once
83039
83040             svgGeolocate.enabled = false;
83041             svgGeolocate.initialized = true;
83042           }
83043
83044           function showLayer() {
83045             layer.style('display', 'block');
83046           }
83047
83048           function hideLayer() {
83049             layer.transition().duration(250).style('opacity', 0);
83050           }
83051
83052           function layerOn() {
83053             layer.style('opacity', 0).transition().duration(250).style('opacity', 1);
83054           }
83055
83056           function layerOff() {
83057             layer.style('display', 'none');
83058           }
83059
83060           function transform(d) {
83061             return svgPointTransform(projection)(d);
83062           }
83063
83064           function accuracy(accuracy, loc) {
83065             // converts accuracy to pixels...
83066             var degreesRadius = geoMetersToLat(accuracy),
83067                 tangentLoc = [loc[0], loc[1] + degreesRadius],
83068                 projectedTangent = projection(tangentLoc),
83069                 projectedLoc = projection([loc[0], loc[1]]); // southern most point will have higher pixel value...
83070
83071             return Math.round(projectedLoc[1] - projectedTangent[1]).toString();
83072           }
83073
83074           function update() {
83075             var geolocation = {
83076               loc: [_position.coords.longitude, _position.coords.latitude]
83077             };
83078             var groups = layer.selectAll('.geolocations').selectAll('.geolocation').data([geolocation]);
83079             groups.exit().remove();
83080             var pointsEnter = groups.enter().append('g').attr('class', 'geolocation');
83081             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');
83082             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');
83083             groups.merge(pointsEnter).attr('transform', transform);
83084             layer.select('.geolocate-radius').attr('r', accuracy(_position.coords.accuracy, geolocation.loc));
83085           }
83086
83087           function drawLocation(selection) {
83088             var enabled = svgGeolocate.enabled;
83089             layer = selection.selectAll('.layer-geolocate').data([0]);
83090             layer.exit().remove();
83091             var layerEnter = layer.enter().append('g').attr('class', 'layer-geolocate').style('display', enabled ? 'block' : 'none');
83092             layerEnter.append('g').attr('class', 'geolocations');
83093             layer = layerEnter.merge(layer);
83094
83095             if (enabled) {
83096               update();
83097             } else {
83098               layerOff();
83099             }
83100           }
83101
83102           drawLocation.enabled = function (position, enabled) {
83103             if (!arguments.length) return svgGeolocate.enabled;
83104             _position = position;
83105             svgGeolocate.enabled = enabled;
83106
83107             if (svgGeolocate.enabled) {
83108               showLayer();
83109               layerOn();
83110             } else {
83111               hideLayer();
83112             }
83113
83114             return this;
83115           };
83116
83117           init();
83118           return drawLocation;
83119         }
83120
83121         function svgLabels(projection, context) {
83122           var path = d3_geoPath(projection);
83123           var detected = utilDetect();
83124           var baselineHack = detected.ie || detected.browser.toLowerCase() === 'edge' || detected.browser.toLowerCase() === 'firefox' && detected.version >= 70;
83125
83126           var _rdrawn = new RBush();
83127
83128           var _rskipped = new RBush();
83129
83130           var _textWidthCache = {};
83131           var _entitybboxes = {}; // Listed from highest to lowest priority
83132
83133           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]];
83134
83135           function shouldSkipIcon(preset) {
83136             var noIcons = ['building', 'landuse', 'natural'];
83137             return noIcons.some(function (s) {
83138               return preset.id.indexOf(s) >= 0;
83139             });
83140           }
83141
83142           function get(array, prop) {
83143             return function (d, i) {
83144               return array[i][prop];
83145             };
83146           }
83147
83148           function textWidth(text, size, elem) {
83149             var c = _textWidthCache[size];
83150             if (!c) c = _textWidthCache[size] = {};
83151
83152             if (c[text]) {
83153               return c[text];
83154             } else if (elem) {
83155               c[text] = elem.getComputedTextLength();
83156               return c[text];
83157             } else {
83158               var str = encodeURIComponent(text).match(/%[CDEFcdef]/g);
83159
83160               if (str === null) {
83161                 return size / 3 * 2 * text.length;
83162               } else {
83163                 return size / 3 * (2 * text.length + str.length);
83164               }
83165             }
83166           }
83167
83168           function drawLinePaths(selection, entities, filter, classes, labels) {
83169             var paths = selection.selectAll('path').filter(filter).data(entities, osmEntity.key); // exit
83170
83171             paths.exit().remove(); // enter/update
83172
83173             paths.enter().append('path').style('stroke-width', get(labels, 'font-size')).attr('id', function (d) {
83174               return 'ideditor-labelpath-' + d.id;
83175             }).attr('class', classes).merge(paths).attr('d', get(labels, 'lineString'));
83176           }
83177
83178           function drawLineLabels(selection, entities, filter, classes, labels) {
83179             var texts = selection.selectAll('text.' + classes).filter(filter).data(entities, osmEntity.key); // exit
83180
83181             texts.exit().remove(); // enter
83182
83183             texts.enter().append('text').attr('class', function (d, i) {
83184               return classes + ' ' + labels[i].classes + ' ' + d.id;
83185             }).attr('dy', baselineHack ? '0.35em' : null).append('textPath').attr('class', 'textpath'); // update
83186
83187             selection.selectAll('text.' + classes).selectAll('.textpath').filter(filter).data(entities, osmEntity.key).attr('startOffset', '50%').attr('xlink:href', function (d) {
83188               return '#ideditor-labelpath-' + d.id;
83189             }).text(utilDisplayNameForPath);
83190           }
83191
83192           function drawPointLabels(selection, entities, filter, classes, labels) {
83193             var texts = selection.selectAll('text.' + classes).filter(filter).data(entities, osmEntity.key); // exit
83194
83195             texts.exit().remove(); // enter/update
83196
83197             texts.enter().append('text').attr('class', function (d, i) {
83198               return classes + ' ' + labels[i].classes + ' ' + d.id;
83199             }).merge(texts).attr('x', get(labels, 'x')).attr('y', get(labels, 'y')).style('text-anchor', get(labels, 'textAnchor')).text(utilDisplayName).each(function (d, i) {
83200               textWidth(utilDisplayName(d), labels[i].height, this);
83201             });
83202           }
83203
83204           function drawAreaLabels(selection, entities, filter, classes, labels) {
83205             entities = entities.filter(hasText);
83206             labels = labels.filter(hasText);
83207             drawPointLabels(selection, entities, filter, classes, labels);
83208
83209             function hasText(d, i) {
83210               return labels[i].hasOwnProperty('x') && labels[i].hasOwnProperty('y');
83211             }
83212           }
83213
83214           function drawAreaIcons(selection, entities, filter, classes, labels) {
83215             var icons = selection.selectAll('use.' + classes).filter(filter).data(entities, osmEntity.key); // exit
83216
83217             icons.exit().remove(); // enter/update
83218
83219             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) {
83220               var preset = _mainPresetIndex.match(d, context.graph());
83221               var picon = preset && preset.icon;
83222
83223               if (!picon) {
83224                 return '';
83225               } else {
83226                 var isMaki = /^maki-/.test(picon);
83227                 return '#' + picon + (isMaki ? '-15' : '');
83228               }
83229             });
83230           }
83231
83232           function drawCollisionBoxes(selection, rtree, which) {
83233             var classes = 'debug ' + which + ' ' + (which === 'debug-skipped' ? 'orange' : 'yellow');
83234             var gj = [];
83235
83236             if (context.getDebug('collision')) {
83237               gj = rtree.all().map(function (d) {
83238                 return {
83239                   type: 'Polygon',
83240                   coordinates: [[[d.minX, d.minY], [d.maxX, d.minY], [d.maxX, d.maxY], [d.minX, d.maxY], [d.minX, d.minY]]]
83241                 };
83242               });
83243             }
83244
83245             var boxes = selection.selectAll('.' + which).data(gj); // exit
83246
83247             boxes.exit().remove(); // enter/update
83248
83249             boxes.enter().append('path').attr('class', classes).merge(boxes).attr('d', d3_geoPath());
83250           }
83251
83252           function drawLabels(selection, graph, entities, filter, dimensions, fullRedraw) {
83253             var wireframe = context.surface().classed('fill-wireframe');
83254             var zoom = geoScaleToZoom(projection.scale());
83255             var labelable = [];
83256             var renderNodeAs = {};
83257             var i, j, k, entity, geometry;
83258
83259             for (i = 0; i < labelStack.length; i++) {
83260               labelable.push([]);
83261             }
83262
83263             if (fullRedraw) {
83264               _rdrawn.clear();
83265
83266               _rskipped.clear();
83267
83268               _entitybboxes = {};
83269             } else {
83270               for (i = 0; i < entities.length; i++) {
83271                 entity = entities[i];
83272                 var toRemove = [].concat(_entitybboxes[entity.id] || []).concat(_entitybboxes[entity.id + 'I'] || []);
83273
83274                 for (j = 0; j < toRemove.length; j++) {
83275                   _rdrawn.remove(toRemove[j]);
83276
83277                   _rskipped.remove(toRemove[j]);
83278                 }
83279               }
83280             } // Loop through all the entities to do some preprocessing
83281
83282
83283             for (i = 0; i < entities.length; i++) {
83284               entity = entities[i];
83285               geometry = entity.geometry(graph); // Insert collision boxes around interesting points/vertices
83286
83287               if (geometry === 'point' || geometry === 'vertex' && isInterestingVertex(entity)) {
83288                 var hasDirections = entity.directions(graph, projection).length;
83289                 var markerPadding;
83290
83291                 if (!wireframe && geometry === 'point' && !(zoom >= 18 && hasDirections)) {
83292                   renderNodeAs[entity.id] = 'point';
83293                   markerPadding = 20; // extra y for marker height
83294                 } else {
83295                   renderNodeAs[entity.id] = 'vertex';
83296                   markerPadding = 0;
83297                 }
83298
83299                 var coord = projection(entity.loc);
83300                 var nodePadding = 10;
83301                 var bbox = {
83302                   minX: coord[0] - nodePadding,
83303                   minY: coord[1] - nodePadding - markerPadding,
83304                   maxX: coord[0] + nodePadding,
83305                   maxY: coord[1] + nodePadding
83306                 };
83307                 doInsert(bbox, entity.id + 'P');
83308               } // From here on, treat vertices like points
83309
83310
83311               if (geometry === 'vertex') {
83312                 geometry = 'point';
83313               } // Determine which entities are label-able
83314
83315
83316               var preset = geometry === 'area' && _mainPresetIndex.match(entity, graph);
83317               var icon = preset && !shouldSkipIcon(preset) && preset.icon;
83318               if (!icon && !utilDisplayName(entity)) continue;
83319
83320               for (k = 0; k < labelStack.length; k++) {
83321                 var matchGeom = labelStack[k][0];
83322                 var matchKey = labelStack[k][1];
83323                 var matchVal = labelStack[k][2];
83324                 var hasVal = entity.tags[matchKey];
83325
83326                 if (geometry === matchGeom && hasVal && (matchVal === '*' || matchVal === hasVal)) {
83327                   labelable[k].push(entity);
83328                   break;
83329                 }
83330               }
83331             }
83332
83333             var positions = {
83334               point: [],
83335               line: [],
83336               area: []
83337             };
83338             var labelled = {
83339               point: [],
83340               line: [],
83341               area: []
83342             }; // Try and find a valid label for labellable entities
83343
83344             for (k = 0; k < labelable.length; k++) {
83345               var fontSize = labelStack[k][3];
83346
83347               for (i = 0; i < labelable[k].length; i++) {
83348                 entity = labelable[k][i];
83349                 geometry = entity.geometry(graph);
83350                 var getName = geometry === 'line' ? utilDisplayNameForPath : utilDisplayName;
83351                 var name = getName(entity);
83352                 var width = name && textWidth(name, fontSize);
83353                 var p = null;
83354
83355                 if (geometry === 'point' || geometry === 'vertex') {
83356                   // no point or vertex labels in wireframe mode
83357                   // no vertex labels at low zooms (vertices have no icons)
83358                   if (wireframe) continue;
83359                   var renderAs = renderNodeAs[entity.id];
83360                   if (renderAs === 'vertex' && zoom < 17) continue;
83361                   p = getPointLabel(entity, width, fontSize, renderAs);
83362                 } else if (geometry === 'line') {
83363                   p = getLineLabel(entity, width, fontSize);
83364                 } else if (geometry === 'area') {
83365                   p = getAreaLabel(entity, width, fontSize);
83366                 }
83367
83368                 if (p) {
83369                   if (geometry === 'vertex') {
83370                     geometry = 'point';
83371                   } // treat vertex like point
83372
83373
83374                   p.classes = geometry + ' tag-' + labelStack[k][1];
83375                   positions[geometry].push(p);
83376                   labelled[geometry].push(entity);
83377                 }
83378               }
83379             }
83380
83381             function isInterestingVertex(entity) {
83382               var selectedIDs = context.selectedIDs();
83383               return entity.hasInterestingTags() || entity.isEndpoint(graph) || entity.isConnected(graph) || selectedIDs.indexOf(entity.id) !== -1 || graph.parentWays(entity).some(function (parent) {
83384                 return selectedIDs.indexOf(parent.id) !== -1;
83385               });
83386             }
83387
83388             function getPointLabel(entity, width, height, geometry) {
83389               var y = geometry === 'point' ? -12 : 0;
83390               var pointOffsets = {
83391                 ltr: [15, y, 'start'],
83392                 rtl: [-15, y, 'end']
83393               };
83394               var textDirection = _mainLocalizer.textDirection();
83395               var coord = projection(entity.loc);
83396               var textPadding = 2;
83397               var offset = pointOffsets[textDirection];
83398               var p = {
83399                 height: height,
83400                 width: width,
83401                 x: coord[0] + offset[0],
83402                 y: coord[1] + offset[1],
83403                 textAnchor: offset[2]
83404               }; // insert a collision box for the text label..
83405
83406               var bbox;
83407
83408               if (textDirection === 'rtl') {
83409                 bbox = {
83410                   minX: p.x - width - textPadding,
83411                   minY: p.y - height / 2 - textPadding,
83412                   maxX: p.x + textPadding,
83413                   maxY: p.y + height / 2 + textPadding
83414                 };
83415               } else {
83416                 bbox = {
83417                   minX: p.x - textPadding,
83418                   minY: p.y - height / 2 - textPadding,
83419                   maxX: p.x + width + textPadding,
83420                   maxY: p.y + height / 2 + textPadding
83421                 };
83422               }
83423
83424               if (tryInsert([bbox], entity.id, true)) {
83425                 return p;
83426               }
83427             }
83428
83429             function getLineLabel(entity, width, height) {
83430               var viewport = geoExtent(context.projection.clipExtent()).polygon();
83431               var points = graph.childNodes(entity).map(function (node) {
83432                 return projection(node.loc);
83433               });
83434               var length = geoPathLength(points);
83435               if (length < width + 20) return; // % along the line to attempt to place the label
83436
83437               var lineOffsets = [50, 45, 55, 40, 60, 35, 65, 30, 70, 25, 75, 20, 80, 15, 95, 10, 90, 5, 95];
83438               var padding = 3;
83439
83440               for (var i = 0; i < lineOffsets.length; i++) {
83441                 var offset = lineOffsets[i];
83442                 var middle = offset / 100 * length;
83443                 var start = middle - width / 2;
83444                 if (start < 0 || start + width > length) continue; // generate subpath and ignore paths that are invalid or don't cross viewport.
83445
83446                 var sub = subpath(points, start, start + width);
83447
83448                 if (!sub || !geoPolygonIntersectsPolygon(viewport, sub, true)) {
83449                   continue;
83450                 }
83451
83452                 var isReverse = reverse(sub);
83453
83454                 if (isReverse) {
83455                   sub = sub.reverse();
83456                 }
83457
83458                 var bboxes = [];
83459                 var boxsize = (height + 2) / 2;
83460
83461                 for (var j = 0; j < sub.length - 1; j++) {
83462                   var a = sub[j];
83463                   var b = sub[j + 1]; // split up the text into small collision boxes
83464
83465                   var num = Math.max(1, Math.floor(geoVecLength(a, b) / boxsize / 2));
83466
83467                   for (var box = 0; box < num; box++) {
83468                     var p = geoVecInterp(a, b, box / num);
83469                     var x0 = p[0] - boxsize - padding;
83470                     var y0 = p[1] - boxsize - padding;
83471                     var x1 = p[0] + boxsize + padding;
83472                     var y1 = p[1] + boxsize + padding;
83473                     bboxes.push({
83474                       minX: Math.min(x0, x1),
83475                       minY: Math.min(y0, y1),
83476                       maxX: Math.max(x0, x1),
83477                       maxY: Math.max(y0, y1)
83478                     });
83479                   }
83480                 }
83481
83482                 if (tryInsert(bboxes, entity.id, false)) {
83483                   // accept this one
83484                   return {
83485                     'font-size': height + 2,
83486                     lineString: lineString(sub),
83487                     startOffset: offset + '%'
83488                   };
83489                 }
83490               }
83491
83492               function reverse(p) {
83493                 var angle = Math.atan2(p[1][1] - p[0][1], p[1][0] - p[0][0]);
83494                 return !(p[0][0] < p[p.length - 1][0] && angle < Math.PI / 2 && angle > -Math.PI / 2);
83495               }
83496
83497               function lineString(points) {
83498                 return 'M' + points.join('L');
83499               }
83500
83501               function subpath(points, from, to) {
83502                 var sofar = 0;
83503                 var start, end, i0, i1;
83504
83505                 for (var i = 0; i < points.length - 1; i++) {
83506                   var a = points[i];
83507                   var b = points[i + 1];
83508                   var current = geoVecLength(a, b);
83509                   var portion;
83510
83511                   if (!start && sofar + current >= from) {
83512                     portion = (from - sofar) / current;
83513                     start = [a[0] + portion * (b[0] - a[0]), a[1] + portion * (b[1] - a[1])];
83514                     i0 = i + 1;
83515                   }
83516
83517                   if (!end && sofar + current >= to) {
83518                     portion = (to - sofar) / current;
83519                     end = [a[0] + portion * (b[0] - a[0]), a[1] + portion * (b[1] - a[1])];
83520                     i1 = i + 1;
83521                   }
83522
83523                   sofar += current;
83524                 }
83525
83526                 var result = points.slice(i0, i1);
83527                 result.unshift(start);
83528                 result.push(end);
83529                 return result;
83530               }
83531             }
83532
83533             function getAreaLabel(entity, width, height) {
83534               var centroid = path.centroid(entity.asGeoJSON(graph));
83535               var extent = entity.extent(graph);
83536               var areaWidth = projection(extent[1])[0] - projection(extent[0])[0];
83537               if (isNaN(centroid[0]) || areaWidth < 20) return;
83538               var preset = _mainPresetIndex.match(entity, context.graph());
83539               var picon = preset && preset.icon;
83540               var iconSize = 17;
83541               var padding = 2;
83542               var p = {};
83543
83544               if (picon) {
83545                 // icon and label..
83546                 if (addIcon()) {
83547                   addLabel(iconSize + padding);
83548                   return p;
83549                 }
83550               } else {
83551                 // label only..
83552                 if (addLabel(0)) {
83553                   return p;
83554                 }
83555               }
83556
83557               function addIcon() {
83558                 var iconX = centroid[0] - iconSize / 2;
83559                 var iconY = centroid[1] - iconSize / 2;
83560                 var bbox = {
83561                   minX: iconX,
83562                   minY: iconY,
83563                   maxX: iconX + iconSize,
83564                   maxY: iconY + iconSize
83565                 };
83566
83567                 if (tryInsert([bbox], entity.id + 'I', true)) {
83568                   p.transform = 'translate(' + iconX + ',' + iconY + ')';
83569                   return true;
83570                 }
83571
83572                 return false;
83573               }
83574
83575               function addLabel(yOffset) {
83576                 if (width && areaWidth >= width + 20) {
83577                   var labelX = centroid[0];
83578                   var labelY = centroid[1] + yOffset;
83579                   var bbox = {
83580                     minX: labelX - width / 2 - padding,
83581                     minY: labelY - height / 2 - padding,
83582                     maxX: labelX + width / 2 + padding,
83583                     maxY: labelY + height / 2 + padding
83584                   };
83585
83586                   if (tryInsert([bbox], entity.id, true)) {
83587                     p.x = labelX;
83588                     p.y = labelY;
83589                     p.textAnchor = 'middle';
83590                     p.height = height;
83591                     return true;
83592                   }
83593                 }
83594
83595                 return false;
83596               }
83597             } // force insert a singular bounding box
83598             // singular box only, no array, id better be unique
83599
83600
83601             function doInsert(bbox, id) {
83602               bbox.id = id;
83603               var oldbox = _entitybboxes[id];
83604
83605               if (oldbox) {
83606                 _rdrawn.remove(oldbox);
83607               }
83608
83609               _entitybboxes[id] = bbox;
83610
83611               _rdrawn.insert(bbox);
83612             }
83613
83614             function tryInsert(bboxes, id, saveSkipped) {
83615               var skipped = false;
83616
83617               for (var i = 0; i < bboxes.length; i++) {
83618                 var bbox = bboxes[i];
83619                 bbox.id = id; // Check that label is visible
83620
83621                 if (bbox.minX < 0 || bbox.minY < 0 || bbox.maxX > dimensions[0] || bbox.maxY > dimensions[1]) {
83622                   skipped = true;
83623                   break;
83624                 }
83625
83626                 if (_rdrawn.collides(bbox)) {
83627                   skipped = true;
83628                   break;
83629                 }
83630               }
83631
83632               _entitybboxes[id] = bboxes;
83633
83634               if (skipped) {
83635                 if (saveSkipped) {
83636                   _rskipped.load(bboxes);
83637                 }
83638               } else {
83639                 _rdrawn.load(bboxes);
83640               }
83641
83642               return !skipped;
83643             }
83644
83645             var layer = selection.selectAll('.layer-osm.labels');
83646             layer.selectAll('.labels-group').data(['halo', 'label', 'debug']).enter().append('g').attr('class', function (d) {
83647               return 'labels-group ' + d;
83648             });
83649             var halo = layer.selectAll('.labels-group.halo');
83650             var label = layer.selectAll('.labels-group.label');
83651             var debug = layer.selectAll('.labels-group.debug'); // points
83652
83653             drawPointLabels(label, labelled.point, filter, 'pointlabel', positions.point);
83654             drawPointLabels(halo, labelled.point, filter, 'pointlabel-halo', positions.point); // lines
83655
83656             drawLinePaths(layer, labelled.line, filter, '', positions.line);
83657             drawLineLabels(label, labelled.line, filter, 'linelabel', positions.line);
83658             drawLineLabels(halo, labelled.line, filter, 'linelabel-halo', positions.line); // areas
83659
83660             drawAreaLabels(label, labelled.area, filter, 'arealabel', positions.area);
83661             drawAreaLabels(halo, labelled.area, filter, 'arealabel-halo', positions.area);
83662             drawAreaIcons(label, labelled.area, filter, 'areaicon', positions.area);
83663             drawAreaIcons(halo, labelled.area, filter, 'areaicon-halo', positions.area); // debug
83664
83665             drawCollisionBoxes(debug, _rskipped, 'debug-skipped');
83666             drawCollisionBoxes(debug, _rdrawn, 'debug-drawn');
83667             layer.call(filterLabels);
83668           }
83669
83670           function filterLabels(selection) {
83671             var drawLayer = selection.selectAll('.layer-osm.labels');
83672             var layers = drawLayer.selectAll('.labels-group.halo, .labels-group.label');
83673             layers.selectAll('.nolabel').classed('nolabel', false);
83674             var mouse = context.map().mouse();
83675             var graph = context.graph();
83676             var selectedIDs = context.selectedIDs();
83677             var ids = [];
83678             var pad, bbox; // hide labels near the mouse
83679
83680             if (mouse) {
83681               pad = 20;
83682               bbox = {
83683                 minX: mouse[0] - pad,
83684                 minY: mouse[1] - pad,
83685                 maxX: mouse[0] + pad,
83686                 maxY: mouse[1] + pad
83687               };
83688
83689               var nearMouse = _rdrawn.search(bbox).map(function (entity) {
83690                 return entity.id;
83691               });
83692
83693               ids.push.apply(ids, nearMouse);
83694             } // hide labels on selected nodes (they look weird when dragging / haloed)
83695
83696
83697             for (var i = 0; i < selectedIDs.length; i++) {
83698               var entity = graph.hasEntity(selectedIDs[i]);
83699
83700               if (entity && entity.type === 'node') {
83701                 ids.push(selectedIDs[i]);
83702               }
83703             }
83704
83705             layers.selectAll(utilEntitySelector(ids)).classed('nolabel', true); // draw the mouse bbox if debugging is on..
83706
83707             var debug = selection.selectAll('.labels-group.debug');
83708             var gj = [];
83709
83710             if (context.getDebug('collision')) {
83711               gj = bbox ? [{
83712                 type: 'Polygon',
83713                 coordinates: [[[bbox.minX, bbox.minY], [bbox.maxX, bbox.minY], [bbox.maxX, bbox.maxY], [bbox.minX, bbox.maxY], [bbox.minX, bbox.minY]]]
83714               }] : [];
83715             }
83716
83717             var box = debug.selectAll('.debug-mouse').data(gj); // exit
83718
83719             box.exit().remove(); // enter/update
83720
83721             box.enter().append('path').attr('class', 'debug debug-mouse yellow').merge(box).attr('d', d3_geoPath());
83722           }
83723
83724           var throttleFilterLabels = throttle(filterLabels, 100);
83725
83726           drawLabels.observe = function (selection) {
83727             var listener = function listener() {
83728               throttleFilterLabels(selection);
83729             };
83730
83731             selection.on('mousemove.hidelabels', listener);
83732             context.on('enter.hidelabels', listener);
83733           };
83734
83735           drawLabels.off = function (selection) {
83736             throttleFilterLabels.cancel();
83737             selection.on('mousemove.hidelabels', null);
83738             context.on('enter.hidelabels', null);
83739           };
83740
83741           return drawLabels;
83742         }
83743
83744         var _layerEnabled$1 = false;
83745
83746         var _qaService$1;
83747
83748         function svgImproveOSM(projection, context, dispatch) {
83749           var throttledRedraw = throttle(function () {
83750             return dispatch.call('change');
83751           }, 1000);
83752
83753           var minZoom = 12;
83754           var touchLayer = select(null);
83755           var drawLayer = select(null);
83756           var layerVisible = false;
83757
83758           function markerPath(selection, klass) {
83759             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');
83760           } // Loosely-coupled improveOSM service for fetching issues
83761
83762
83763           function getService() {
83764             if (services.improveOSM && !_qaService$1) {
83765               _qaService$1 = services.improveOSM;
83766
83767               _qaService$1.on('loaded', throttledRedraw);
83768             } else if (!services.improveOSM && _qaService$1) {
83769               _qaService$1 = null;
83770             }
83771
83772             return _qaService$1;
83773           } // Show the markers
83774
83775
83776           function editOn() {
83777             if (!layerVisible) {
83778               layerVisible = true;
83779               drawLayer.style('display', 'block');
83780             }
83781           } // Immediately remove the markers and their touch targets
83782
83783
83784           function editOff() {
83785             if (layerVisible) {
83786               layerVisible = false;
83787               drawLayer.style('display', 'none');
83788               drawLayer.selectAll('.qaItem.improveOSM').remove();
83789               touchLayer.selectAll('.qaItem.improveOSM').remove();
83790             }
83791           } // Enable the layer.  This shows the markers and transitions them to visible.
83792
83793
83794           function layerOn() {
83795             editOn();
83796             drawLayer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end interrupt', function () {
83797               return dispatch.call('change');
83798             });
83799           } // Disable the layer.  This transitions the layer invisible and then hides the markers.
83800
83801
83802           function layerOff() {
83803             throttledRedraw.cancel();
83804             drawLayer.interrupt();
83805             touchLayer.selectAll('.qaItem.improveOSM').remove();
83806             drawLayer.transition().duration(250).style('opacity', 0).on('end interrupt', function () {
83807               editOff();
83808               dispatch.call('change');
83809             });
83810           } // Update the issue markers
83811
83812
83813           function updateMarkers() {
83814             if (!layerVisible || !_layerEnabled$1) return;
83815             var service = getService();
83816             var selectedID = context.selectedErrorID();
83817             var data = service ? service.getItems(projection) : [];
83818             var getTransform = svgPointTransform(projection); // Draw markers..
83819
83820             var markers = drawLayer.selectAll('.qaItem.improveOSM').data(data, function (d) {
83821               return d.id;
83822             }); // exit
83823
83824             markers.exit().remove(); // enter
83825
83826             var markersEnter = markers.enter().append('g').attr('class', function (d) {
83827               return "qaItem ".concat(d.service, " itemId-").concat(d.id, " itemType-").concat(d.itemType);
83828             });
83829             markersEnter.append('polygon').call(markerPath, 'shadow');
83830             markersEnter.append('ellipse').attr('cx', 0).attr('cy', 0).attr('rx', 4.5).attr('ry', 2).attr('class', 'stroke');
83831             markersEnter.append('polygon').attr('fill', 'currentColor').call(markerPath, 'qaItem-fill');
83832             markersEnter.append('use').attr('transform', 'translate(-6.5, -23)').attr('class', 'icon-annotation').attr('width', '13px').attr('height', '13px').attr('xlink:href', function (d) {
83833               var picon = d.icon;
83834
83835               if (!picon) {
83836                 return '';
83837               } else {
83838                 var isMaki = /^maki-/.test(picon);
83839                 return "#".concat(picon).concat(isMaki ? '-11' : '');
83840               }
83841             }); // update
83842
83843             markers.merge(markersEnter).sort(sortY).classed('selected', function (d) {
83844               return d.id === selectedID;
83845             }).attr('transform', getTransform); // Draw targets..
83846
83847             if (touchLayer.empty()) return;
83848             var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
83849             var targets = touchLayer.selectAll('.qaItem.improveOSM').data(data, function (d) {
83850               return d.id;
83851             }); // exit
83852
83853             targets.exit().remove(); // enter/update
83854
83855             targets.enter().append('rect').attr('width', '20px').attr('height', '30px').attr('x', '-10px').attr('y', '-28px').merge(targets).sort(sortY).attr('class', function (d) {
83856               return "qaItem ".concat(d.service, " target ").concat(fillClass, " itemId-").concat(d.id);
83857             }).attr('transform', getTransform);
83858
83859             function sortY(a, b) {
83860               return a.id === selectedID ? 1 : b.id === selectedID ? -1 : b.loc[1] - a.loc[1];
83861             }
83862           } // Draw the ImproveOSM layer and schedule loading issues and updating markers.
83863
83864
83865           function drawImproveOSM(selection) {
83866             var service = getService();
83867             var surface = context.surface();
83868
83869             if (surface && !surface.empty()) {
83870               touchLayer = surface.selectAll('.data-layer.touch .layer-touch.markers');
83871             }
83872
83873             drawLayer = selection.selectAll('.layer-improveOSM').data(service ? [0] : []);
83874             drawLayer.exit().remove();
83875             drawLayer = drawLayer.enter().append('g').attr('class', 'layer-improveOSM').style('display', _layerEnabled$1 ? 'block' : 'none').merge(drawLayer);
83876
83877             if (_layerEnabled$1) {
83878               if (service && ~~context.map().zoom() >= minZoom) {
83879                 editOn();
83880                 service.loadIssues(projection);
83881                 updateMarkers();
83882               } else {
83883                 editOff();
83884               }
83885             }
83886           } // Toggles the layer on and off
83887
83888
83889           drawImproveOSM.enabled = function (val) {
83890             if (!arguments.length) return _layerEnabled$1;
83891             _layerEnabled$1 = val;
83892
83893             if (_layerEnabled$1) {
83894               layerOn();
83895             } else {
83896               layerOff();
83897
83898               if (context.selectedErrorID()) {
83899                 context.enter(modeBrowse(context));
83900               }
83901             }
83902
83903             dispatch.call('change');
83904             return this;
83905           };
83906
83907           drawImproveOSM.supported = function () {
83908             return !!getService();
83909           };
83910
83911           return drawImproveOSM;
83912         }
83913
83914         var _layerEnabled = false;
83915
83916         var _qaService;
83917
83918         function svgOsmose(projection, context, dispatch) {
83919           var throttledRedraw = throttle(function () {
83920             return dispatch.call('change');
83921           }, 1000);
83922
83923           var minZoom = 12;
83924           var touchLayer = select(null);
83925           var drawLayer = select(null);
83926           var layerVisible = false;
83927
83928           function markerPath(selection, klass) {
83929             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');
83930           } // Loosely-coupled osmose service for fetching issues
83931
83932
83933           function getService() {
83934             if (services.osmose && !_qaService) {
83935               _qaService = services.osmose;
83936
83937               _qaService.on('loaded', throttledRedraw);
83938             } else if (!services.osmose && _qaService) {
83939               _qaService = null;
83940             }
83941
83942             return _qaService;
83943           } // Show the markers
83944
83945
83946           function editOn() {
83947             if (!layerVisible) {
83948               layerVisible = true;
83949               drawLayer.style('display', 'block');
83950             }
83951           } // Immediately remove the markers and their touch targets
83952
83953
83954           function editOff() {
83955             if (layerVisible) {
83956               layerVisible = false;
83957               drawLayer.style('display', 'none');
83958               drawLayer.selectAll('.qaItem.osmose').remove();
83959               touchLayer.selectAll('.qaItem.osmose').remove();
83960             }
83961           } // Enable the layer.  This shows the markers and transitions them to visible.
83962
83963
83964           function layerOn() {
83965             editOn();
83966             drawLayer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end interrupt', function () {
83967               return dispatch.call('change');
83968             });
83969           } // Disable the layer.  This transitions the layer invisible and then hides the markers.
83970
83971
83972           function layerOff() {
83973             throttledRedraw.cancel();
83974             drawLayer.interrupt();
83975             touchLayer.selectAll('.qaItem.osmose').remove();
83976             drawLayer.transition().duration(250).style('opacity', 0).on('end interrupt', function () {
83977               editOff();
83978               dispatch.call('change');
83979             });
83980           } // Update the issue markers
83981
83982
83983           function updateMarkers() {
83984             if (!layerVisible || !_layerEnabled) return;
83985             var service = getService();
83986             var selectedID = context.selectedErrorID();
83987             var data = service ? service.getItems(projection) : [];
83988             var getTransform = svgPointTransform(projection); // Draw markers..
83989
83990             var markers = drawLayer.selectAll('.qaItem.osmose').data(data, function (d) {
83991               return d.id;
83992             }); // exit
83993
83994             markers.exit().remove(); // enter
83995
83996             var markersEnter = markers.enter().append('g').attr('class', function (d) {
83997               return "qaItem ".concat(d.service, " itemId-").concat(d.id, " itemType-").concat(d.itemType);
83998             });
83999             markersEnter.append('polygon').call(markerPath, 'shadow');
84000             markersEnter.append('ellipse').attr('cx', 0).attr('cy', 0).attr('rx', 4.5).attr('ry', 2).attr('class', 'stroke');
84001             markersEnter.append('polygon').attr('fill', function (d) {
84002               return service.getColor(d.item);
84003             }).call(markerPath, 'qaItem-fill');
84004             markersEnter.append('use').attr('transform', 'translate(-6.5, -23)').attr('class', 'icon-annotation').attr('width', '13px').attr('height', '13px').attr('xlink:href', function (d) {
84005               var picon = d.icon;
84006
84007               if (!picon) {
84008                 return '';
84009               } else {
84010                 var isMaki = /^maki-/.test(picon);
84011                 return "#".concat(picon).concat(isMaki ? '-11' : '');
84012               }
84013             }); // update
84014
84015             markers.merge(markersEnter).sort(sortY).classed('selected', function (d) {
84016               return d.id === selectedID;
84017             }).attr('transform', getTransform); // Draw targets..
84018
84019             if (touchLayer.empty()) return;
84020             var fillClass = context.getDebug('target') ? 'pink' : 'nocolor';
84021             var targets = touchLayer.selectAll('.qaItem.osmose').data(data, function (d) {
84022               return d.id;
84023             }); // exit
84024
84025             targets.exit().remove(); // enter/update
84026
84027             targets.enter().append('rect').attr('width', '20px').attr('height', '30px').attr('x', '-10px').attr('y', '-28px').merge(targets).sort(sortY).attr('class', function (d) {
84028               return "qaItem ".concat(d.service, " target ").concat(fillClass, " itemId-").concat(d.id);
84029             }).attr('transform', getTransform);
84030
84031             function sortY(a, b) {
84032               return a.id === selectedID ? 1 : b.id === selectedID ? -1 : b.loc[1] - a.loc[1];
84033             }
84034           } // Draw the Osmose layer and schedule loading issues and updating markers.
84035
84036
84037           function drawOsmose(selection) {
84038             var service = getService();
84039             var surface = context.surface();
84040
84041             if (surface && !surface.empty()) {
84042               touchLayer = surface.selectAll('.data-layer.touch .layer-touch.markers');
84043             }
84044
84045             drawLayer = selection.selectAll('.layer-osmose').data(service ? [0] : []);
84046             drawLayer.exit().remove();
84047             drawLayer = drawLayer.enter().append('g').attr('class', 'layer-osmose').style('display', _layerEnabled ? 'block' : 'none').merge(drawLayer);
84048
84049             if (_layerEnabled) {
84050               if (service && ~~context.map().zoom() >= minZoom) {
84051                 editOn();
84052                 service.loadIssues(projection);
84053                 updateMarkers();
84054               } else {
84055                 editOff();
84056               }
84057             }
84058           } // Toggles the layer on and off
84059
84060
84061           drawOsmose.enabled = function (val) {
84062             if (!arguments.length) return _layerEnabled;
84063             _layerEnabled = val;
84064
84065             if (_layerEnabled) {
84066               // Strings supplied by Osmose fetched before showing layer for first time
84067               // NOTE: Currently no way to change locale in iD at runtime, would need to re-call this method if that's ever implemented
84068               // Also, If layer is toggled quickly multiple requests are sent
84069               getService().loadStrings().then(layerOn)["catch"](function (err) {
84070                 console.log(err); // eslint-disable-line no-console
84071               });
84072             } else {
84073               layerOff();
84074
84075               if (context.selectedErrorID()) {
84076                 context.enter(modeBrowse(context));
84077               }
84078             }
84079
84080             dispatch.call('change');
84081             return this;
84082           };
84083
84084           drawOsmose.supported = function () {
84085             return !!getService();
84086           };
84087
84088           return drawOsmose;
84089         }
84090
84091         function svgStreetside(projection, context, dispatch) {
84092           var throttledRedraw = throttle(function () {
84093             dispatch.call('change');
84094           }, 1000);
84095
84096           var minZoom = 14;
84097           var minMarkerZoom = 16;
84098           var minViewfieldZoom = 18;
84099           var layer = select(null);
84100           var _viewerYaw = 0;
84101           var _selectedSequence = null;
84102
84103           var _streetside;
84104           /**
84105            * init().
84106            */
84107
84108
84109           function init() {
84110             if (svgStreetside.initialized) return; // run once
84111
84112             svgStreetside.enabled = false;
84113             svgStreetside.initialized = true;
84114           }
84115           /**
84116            * getService().
84117            */
84118
84119
84120           function getService() {
84121             if (services.streetside && !_streetside) {
84122               _streetside = services.streetside;
84123
84124               _streetside.event.on('viewerChanged.svgStreetside', viewerChanged).on('loadedImages.svgStreetside', throttledRedraw);
84125             } else if (!services.streetside && _streetside) {
84126               _streetside = null;
84127             }
84128
84129             return _streetside;
84130           }
84131           /**
84132            * showLayer().
84133            */
84134
84135
84136           function showLayer() {
84137             var service = getService();
84138             if (!service) return;
84139             editOn();
84140             layer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end', function () {
84141               dispatch.call('change');
84142             });
84143           }
84144           /**
84145            * hideLayer().
84146            */
84147
84148
84149           function hideLayer() {
84150             throttledRedraw.cancel();
84151             layer.transition().duration(250).style('opacity', 0).on('end', editOff);
84152           }
84153           /**
84154            * editOn().
84155            */
84156
84157
84158           function editOn() {
84159             layer.style('display', 'block');
84160           }
84161           /**
84162            * editOff().
84163            */
84164
84165
84166           function editOff() {
84167             layer.selectAll('.viewfield-group').remove();
84168             layer.style('display', 'none');
84169           }
84170           /**
84171            * click() Handles 'bubble' point click event.
84172            */
84173
84174
84175           function click(d3_event, d) {
84176             var service = getService();
84177             if (!service) return; // try to preserve the viewer rotation when staying on the same sequence
84178
84179             if (d.sequenceKey !== _selectedSequence) {
84180               _viewerYaw = 0; // reset
84181             }
84182
84183             _selectedSequence = d.sequenceKey;
84184             service.ensureViewerLoaded(context).then(function () {
84185               service.selectImage(context, d.key).yaw(_viewerYaw).showViewer(context);
84186             });
84187             context.map().centerEase(d.loc);
84188           }
84189           /**
84190            * mouseover().
84191            */
84192
84193
84194           function mouseover(d3_event, d) {
84195             var service = getService();
84196             if (service) service.setStyles(context, d);
84197           }
84198           /**
84199            * mouseout().
84200            */
84201
84202
84203           function mouseout() {
84204             var service = getService();
84205             if (service) service.setStyles(context, null);
84206           }
84207           /**
84208            * transform().
84209            */
84210
84211
84212           function transform(d) {
84213             var t = svgPointTransform(projection)(d);
84214             var rot = d.ca + _viewerYaw;
84215
84216             if (rot) {
84217               t += ' rotate(' + Math.floor(rot) + ',0,0)';
84218             }
84219
84220             return t;
84221           }
84222
84223           function viewerChanged() {
84224             var service = getService();
84225             if (!service) return;
84226             var viewer = service.viewer();
84227             if (!viewer) return; // update viewfield rotation
84228
84229             _viewerYaw = viewer.getYaw(); // avoid updating if the map is currently transformed
84230             // e.g. during drags or easing.
84231
84232             if (context.map().isTransformed()) return;
84233             layer.selectAll('.viewfield-group.currentView').attr('transform', transform);
84234           }
84235
84236           function filterBubbles(bubbles) {
84237             var fromDate = context.photos().fromDate();
84238             var toDate = context.photos().toDate();
84239             var usernames = context.photos().usernames();
84240
84241             if (fromDate) {
84242               var fromTimestamp = new Date(fromDate).getTime();
84243               bubbles = bubbles.filter(function (bubble) {
84244                 return new Date(bubble.captured_at).getTime() >= fromTimestamp;
84245               });
84246             }
84247
84248             if (toDate) {
84249               var toTimestamp = new Date(toDate).getTime();
84250               bubbles = bubbles.filter(function (bubble) {
84251                 return new Date(bubble.captured_at).getTime() <= toTimestamp;
84252               });
84253             }
84254
84255             if (usernames) {
84256               bubbles = bubbles.filter(function (bubble) {
84257                 return usernames.indexOf(bubble.captured_by) !== -1;
84258               });
84259             }
84260
84261             return bubbles;
84262           }
84263
84264           function filterSequences(sequences) {
84265             var fromDate = context.photos().fromDate();
84266             var toDate = context.photos().toDate();
84267             var usernames = context.photos().usernames();
84268
84269             if (fromDate) {
84270               var fromTimestamp = new Date(fromDate).getTime();
84271               sequences = sequences.filter(function (sequences) {
84272                 return new Date(sequences.properties.captured_at).getTime() >= fromTimestamp;
84273               });
84274             }
84275
84276             if (toDate) {
84277               var toTimestamp = new Date(toDate).getTime();
84278               sequences = sequences.filter(function (sequences) {
84279                 return new Date(sequences.properties.captured_at).getTime() <= toTimestamp;
84280               });
84281             }
84282
84283             if (usernames) {
84284               sequences = sequences.filter(function (sequences) {
84285                 return usernames.indexOf(sequences.properties.captured_by) !== -1;
84286               });
84287             }
84288
84289             return sequences;
84290           }
84291           /**
84292            * update().
84293            */
84294
84295
84296           function update() {
84297             var viewer = context.container().select('.photoviewer');
84298             var selected = viewer.empty() ? undefined : viewer.datum();
84299             var z = ~~context.map().zoom();
84300             var showMarkers = z >= minMarkerZoom;
84301             var showViewfields = z >= minViewfieldZoom;
84302             var service = getService();
84303             var sequences = [];
84304             var bubbles = [];
84305
84306             if (context.photos().showsPanoramic()) {
84307               sequences = service ? service.sequences(projection) : [];
84308               bubbles = service && showMarkers ? service.bubbles(projection) : [];
84309               sequences = filterSequences(sequences);
84310               bubbles = filterBubbles(bubbles);
84311             }
84312
84313             var traces = layer.selectAll('.sequences').selectAll('.sequence').data(sequences, function (d) {
84314               return d.properties.key;
84315             }); // exit
84316
84317             traces.exit().remove(); // enter/update
84318
84319             traces = traces.enter().append('path').attr('class', 'sequence').merge(traces).attr('d', svgPath(projection).geojson);
84320             var groups = layer.selectAll('.markers').selectAll('.viewfield-group').data(bubbles, function (d) {
84321               // force reenter once bubbles are attached to a sequence
84322               return d.key + (d.sequenceKey ? 'v1' : 'v0');
84323             }); // exit
84324
84325             groups.exit().remove(); // enter
84326
84327             var groupsEnter = groups.enter().append('g').attr('class', 'viewfield-group').on('mouseenter', mouseover).on('mouseleave', mouseout).on('click', click);
84328             groupsEnter.append('g').attr('class', 'viewfield-scale'); // update
84329
84330             var markers = groups.merge(groupsEnter).sort(function (a, b) {
84331               return a === selected ? 1 : b === selected ? -1 : b.loc[1] - a.loc[1];
84332             }).attr('transform', transform).select('.viewfield-scale');
84333             markers.selectAll('circle').data([0]).enter().append('circle').attr('dx', '0').attr('dy', '0').attr('r', '6');
84334             var viewfields = markers.selectAll('.viewfield').data(showViewfields ? [0] : []);
84335             viewfields.exit().remove(); // viewfields may or may not be drawn...
84336             // but if they are, draw below the circles
84337
84338             viewfields.enter().insert('path', 'circle').attr('class', 'viewfield').attr('transform', 'scale(1.5,1.5),translate(-8, -13)').attr('d', viewfieldPath);
84339
84340             function viewfieldPath() {
84341               var d = this.parentNode.__data__;
84342
84343               if (d.pano) {
84344                 return 'M 8,13 m -10,0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0';
84345               } else {
84346                 return 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z';
84347               }
84348             }
84349           }
84350           /**
84351            * drawImages()
84352            * drawImages is the method that is returned (and that runs) every time 'svgStreetside()' is called.
84353            * 'svgStreetside()' is called from index.js
84354            */
84355
84356
84357           function drawImages(selection) {
84358             var enabled = svgStreetside.enabled;
84359             var service = getService();
84360             layer = selection.selectAll('.layer-streetside-images').data(service ? [0] : []);
84361             layer.exit().remove();
84362             var layerEnter = layer.enter().append('g').attr('class', 'layer-streetside-images').style('display', enabled ? 'block' : 'none');
84363             layerEnter.append('g').attr('class', 'sequences');
84364             layerEnter.append('g').attr('class', 'markers');
84365             layer = layerEnter.merge(layer);
84366
84367             if (enabled) {
84368               if (service && ~~context.map().zoom() >= minZoom) {
84369                 editOn();
84370                 update();
84371                 service.loadBubbles(projection);
84372               } else {
84373                 editOff();
84374               }
84375             }
84376           }
84377           /**
84378            * drawImages.enabled().
84379            */
84380
84381
84382           drawImages.enabled = function (_) {
84383             if (!arguments.length) return svgStreetside.enabled;
84384             svgStreetside.enabled = _;
84385
84386             if (svgStreetside.enabled) {
84387               showLayer();
84388               context.photos().on('change.streetside', update);
84389             } else {
84390               hideLayer();
84391               context.photos().on('change.streetside', null);
84392             }
84393
84394             dispatch.call('change');
84395             return this;
84396           };
84397           /**
84398            * drawImages.supported().
84399            */
84400
84401
84402           drawImages.supported = function () {
84403             return !!getService();
84404           };
84405
84406           init();
84407           return drawImages;
84408         }
84409
84410         function svgMapillaryImages(projection, context, dispatch) {
84411           var throttledRedraw = throttle(function () {
84412             dispatch.call('change');
84413           }, 1000);
84414
84415           var minZoom = 12;
84416           var minMarkerZoom = 16;
84417           var minViewfieldZoom = 18;
84418           var layer = select(null);
84419
84420           var _mapillary;
84421
84422           function init() {
84423             if (svgMapillaryImages.initialized) return; // run once
84424
84425             svgMapillaryImages.enabled = false;
84426             svgMapillaryImages.initialized = true;
84427           }
84428
84429           function getService() {
84430             if (services.mapillary && !_mapillary) {
84431               _mapillary = services.mapillary;
84432
84433               _mapillary.event.on('loadedImages', throttledRedraw);
84434             } else if (!services.mapillary && _mapillary) {
84435               _mapillary = null;
84436             }
84437
84438             return _mapillary;
84439           }
84440
84441           function showLayer() {
84442             var service = getService();
84443             if (!service) return;
84444             editOn();
84445             layer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end', function () {
84446               dispatch.call('change');
84447             });
84448           }
84449
84450           function hideLayer() {
84451             throttledRedraw.cancel();
84452             layer.transition().duration(250).style('opacity', 0).on('end', editOff);
84453           }
84454
84455           function editOn() {
84456             layer.style('display', 'block');
84457           }
84458
84459           function editOff() {
84460             layer.selectAll('.viewfield-group').remove();
84461             layer.style('display', 'none');
84462           }
84463
84464           function click(d3_event, image) {
84465             var service = getService();
84466             if (!service) return;
84467             service.ensureViewerLoaded(context).then(function () {
84468               service.selectImage(context, image.id).showViewer(context);
84469             });
84470             context.map().centerEase(image.loc);
84471           }
84472
84473           function mouseover(d3_event, image) {
84474             var service = getService();
84475             if (service) service.setStyles(context, image);
84476           }
84477
84478           function mouseout() {
84479             var service = getService();
84480             if (service) service.setStyles(context, null);
84481           }
84482
84483           function transform(d) {
84484             var t = svgPointTransform(projection)(d);
84485
84486             if (d.ca) {
84487               t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
84488             }
84489
84490             return t;
84491           }
84492
84493           function filterImages(images) {
84494             var showsPano = context.photos().showsPanoramic();
84495             var showsFlat = context.photos().showsFlat();
84496             var fromDate = context.photos().fromDate();
84497             var toDate = context.photos().toDate();
84498
84499             if (!showsPano || !showsFlat) {
84500               images = images.filter(function (image) {
84501                 if (image.is_pano) return showsPano;
84502                 return showsFlat;
84503               });
84504             }
84505
84506             if (fromDate) {
84507               images = images.filter(function (image) {
84508                 return new Date(image.captured_at).getTime() >= new Date(fromDate).getTime();
84509               });
84510             }
84511
84512             if (toDate) {
84513               images = images.filter(function (image) {
84514                 return new Date(image.captured_at).getTime() <= new Date(toDate).getTime();
84515               });
84516             }
84517
84518             return images;
84519           }
84520
84521           function filterSequences(sequences) {
84522             var showsPano = context.photos().showsPanoramic();
84523             var showsFlat = context.photos().showsFlat();
84524             var fromDate = context.photos().fromDate();
84525             var toDate = context.photos().toDate();
84526
84527             if (!showsPano || !showsFlat) {
84528               sequences = sequences.filter(function (sequence) {
84529                 if (sequence.properties.hasOwnProperty('is_pano')) {
84530                   if (sequence.properties.is_pano) return showsPano;
84531                   return showsFlat;
84532                 }
84533
84534                 return false;
84535               });
84536             }
84537
84538             if (fromDate) {
84539               sequences = sequences.filter(function (sequence) {
84540                 return new Date(sequence.properties.captured_at).getTime() >= new Date(fromDate).getTime().toString();
84541               });
84542             }
84543
84544             if (toDate) {
84545               sequences = sequences.filter(function (sequence) {
84546                 return new Date(sequence.properties.captured_at).getTime() <= new Date(toDate).getTime().toString();
84547               });
84548             }
84549
84550             return sequences;
84551           }
84552
84553           function update() {
84554             var z = ~~context.map().zoom();
84555             var showMarkers = z >= minMarkerZoom;
84556             var showViewfields = z >= minViewfieldZoom;
84557             var service = getService();
84558             var sequences = service ? service.sequences(projection) : [];
84559             var images = service && showMarkers ? service.images(projection) : [];
84560             images = filterImages(images);
84561             sequences = filterSequences(sequences);
84562             service.filterViewer(context);
84563             var traces = layer.selectAll('.sequences').selectAll('.sequence').data(sequences, function (d) {
84564               return d.properties.id;
84565             }); // exit
84566
84567             traces.exit().remove(); // enter/update
84568
84569             traces = traces.enter().append('path').attr('class', 'sequence').merge(traces).attr('d', svgPath(projection).geojson);
84570             var groups = layer.selectAll('.markers').selectAll('.viewfield-group').data(images, function (d) {
84571               return d.id;
84572             }); // exit
84573
84574             groups.exit().remove(); // enter
84575
84576             var groupsEnter = groups.enter().append('g').attr('class', 'viewfield-group').on('mouseenter', mouseover).on('mouseleave', mouseout).on('click', click);
84577             groupsEnter.append('g').attr('class', 'viewfield-scale'); // update
84578
84579             var markers = groups.merge(groupsEnter).sort(function (a, b) {
84580               return b.loc[1] - a.loc[1]; // sort Y
84581             }).attr('transform', transform).select('.viewfield-scale');
84582             markers.selectAll('circle').data([0]).enter().append('circle').attr('dx', '0').attr('dy', '0').attr('r', '6');
84583             var viewfields = markers.selectAll('.viewfield').data(showViewfields ? [0] : []);
84584             viewfields.exit().remove();
84585             viewfields.enter() // viewfields may or may not be drawn...
84586             .insert('path', 'circle') // but if they are, draw below the circles
84587             .attr('class', 'viewfield').classed('pano', function () {
84588               return this.parentNode.__data__.is_pano;
84589             }).attr('transform', 'scale(1.5,1.5),translate(-8, -13)').attr('d', viewfieldPath);
84590
84591             function viewfieldPath() {
84592               if (this.parentNode.__data__.is_pano) {
84593                 return 'M 8,13 m -10,0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0';
84594               } else {
84595                 return 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z';
84596               }
84597             }
84598           }
84599
84600           function drawImages(selection) {
84601             var enabled = svgMapillaryImages.enabled;
84602             var service = getService();
84603             layer = selection.selectAll('.layer-mapillary').data(service ? [0] : []);
84604             layer.exit().remove();
84605             var layerEnter = layer.enter().append('g').attr('class', 'layer-mapillary').style('display', enabled ? 'block' : 'none');
84606             layerEnter.append('g').attr('class', 'sequences');
84607             layerEnter.append('g').attr('class', 'markers');
84608             layer = layerEnter.merge(layer);
84609
84610             if (enabled) {
84611               if (service && ~~context.map().zoom() >= minZoom) {
84612                 editOn();
84613                 update();
84614                 service.loadImages(projection);
84615               } else {
84616                 editOff();
84617               }
84618             }
84619           }
84620
84621           drawImages.enabled = function (_) {
84622             if (!arguments.length) return svgMapillaryImages.enabled;
84623             svgMapillaryImages.enabled = _;
84624
84625             if (svgMapillaryImages.enabled) {
84626               showLayer();
84627               context.photos().on('change.mapillary_images', update);
84628             } else {
84629               hideLayer();
84630               context.photos().on('change.mapillary_images', null);
84631             }
84632
84633             dispatch.call('change');
84634             return this;
84635           };
84636
84637           drawImages.supported = function () {
84638             return !!getService();
84639           };
84640
84641           init();
84642           return drawImages;
84643         }
84644
84645         function svgMapillaryPosition(projection, context) {
84646           var throttledRedraw = throttle(function () {
84647             update();
84648           }, 1000);
84649
84650           var minZoom = 12;
84651           var minViewfieldZoom = 18;
84652           var layer = select(null);
84653
84654           var _mapillary;
84655
84656           var viewerCompassAngle;
84657
84658           function init() {
84659             if (svgMapillaryPosition.initialized) return; // run once
84660
84661             svgMapillaryPosition.initialized = true;
84662           }
84663
84664           function getService() {
84665             if (services.mapillary && !_mapillary) {
84666               _mapillary = services.mapillary;
84667
84668               _mapillary.event.on('imageChanged', throttledRedraw);
84669
84670               _mapillary.event.on('bearingChanged', function (e) {
84671                 viewerCompassAngle = e.bearing;
84672                 if (context.map().isTransformed()) return;
84673                 layer.selectAll('.viewfield-group.currentView').filter(function (d) {
84674                   return d.is_pano;
84675                 }).attr('transform', transform);
84676               });
84677             } else if (!services.mapillary && _mapillary) {
84678               _mapillary = null;
84679             }
84680
84681             return _mapillary;
84682           }
84683
84684           function editOn() {
84685             layer.style('display', 'block');
84686           }
84687
84688           function editOff() {
84689             layer.selectAll('.viewfield-group').remove();
84690             layer.style('display', 'none');
84691           }
84692
84693           function transform(d) {
84694             var t = svgPointTransform(projection)(d);
84695
84696             if (d.is_pano && viewerCompassAngle !== null && isFinite(viewerCompassAngle)) {
84697               t += ' rotate(' + Math.floor(viewerCompassAngle) + ',0,0)';
84698             } else if (d.ca) {
84699               t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
84700             }
84701
84702             return t;
84703           }
84704
84705           function update() {
84706             var z = ~~context.map().zoom();
84707             var showViewfields = z >= minViewfieldZoom;
84708             var service = getService();
84709             var image = service && service.getActiveImage();
84710             var groups = layer.selectAll('.markers').selectAll('.viewfield-group').data(image ? [image] : [], function (d) {
84711               return d.id;
84712             }); // exit
84713
84714             groups.exit().remove(); // enter
84715
84716             var groupsEnter = groups.enter().append('g').attr('class', 'viewfield-group currentView highlighted');
84717             groupsEnter.append('g').attr('class', 'viewfield-scale'); // update
84718
84719             var markers = groups.merge(groupsEnter).attr('transform', transform).select('.viewfield-scale');
84720             markers.selectAll('circle').data([0]).enter().append('circle').attr('dx', '0').attr('dy', '0').attr('r', '6');
84721             var viewfields = markers.selectAll('.viewfield').data(showViewfields ? [0] : []);
84722             viewfields.exit().remove();
84723             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');
84724           }
84725
84726           function drawImages(selection) {
84727             var service = getService();
84728             layer = selection.selectAll('.layer-mapillary-position').data(service ? [0] : []);
84729             layer.exit().remove();
84730             var layerEnter = layer.enter().append('g').attr('class', 'layer-mapillary-position');
84731             layerEnter.append('g').attr('class', 'markers');
84732             layer = layerEnter.merge(layer);
84733
84734             if (service && ~~context.map().zoom() >= minZoom) {
84735               editOn();
84736               update();
84737             } else {
84738               editOff();
84739             }
84740           }
84741
84742           drawImages.enabled = function () {
84743             update();
84744             return this;
84745           };
84746
84747           drawImages.supported = function () {
84748             return !!getService();
84749           };
84750
84751           init();
84752           return drawImages;
84753         }
84754
84755         function svgMapillarySigns(projection, context, dispatch) {
84756           var throttledRedraw = throttle(function () {
84757             dispatch.call('change');
84758           }, 1000);
84759
84760           var minZoom = 12;
84761           var layer = select(null);
84762
84763           var _mapillary;
84764
84765           function init() {
84766             if (svgMapillarySigns.initialized) return; // run once
84767
84768             svgMapillarySigns.enabled = false;
84769             svgMapillarySigns.initialized = true;
84770           }
84771
84772           function getService() {
84773             if (services.mapillary && !_mapillary) {
84774               _mapillary = services.mapillary;
84775
84776               _mapillary.event.on('loadedSigns', throttledRedraw);
84777             } else if (!services.mapillary && _mapillary) {
84778               _mapillary = null;
84779             }
84780
84781             return _mapillary;
84782           }
84783
84784           function showLayer() {
84785             var service = getService();
84786             if (!service) return;
84787             service.loadSignResources(context);
84788             editOn();
84789           }
84790
84791           function hideLayer() {
84792             throttledRedraw.cancel();
84793             editOff();
84794           }
84795
84796           function editOn() {
84797             layer.style('display', 'block');
84798           }
84799
84800           function editOff() {
84801             layer.selectAll('.icon-sign').remove();
84802             layer.style('display', 'none');
84803           }
84804
84805           function click(d3_event, d) {
84806             var service = getService();
84807             if (!service) return;
84808             context.map().centerEase(d.loc);
84809             var selectedImageId = service.getActiveImage() && service.getActiveImage().id;
84810             service.getDetections(d.id).then(function (detections) {
84811               if (detections.length) {
84812                 var imageId = detections[0].image.id;
84813
84814                 if (imageId === selectedImageId) {
84815                   service.highlightDetection(detections[0]).selectImage(context, imageId);
84816                 } else {
84817                   service.ensureViewerLoaded(context).then(function () {
84818                     service.highlightDetection(detections[0]).selectImage(context, imageId).showViewer(context);
84819                   });
84820                 }
84821               }
84822             });
84823           }
84824
84825           function filterData(detectedFeatures) {
84826             var fromDate = context.photos().fromDate();
84827             var toDate = context.photos().toDate();
84828
84829             if (fromDate) {
84830               var fromTimestamp = new Date(fromDate).getTime();
84831               detectedFeatures = detectedFeatures.filter(function (feature) {
84832                 return new Date(feature.last_seen_at).getTime() >= fromTimestamp;
84833               });
84834             }
84835
84836             if (toDate) {
84837               var toTimestamp = new Date(toDate).getTime();
84838               detectedFeatures = detectedFeatures.filter(function (feature) {
84839                 return new Date(feature.first_seen_at).getTime() <= toTimestamp;
84840               });
84841             }
84842
84843             return detectedFeatures;
84844           }
84845
84846           function update() {
84847             var service = getService();
84848             var data = service ? service.signs(projection) : [];
84849             data = filterData(data);
84850             var transform = svgPointTransform(projection);
84851             var signs = layer.selectAll('.icon-sign').data(data, function (d) {
84852               return d.id;
84853             }); // exit
84854
84855             signs.exit().remove(); // enter
84856
84857             var enter = signs.enter().append('g').attr('class', 'icon-sign icon-detected').on('click', click);
84858             enter.append('use').attr('width', '24px').attr('height', '24px').attr('x', '-12px').attr('y', '-12px').attr('xlink:href', function (d) {
84859               return '#' + d.value;
84860             });
84861             enter.append('rect').attr('width', '24px').attr('height', '24px').attr('x', '-12px').attr('y', '-12px'); // update
84862
84863             signs.merge(enter).attr('transform', transform);
84864           }
84865
84866           function drawSigns(selection) {
84867             var enabled = svgMapillarySigns.enabled;
84868             var service = getService();
84869             layer = selection.selectAll('.layer-mapillary-signs').data(service ? [0] : []);
84870             layer.exit().remove();
84871             layer = layer.enter().append('g').attr('class', 'layer-mapillary-signs layer-mapillary-detections').style('display', enabled ? 'block' : 'none').merge(layer);
84872
84873             if (enabled) {
84874               if (service && ~~context.map().zoom() >= minZoom) {
84875                 editOn();
84876                 update();
84877                 service.loadSigns(projection);
84878                 service.showSignDetections(true);
84879               } else {
84880                 editOff();
84881               }
84882             } else if (service) {
84883               service.showSignDetections(false);
84884             }
84885           }
84886
84887           drawSigns.enabled = function (_) {
84888             if (!arguments.length) return svgMapillarySigns.enabled;
84889             svgMapillarySigns.enabled = _;
84890
84891             if (svgMapillarySigns.enabled) {
84892               showLayer();
84893               context.photos().on('change.mapillary_signs', update);
84894             } else {
84895               hideLayer();
84896               context.photos().on('change.mapillary_signs', null);
84897             }
84898
84899             dispatch.call('change');
84900             return this;
84901           };
84902
84903           drawSigns.supported = function () {
84904             return !!getService();
84905           };
84906
84907           init();
84908           return drawSigns;
84909         }
84910
84911         function svgMapillaryMapFeatures(projection, context, dispatch) {
84912           var throttledRedraw = throttle(function () {
84913             dispatch.call('change');
84914           }, 1000);
84915
84916           var minZoom = 12;
84917           var layer = select(null);
84918
84919           var _mapillary;
84920
84921           function init() {
84922             if (svgMapillaryMapFeatures.initialized) return; // run once
84923
84924             svgMapillaryMapFeatures.enabled = false;
84925             svgMapillaryMapFeatures.initialized = true;
84926           }
84927
84928           function getService() {
84929             if (services.mapillary && !_mapillary) {
84930               _mapillary = services.mapillary;
84931
84932               _mapillary.event.on('loadedMapFeatures', throttledRedraw);
84933             } else if (!services.mapillary && _mapillary) {
84934               _mapillary = null;
84935             }
84936
84937             return _mapillary;
84938           }
84939
84940           function showLayer() {
84941             var service = getService();
84942             if (!service) return;
84943             service.loadObjectResources(context);
84944             editOn();
84945           }
84946
84947           function hideLayer() {
84948             throttledRedraw.cancel();
84949             editOff();
84950           }
84951
84952           function editOn() {
84953             layer.style('display', 'block');
84954           }
84955
84956           function editOff() {
84957             layer.selectAll('.icon-map-feature').remove();
84958             layer.style('display', 'none');
84959           }
84960
84961           function click(d3_event, d) {
84962             var service = getService();
84963             if (!service) return;
84964             context.map().centerEase(d.loc);
84965             var selectedImageId = service.getActiveImage() && service.getActiveImage().id;
84966             service.getDetections(d.id).then(function (detections) {
84967               if (detections.length) {
84968                 var imageId = detections[0].image.id;
84969
84970                 if (imageId === selectedImageId) {
84971                   service.highlightDetection(detections[0]).selectImage(context, imageId);
84972                 } else {
84973                   service.ensureViewerLoaded(context).then(function () {
84974                     service.highlightDetection(detections[0]).selectImage(context, imageId).showViewer(context);
84975                   });
84976                 }
84977               }
84978             });
84979           }
84980
84981           function filterData(detectedFeatures) {
84982             var fromDate = context.photos().fromDate();
84983             var toDate = context.photos().toDate();
84984
84985             if (fromDate) {
84986               detectedFeatures = detectedFeatures.filter(function (feature) {
84987                 return new Date(feature.last_seen_at).getTime() >= new Date(fromDate).getTime();
84988               });
84989             }
84990
84991             if (toDate) {
84992               detectedFeatures = detectedFeatures.filter(function (feature) {
84993                 return new Date(feature.first_seen_at).getTime() <= new Date(toDate).getTime();
84994               });
84995             }
84996
84997             return detectedFeatures;
84998           }
84999
85000           function update() {
85001             var service = getService();
85002             var data = service ? service.mapFeatures(projection) : [];
85003             data = filterData(data);
85004             var transform = svgPointTransform(projection);
85005             var mapFeatures = layer.selectAll('.icon-map-feature').data(data, function (d) {
85006               return d.id;
85007             }); // exit
85008
85009             mapFeatures.exit().remove(); // enter
85010
85011             var enter = mapFeatures.enter().append('g').attr('class', 'icon-map-feature icon-detected').on('click', click);
85012             enter.append('title').text(function (d) {
85013               var id = d.value.replace(/--/g, '.').replace(/-/g, '_');
85014               return _t('mapillary_map_features.' + id);
85015             });
85016             enter.append('use').attr('width', '24px').attr('height', '24px').attr('x', '-12px').attr('y', '-12px').attr('xlink:href', function (d) {
85017               if (d.value === 'object--billboard') {
85018                 // no billboard icon right now, so use the advertisement icon
85019                 return '#object--sign--advertisement';
85020               }
85021
85022               return '#' + d.value;
85023             });
85024             enter.append('rect').attr('width', '24px').attr('height', '24px').attr('x', '-12px').attr('y', '-12px'); // update
85025
85026             mapFeatures.merge(enter).attr('transform', transform);
85027           }
85028
85029           function drawMapFeatures(selection) {
85030             var enabled = svgMapillaryMapFeatures.enabled;
85031             var service = getService();
85032             layer = selection.selectAll('.layer-mapillary-map-features').data(service ? [0] : []);
85033             layer.exit().remove();
85034             layer = layer.enter().append('g').attr('class', 'layer-mapillary-map-features layer-mapillary-detections').style('display', enabled ? 'block' : 'none').merge(layer);
85035
85036             if (enabled) {
85037               if (service && ~~context.map().zoom() >= minZoom) {
85038                 editOn();
85039                 update();
85040                 service.loadMapFeatures(projection);
85041                 service.showFeatureDetections(true);
85042               } else {
85043                 editOff();
85044               }
85045             } else if (service) {
85046               service.showFeatureDetections(false);
85047             }
85048           }
85049
85050           drawMapFeatures.enabled = function (_) {
85051             if (!arguments.length) return svgMapillaryMapFeatures.enabled;
85052             svgMapillaryMapFeatures.enabled = _;
85053
85054             if (svgMapillaryMapFeatures.enabled) {
85055               showLayer();
85056               context.photos().on('change.mapillary_map_features', update);
85057             } else {
85058               hideLayer();
85059               context.photos().on('change.mapillary_map_features', null);
85060             }
85061
85062             dispatch.call('change');
85063             return this;
85064           };
85065
85066           drawMapFeatures.supported = function () {
85067             return !!getService();
85068           };
85069
85070           init();
85071           return drawMapFeatures;
85072         }
85073
85074         function svgKartaviewImages(projection, context, dispatch) {
85075           var throttledRedraw = throttle(function () {
85076             dispatch.call('change');
85077           }, 1000);
85078
85079           var minZoom = 12;
85080           var minMarkerZoom = 16;
85081           var minViewfieldZoom = 18;
85082           var layer = select(null);
85083
85084           var _kartaview;
85085
85086           function init() {
85087             if (svgKartaviewImages.initialized) return; // run once
85088
85089             svgKartaviewImages.enabled = false;
85090             svgKartaviewImages.initialized = true;
85091           }
85092
85093           function getService() {
85094             if (services.kartaview && !_kartaview) {
85095               _kartaview = services.kartaview;
85096
85097               _kartaview.event.on('loadedImages', throttledRedraw);
85098             } else if (!services.kartaview && _kartaview) {
85099               _kartaview = null;
85100             }
85101
85102             return _kartaview;
85103           }
85104
85105           function showLayer() {
85106             var service = getService();
85107             if (!service) return;
85108             editOn();
85109             layer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end', function () {
85110               dispatch.call('change');
85111             });
85112           }
85113
85114           function hideLayer() {
85115             throttledRedraw.cancel();
85116             layer.transition().duration(250).style('opacity', 0).on('end', editOff);
85117           }
85118
85119           function editOn() {
85120             layer.style('display', 'block');
85121           }
85122
85123           function editOff() {
85124             layer.selectAll('.viewfield-group').remove();
85125             layer.style('display', 'none');
85126           }
85127
85128           function click(d3_event, d) {
85129             var service = getService();
85130             if (!service) return;
85131             service.ensureViewerLoaded(context).then(function () {
85132               service.selectImage(context, d.key).showViewer(context);
85133             });
85134             context.map().centerEase(d.loc);
85135           }
85136
85137           function mouseover(d3_event, d) {
85138             var service = getService();
85139             if (service) service.setStyles(context, d);
85140           }
85141
85142           function mouseout() {
85143             var service = getService();
85144             if (service) service.setStyles(context, null);
85145           }
85146
85147           function transform(d) {
85148             var t = svgPointTransform(projection)(d);
85149
85150             if (d.ca) {
85151               t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
85152             }
85153
85154             return t;
85155           }
85156
85157           function filterImages(images) {
85158             var fromDate = context.photos().fromDate();
85159             var toDate = context.photos().toDate();
85160             var usernames = context.photos().usernames();
85161
85162             if (fromDate) {
85163               var fromTimestamp = new Date(fromDate).getTime();
85164               images = images.filter(function (item) {
85165                 return new Date(item.captured_at).getTime() >= fromTimestamp;
85166               });
85167             }
85168
85169             if (toDate) {
85170               var toTimestamp = new Date(toDate).getTime();
85171               images = images.filter(function (item) {
85172                 return new Date(item.captured_at).getTime() <= toTimestamp;
85173               });
85174             }
85175
85176             if (usernames) {
85177               images = images.filter(function (item) {
85178                 return usernames.indexOf(item.captured_by) !== -1;
85179               });
85180             }
85181
85182             return images;
85183           }
85184
85185           function filterSequences(sequences) {
85186             var fromDate = context.photos().fromDate();
85187             var toDate = context.photos().toDate();
85188             var usernames = context.photos().usernames();
85189
85190             if (fromDate) {
85191               var fromTimestamp = new Date(fromDate).getTime();
85192               sequences = sequences.filter(function (image) {
85193                 return new Date(image.properties.captured_at).getTime() >= fromTimestamp;
85194               });
85195             }
85196
85197             if (toDate) {
85198               var toTimestamp = new Date(toDate).getTime();
85199               sequences = sequences.filter(function (image) {
85200                 return new Date(image.properties.captured_at).getTime() <= toTimestamp;
85201               });
85202             }
85203
85204             if (usernames) {
85205               sequences = sequences.filter(function (image) {
85206                 return usernames.indexOf(image.properties.captured_by) !== -1;
85207               });
85208             }
85209
85210             return sequences;
85211           }
85212
85213           function update() {
85214             var viewer = context.container().select('.photoviewer');
85215             var selected = viewer.empty() ? undefined : viewer.datum();
85216             var z = ~~context.map().zoom();
85217             var showMarkers = z >= minMarkerZoom;
85218             var showViewfields = z >= minViewfieldZoom;
85219             var service = getService();
85220             var sequences = [];
85221             var images = [];
85222
85223             if (context.photos().showsFlat()) {
85224               sequences = service ? service.sequences(projection) : [];
85225               images = service && showMarkers ? service.images(projection) : [];
85226               sequences = filterSequences(sequences);
85227               images = filterImages(images);
85228             }
85229
85230             var traces = layer.selectAll('.sequences').selectAll('.sequence').data(sequences, function (d) {
85231               return d.properties.key;
85232             }); // exit
85233
85234             traces.exit().remove(); // enter/update
85235
85236             traces = traces.enter().append('path').attr('class', 'sequence').merge(traces).attr('d', svgPath(projection).geojson);
85237             var groups = layer.selectAll('.markers').selectAll('.viewfield-group').data(images, function (d) {
85238               return d.key;
85239             }); // exit
85240
85241             groups.exit().remove(); // enter
85242
85243             var groupsEnter = groups.enter().append('g').attr('class', 'viewfield-group').on('mouseenter', mouseover).on('mouseleave', mouseout).on('click', click);
85244             groupsEnter.append('g').attr('class', 'viewfield-scale'); // update
85245
85246             var markers = groups.merge(groupsEnter).sort(function (a, b) {
85247               return a === selected ? 1 : b === selected ? -1 : b.loc[1] - a.loc[1]; // sort Y
85248             }).attr('transform', transform).select('.viewfield-scale');
85249             markers.selectAll('circle').data([0]).enter().append('circle').attr('dx', '0').attr('dy', '0').attr('r', '6');
85250             var viewfields = markers.selectAll('.viewfield').data(showViewfields ? [0] : []);
85251             viewfields.exit().remove();
85252             viewfields.enter() // viewfields may or may not be drawn...
85253             .insert('path', 'circle') // but if they are, draw below the circles
85254             .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');
85255           }
85256
85257           function drawImages(selection) {
85258             var enabled = svgKartaviewImages.enabled,
85259                 service = getService();
85260             layer = selection.selectAll('.layer-kartaview').data(service ? [0] : []);
85261             layer.exit().remove();
85262             var layerEnter = layer.enter().append('g').attr('class', 'layer-kartaview').style('display', enabled ? 'block' : 'none');
85263             layerEnter.append('g').attr('class', 'sequences');
85264             layerEnter.append('g').attr('class', 'markers');
85265             layer = layerEnter.merge(layer);
85266
85267             if (enabled) {
85268               if (service && ~~context.map().zoom() >= minZoom) {
85269                 editOn();
85270                 update();
85271                 service.loadImages(projection);
85272               } else {
85273                 editOff();
85274               }
85275             }
85276           }
85277
85278           drawImages.enabled = function (_) {
85279             if (!arguments.length) return svgKartaviewImages.enabled;
85280             svgKartaviewImages.enabled = _;
85281
85282             if (svgKartaviewImages.enabled) {
85283               showLayer();
85284               context.photos().on('change.kartaview_images', update);
85285             } else {
85286               hideLayer();
85287               context.photos().on('change.kartaview_images', null);
85288             }
85289
85290             dispatch.call('change');
85291             return this;
85292           };
85293
85294           drawImages.supported = function () {
85295             return !!getService();
85296           };
85297
85298           init();
85299           return drawImages;
85300         }
85301
85302         function svgOsm(projection, context, dispatch) {
85303           var enabled = true;
85304
85305           function drawOsm(selection) {
85306             selection.selectAll('.layer-osm').data(['covered', 'areas', 'lines', 'points', 'labels']).enter().append('g').attr('class', function (d) {
85307               return 'layer-osm ' + d;
85308             });
85309             selection.selectAll('.layer-osm.points').selectAll('.points-group').data(['points', 'midpoints', 'vertices', 'turns']).enter().append('g').attr('class', function (d) {
85310               return 'points-group ' + d;
85311             });
85312           }
85313
85314           function showLayer() {
85315             var layer = context.surface().selectAll('.data-layer.osm');
85316             layer.interrupt();
85317             layer.classed('disabled', false).style('opacity', 0).transition().duration(250).style('opacity', 1).on('end interrupt', function () {
85318               dispatch.call('change');
85319             });
85320           }
85321
85322           function hideLayer() {
85323             var layer = context.surface().selectAll('.data-layer.osm');
85324             layer.interrupt();
85325             layer.transition().duration(250).style('opacity', 0).on('end interrupt', function () {
85326               layer.classed('disabled', true);
85327               dispatch.call('change');
85328             });
85329           }
85330
85331           drawOsm.enabled = function (val) {
85332             if (!arguments.length) return enabled;
85333             enabled = val;
85334
85335             if (enabled) {
85336               showLayer();
85337             } else {
85338               hideLayer();
85339             }
85340
85341             dispatch.call('change');
85342             return this;
85343           };
85344
85345           return drawOsm;
85346         }
85347
85348         var _notesEnabled = false;
85349
85350         var _osmService;
85351
85352         function svgNotes(projection, context, dispatch) {
85353           if (!dispatch) {
85354             dispatch = dispatch$8('change');
85355           }
85356
85357           var throttledRedraw = throttle(function () {
85358             dispatch.call('change');
85359           }, 1000);
85360
85361           var minZoom = 12;
85362           var touchLayer = select(null);
85363           var drawLayer = select(null);
85364           var _notesVisible = false;
85365
85366           function markerPath(selection, klass) {
85367             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');
85368           } // Loosely-coupled osm service for fetching notes.
85369
85370
85371           function getService() {
85372             if (services.osm && !_osmService) {
85373               _osmService = services.osm;
85374
85375               _osmService.on('loadedNotes', throttledRedraw);
85376             } else if (!services.osm && _osmService) {
85377               _osmService = null;
85378             }
85379
85380             return _osmService;
85381           } // Show the notes
85382
85383
85384           function editOn() {
85385             if (!_notesVisible) {
85386               _notesVisible = true;
85387               drawLayer.style('display', 'block');
85388             }
85389           } // Immediately remove the notes and their touch targets
85390
85391
85392           function editOff() {
85393             if (_notesVisible) {
85394               _notesVisible = false;
85395               drawLayer.style('display', 'none');
85396               drawLayer.selectAll('.note').remove();
85397               touchLayer.selectAll('.note').remove();
85398             }
85399           } // Enable the layer.  This shows the notes and transitions them to visible.
85400
85401
85402           function layerOn() {
85403             editOn();
85404             drawLayer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end interrupt', function () {
85405               dispatch.call('change');
85406             });
85407           } // Disable the layer.  This transitions the layer invisible and then hides the notes.
85408
85409
85410           function layerOff() {
85411             throttledRedraw.cancel();
85412             drawLayer.interrupt();
85413             touchLayer.selectAll('.note').remove();
85414             drawLayer.transition().duration(250).style('opacity', 0).on('end interrupt', function () {
85415               editOff();
85416               dispatch.call('change');
85417             });
85418           } // Update the note markers
85419
85420
85421           function updateMarkers() {
85422             if (!_notesVisible || !_notesEnabled) return;
85423             var service = getService();
85424             var selectedID = context.selectedNoteID();
85425             var data = service ? service.notes(projection) : [];
85426             var getTransform = svgPointTransform(projection); // Draw markers..
85427
85428             var notes = drawLayer.selectAll('.note').data(data, function (d) {
85429               return d.status + d.id;
85430             }); // exit
85431
85432             notes.exit().remove(); // enter
85433
85434             var notesEnter = notes.enter().append('g').attr('class', function (d) {
85435               return 'note note-' + d.id + ' ' + d.status;
85436             }).classed('new', function (d) {
85437               return d.id < 0;
85438             });
85439             notesEnter.append('ellipse').attr('cx', 0.5).attr('cy', 1).attr('rx', 6.5).attr('ry', 3).attr('class', 'stroke');
85440             notesEnter.append('path').call(markerPath, 'shadow');
85441             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');
85442             notesEnter.selectAll('.icon-annotation').data(function (d) {
85443               return [d];
85444             }).enter().append('use').attr('class', 'icon-annotation').attr('width', '10px').attr('height', '10px').attr('x', '-3px').attr('y', '-19px').attr('xlink:href', function (d) {
85445               if (d.id < 0) return '#iD-icon-plus';
85446               if (d.status === 'open') return '#iD-icon-close';
85447               return '#iD-icon-apply';
85448             }); // update
85449
85450             notes.merge(notesEnter).sort(sortY).classed('selected', function (d) {
85451               var mode = context.mode();
85452               var isMoving = mode && mode.id === 'drag-note'; // no shadows when dragging
85453
85454               return !isMoving && d.id === selectedID;
85455             }).attr('transform', getTransform); // Draw targets..
85456
85457             if (touchLayer.empty()) return;
85458             var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
85459             var targets = touchLayer.selectAll('.note').data(data, function (d) {
85460               return d.id;
85461             }); // exit
85462
85463             targets.exit().remove(); // enter/update
85464
85465             targets.enter().append('rect').attr('width', '20px').attr('height', '20px').attr('x', '-8px').attr('y', '-22px').merge(targets).sort(sortY).attr('class', function (d) {
85466               var newClass = d.id < 0 ? 'new' : '';
85467               return 'note target note-' + d.id + ' ' + fillClass + newClass;
85468             }).attr('transform', getTransform);
85469
85470             function sortY(a, b) {
85471               if (a.id === selectedID) return 1;
85472               if (b.id === selectedID) return -1;
85473               return b.loc[1] - a.loc[1];
85474             }
85475           } // Draw the notes layer and schedule loading notes and updating markers.
85476
85477
85478           function drawNotes(selection) {
85479             var service = getService();
85480             var surface = context.surface();
85481
85482             if (surface && !surface.empty()) {
85483               touchLayer = surface.selectAll('.data-layer.touch .layer-touch.markers');
85484             }
85485
85486             drawLayer = selection.selectAll('.layer-notes').data(service ? [0] : []);
85487             drawLayer.exit().remove();
85488             drawLayer = drawLayer.enter().append('g').attr('class', 'layer-notes').style('display', _notesEnabled ? 'block' : 'none').merge(drawLayer);
85489
85490             if (_notesEnabled) {
85491               if (service && ~~context.map().zoom() >= minZoom) {
85492                 editOn();
85493                 service.loadNotes(projection);
85494                 updateMarkers();
85495               } else {
85496                 editOff();
85497               }
85498             }
85499           } // Toggles the layer on and off
85500
85501
85502           drawNotes.enabled = function (val) {
85503             if (!arguments.length) return _notesEnabled;
85504             _notesEnabled = val;
85505
85506             if (_notesEnabled) {
85507               layerOn();
85508             } else {
85509               layerOff();
85510
85511               if (context.selectedNoteID()) {
85512                 context.enter(modeBrowse(context));
85513               }
85514             }
85515
85516             dispatch.call('change');
85517             return this;
85518           };
85519
85520           return drawNotes;
85521         }
85522
85523         function svgTouch() {
85524           function drawTouch(selection) {
85525             selection.selectAll('.layer-touch').data(['areas', 'lines', 'points', 'turns', 'markers']).enter().append('g').attr('class', function (d) {
85526               return 'layer-touch ' + d;
85527             });
85528           }
85529
85530           return drawTouch;
85531         }
85532
85533         function refresh(selection, node) {
85534           var cr = node.getBoundingClientRect();
85535           var prop = [cr.width, cr.height];
85536           selection.property('__dimensions__', prop);
85537           return prop;
85538         }
85539
85540         function utilGetDimensions(selection, force) {
85541           if (!selection || selection.empty()) {
85542             return [0, 0];
85543           }
85544
85545           var node = selection.node(),
85546               cached = selection.property('__dimensions__');
85547           return !cached || force ? refresh(selection, node) : cached;
85548         }
85549         function utilSetDimensions(selection, dimensions) {
85550           if (!selection || selection.empty()) {
85551             return selection;
85552           }
85553
85554           var node = selection.node();
85555
85556           if (dimensions === null) {
85557             refresh(selection, node);
85558             return selection;
85559           }
85560
85561           return selection.property('__dimensions__', [dimensions[0], dimensions[1]]).attr('width', dimensions[0]).attr('height', dimensions[1]);
85562         }
85563
85564         function svgLayers(projection, context) {
85565           var dispatch = dispatch$8('change');
85566           var svg = select(null);
85567           var _layers = [{
85568             id: 'osm',
85569             layer: svgOsm(projection, context, dispatch)
85570           }, {
85571             id: 'notes',
85572             layer: svgNotes(projection, context, dispatch)
85573           }, {
85574             id: 'data',
85575             layer: svgData(projection, context, dispatch)
85576           }, {
85577             id: 'keepRight',
85578             layer: svgKeepRight(projection, context, dispatch)
85579           }, {
85580             id: 'improveOSM',
85581             layer: svgImproveOSM(projection, context, dispatch)
85582           }, {
85583             id: 'osmose',
85584             layer: svgOsmose(projection, context, dispatch)
85585           }, {
85586             id: 'streetside',
85587             layer: svgStreetside(projection, context, dispatch)
85588           }, {
85589             id: 'mapillary',
85590             layer: svgMapillaryImages(projection, context, dispatch)
85591           }, {
85592             id: 'mapillary-position',
85593             layer: svgMapillaryPosition(projection, context)
85594           }, {
85595             id: 'mapillary-map-features',
85596             layer: svgMapillaryMapFeatures(projection, context, dispatch)
85597           }, {
85598             id: 'mapillary-signs',
85599             layer: svgMapillarySigns(projection, context, dispatch)
85600           }, {
85601             id: 'kartaview',
85602             layer: svgKartaviewImages(projection, context, dispatch)
85603           }, {
85604             id: 'debug',
85605             layer: svgDebug(projection, context)
85606           }, {
85607             id: 'geolocate',
85608             layer: svgGeolocate(projection)
85609           }, {
85610             id: 'touch',
85611             layer: svgTouch()
85612           }];
85613
85614           function drawLayers(selection) {
85615             svg = selection.selectAll('.surface').data([0]);
85616             svg = svg.enter().append('svg').attr('class', 'surface').merge(svg);
85617             var defs = svg.selectAll('.surface-defs').data([0]);
85618             defs.enter().append('defs').attr('class', 'surface-defs');
85619             var groups = svg.selectAll('.data-layer').data(_layers);
85620             groups.exit().remove();
85621             groups.enter().append('g').attr('class', function (d) {
85622               return 'data-layer ' + d.id;
85623             }).merge(groups).each(function (d) {
85624               select(this).call(d.layer);
85625             });
85626           }
85627
85628           drawLayers.all = function () {
85629             return _layers;
85630           };
85631
85632           drawLayers.layer = function (id) {
85633             var obj = _layers.find(function (o) {
85634               return o.id === id;
85635             });
85636
85637             return obj && obj.layer;
85638           };
85639
85640           drawLayers.only = function (what) {
85641             var arr = [].concat(what);
85642
85643             var all = _layers.map(function (layer) {
85644               return layer.id;
85645             });
85646
85647             return drawLayers.remove(utilArrayDifference(all, arr));
85648           };
85649
85650           drawLayers.remove = function (what) {
85651             var arr = [].concat(what);
85652             arr.forEach(function (id) {
85653               _layers = _layers.filter(function (o) {
85654                 return o.id !== id;
85655               });
85656             });
85657             dispatch.call('change');
85658             return this;
85659           };
85660
85661           drawLayers.add = function (what) {
85662             var arr = [].concat(what);
85663             arr.forEach(function (obj) {
85664               if ('id' in obj && 'layer' in obj) {
85665                 _layers.push(obj);
85666               }
85667             });
85668             dispatch.call('change');
85669             return this;
85670           };
85671
85672           drawLayers.dimensions = function (val) {
85673             if (!arguments.length) return utilGetDimensions(svg);
85674             utilSetDimensions(svg, val);
85675             return this;
85676           };
85677
85678           return utilRebind(drawLayers, dispatch, 'on');
85679         }
85680
85681         function svgLines(projection, context) {
85682           var detected = utilDetect();
85683           var highway_stack = {
85684             motorway: 0,
85685             motorway_link: 1,
85686             trunk: 2,
85687             trunk_link: 3,
85688             primary: 4,
85689             primary_link: 5,
85690             secondary: 6,
85691             tertiary: 7,
85692             unclassified: 8,
85693             residential: 9,
85694             service: 10,
85695             footway: 11
85696           };
85697
85698           function drawTargets(selection, graph, entities, filter) {
85699             var targetClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
85700             var nopeClass = context.getDebug('target') ? 'red ' : 'nocolor ';
85701             var getPath = svgPath(projection).geojson;
85702             var activeID = context.activeID();
85703             var base = context.history().base(); // The targets and nopes will be MultiLineString sub-segments of the ways
85704
85705             var data = {
85706               targets: [],
85707               nopes: []
85708             };
85709             entities.forEach(function (way) {
85710               var features = svgSegmentWay(way, graph, activeID);
85711               data.targets.push.apply(data.targets, features.passive);
85712               data.nopes.push.apply(data.nopes, features.active);
85713             }); // Targets allow hover and vertex snapping
85714
85715             var targetData = data.targets.filter(getPath);
85716             var targets = selection.selectAll('.line.target-allowed').filter(function (d) {
85717               return filter(d.properties.entity);
85718             }).data(targetData, function key(d) {
85719               return d.id;
85720             }); // exit
85721
85722             targets.exit().remove();
85723
85724             var segmentWasEdited = function segmentWasEdited(d) {
85725               var wayID = d.properties.entity.id; // if the whole line was edited, don't draw segment changes
85726
85727               if (!base.entities[wayID] || !fastDeepEqual(graph.entities[wayID].nodes, base.entities[wayID].nodes)) {
85728                 return false;
85729               }
85730
85731               return d.properties.nodes.some(function (n) {
85732                 return !base.entities[n.id] || !fastDeepEqual(graph.entities[n.id].loc, base.entities[n.id].loc);
85733               });
85734             }; // enter/update
85735
85736
85737             targets.enter().append('path').merge(targets).attr('d', getPath).attr('class', function (d) {
85738               return 'way line target target-allowed ' + targetClass + d.id;
85739             }).classed('segment-edited', segmentWasEdited); // NOPE
85740
85741             var nopeData = data.nopes.filter(getPath);
85742             var nopes = selection.selectAll('.line.target-nope').filter(function (d) {
85743               return filter(d.properties.entity);
85744             }).data(nopeData, function key(d) {
85745               return d.id;
85746             }); // exit
85747
85748             nopes.exit().remove(); // enter/update
85749
85750             nopes.enter().append('path').merge(nopes).attr('d', getPath).attr('class', function (d) {
85751               return 'way line target target-nope ' + nopeClass + d.id;
85752             }).classed('segment-edited', segmentWasEdited);
85753           }
85754
85755           function drawLines(selection, graph, entities, filter) {
85756             var base = context.history().base();
85757
85758             function waystack(a, b) {
85759               var selected = context.selectedIDs();
85760               var scoreA = selected.indexOf(a.id) !== -1 ? 20 : 0;
85761               var scoreB = selected.indexOf(b.id) !== -1 ? 20 : 0;
85762
85763               if (a.tags.highway) {
85764                 scoreA -= highway_stack[a.tags.highway];
85765               }
85766
85767               if (b.tags.highway) {
85768                 scoreB -= highway_stack[b.tags.highway];
85769               }
85770
85771               return scoreA - scoreB;
85772             }
85773
85774             function drawLineGroup(selection, klass, isSelected) {
85775               // Note: Don't add `.selected` class in draw modes
85776               var mode = context.mode();
85777               var isDrawing = mode && /^draw/.test(mode.id);
85778               var selectedClass = !isDrawing && isSelected ? 'selected ' : '';
85779               var lines = selection.selectAll('path').filter(filter).data(getPathData(isSelected), osmEntity.key);
85780               lines.exit().remove(); // Optimization: Call expensive TagClasses only on enter selection. This
85781               // works because osmEntity.key is defined to include the entity v attribute.
85782
85783               lines.enter().append('path').attr('class', function (d) {
85784                 var prefix = 'way line'; // if this line isn't styled by its own tags
85785
85786                 if (!d.hasInterestingTags()) {
85787                   var parentRelations = graph.parentRelations(d);
85788                   var parentMultipolygons = parentRelations.filter(function (relation) {
85789                     return relation.isMultipolygon();
85790                   }); // and if it's a member of at least one multipolygon relation
85791
85792                   if (parentMultipolygons.length > 0 && // and only multipolygon relations
85793                   parentRelations.length === parentMultipolygons.length) {
85794                     // then fudge the classes to style this as an area edge
85795                     prefix = 'relation area';
85796                   }
85797                 }
85798
85799                 var oldMPClass = oldMultiPolygonOuters[d.id] ? 'old-multipolygon ' : '';
85800                 return prefix + ' ' + klass + ' ' + selectedClass + oldMPClass + d.id;
85801               }).classed('added', function (d) {
85802                 return !base.entities[d.id];
85803               }).classed('geometry-edited', function (d) {
85804                 return graph.entities[d.id] && base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].nodes, base.entities[d.id].nodes);
85805               }).classed('retagged', function (d) {
85806                 return graph.entities[d.id] && base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].tags, base.entities[d.id].tags);
85807               }).call(svgTagClasses()).merge(lines).sort(waystack).attr('d', getPath).call(svgTagClasses().tags(svgRelationMemberTags(graph)));
85808               return selection;
85809             }
85810
85811             function getPathData(isSelected) {
85812               return function () {
85813                 var layer = this.parentNode.__data__;
85814                 var data = pathdata[layer] || [];
85815                 return data.filter(function (d) {
85816                   if (isSelected) {
85817                     return context.selectedIDs().indexOf(d.id) !== -1;
85818                   } else {
85819                     return context.selectedIDs().indexOf(d.id) === -1;
85820                   }
85821                 });
85822               };
85823             }
85824
85825             function addMarkers(layergroup, pathclass, groupclass, groupdata, marker) {
85826               var markergroup = layergroup.selectAll('g.' + groupclass).data([pathclass]);
85827               markergroup = markergroup.enter().append('g').attr('class', groupclass).merge(markergroup);
85828               var markers = markergroup.selectAll('path').filter(filter).data(function data() {
85829                 return groupdata[this.parentNode.__data__] || [];
85830               }, function key(d) {
85831                 return [d.id, d.index];
85832               });
85833               markers.exit().remove();
85834               markers = markers.enter().append('path').attr('class', pathclass).merge(markers).attr('marker-mid', marker).attr('d', function (d) {
85835                 return d.d;
85836               });
85837
85838               if (detected.ie) {
85839                 markers.each(function () {
85840                   this.parentNode.insertBefore(this, this);
85841                 });
85842               }
85843             }
85844
85845             var getPath = svgPath(projection, graph);
85846             var ways = [];
85847             var onewaydata = {};
85848             var sideddata = {};
85849             var oldMultiPolygonOuters = {};
85850
85851             for (var i = 0; i < entities.length; i++) {
85852               var entity = entities[i];
85853               var outer = osmOldMultipolygonOuterMember(entity, graph);
85854
85855               if (outer) {
85856                 ways.push(entity.mergeTags(outer.tags));
85857                 oldMultiPolygonOuters[outer.id] = true;
85858               } else if (entity.geometry(graph) === 'line') {
85859                 ways.push(entity);
85860               }
85861             }
85862
85863             ways = ways.filter(getPath);
85864             var pathdata = utilArrayGroupBy(ways, function (way) {
85865               return way.layer();
85866             });
85867             Object.keys(pathdata).forEach(function (k) {
85868               var v = pathdata[k];
85869               var onewayArr = v.filter(function (d) {
85870                 return d.isOneWay();
85871               });
85872               var onewaySegments = svgMarkerSegments(projection, graph, 35, function shouldReverse(entity) {
85873                 return entity.tags.oneway === '-1';
85874               }, function bothDirections(entity) {
85875                 return entity.tags.oneway === 'reversible' || entity.tags.oneway === 'alternating';
85876               });
85877               onewaydata[k] = utilArrayFlatten(onewayArr.map(onewaySegments));
85878               var sidedArr = v.filter(function (d) {
85879                 return d.isSided();
85880               });
85881               var sidedSegments = svgMarkerSegments(projection, graph, 30, function shouldReverse() {
85882                 return false;
85883               }, function bothDirections() {
85884                 return false;
85885               });
85886               sideddata[k] = utilArrayFlatten(sidedArr.map(sidedSegments));
85887             });
85888             var covered = selection.selectAll('.layer-osm.covered'); // under areas
85889
85890             var uncovered = selection.selectAll('.layer-osm.lines'); // over areas
85891
85892             var touchLayer = selection.selectAll('.layer-touch.lines'); // Draw lines..
85893
85894             [covered, uncovered].forEach(function (selection) {
85895               var range = selection === covered ? range$1(-10, 0) : range$1(0, 11);
85896               var layergroup = selection.selectAll('g.layergroup').data(range);
85897               layergroup = layergroup.enter().append('g').attr('class', function (d) {
85898                 return 'layergroup layer' + String(d);
85899               }).merge(layergroup);
85900               layergroup.selectAll('g.linegroup').data(['shadow', 'casing', 'stroke', 'shadow-highlighted', 'casing-highlighted', 'stroke-highlighted']).enter().append('g').attr('class', function (d) {
85901                 return 'linegroup line-' + d;
85902               });
85903               layergroup.selectAll('g.line-shadow').call(drawLineGroup, 'shadow', false);
85904               layergroup.selectAll('g.line-casing').call(drawLineGroup, 'casing', false);
85905               layergroup.selectAll('g.line-stroke').call(drawLineGroup, 'stroke', false);
85906               layergroup.selectAll('g.line-shadow-highlighted').call(drawLineGroup, 'shadow', true);
85907               layergroup.selectAll('g.line-casing-highlighted').call(drawLineGroup, 'casing', true);
85908               layergroup.selectAll('g.line-stroke-highlighted').call(drawLineGroup, 'stroke', true);
85909               addMarkers(layergroup, 'oneway', 'onewaygroup', onewaydata, 'url(#ideditor-oneway-marker)');
85910               addMarkers(layergroup, 'sided', 'sidedgroup', sideddata, function marker(d) {
85911                 var category = graph.entity(d.id).sidednessIdentifier();
85912                 return 'url(#ideditor-sided-marker-' + category + ')';
85913               });
85914             }); // Draw touch targets..
85915
85916             touchLayer.call(drawTargets, graph, ways, filter);
85917           }
85918
85919           return drawLines;
85920         }
85921
85922         function svgMidpoints(projection, context) {
85923           var targetRadius = 8;
85924
85925           function drawTargets(selection, graph, entities, filter) {
85926             var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
85927             var getTransform = svgPointTransform(projection).geojson;
85928             var data = entities.map(function (midpoint) {
85929               return {
85930                 type: 'Feature',
85931                 id: midpoint.id,
85932                 properties: {
85933                   target: true,
85934                   entity: midpoint
85935                 },
85936                 geometry: {
85937                   type: 'Point',
85938                   coordinates: midpoint.loc
85939                 }
85940               };
85941             });
85942             var targets = selection.selectAll('.midpoint.target').filter(function (d) {
85943               return filter(d.properties.entity);
85944             }).data(data, function key(d) {
85945               return d.id;
85946             }); // exit
85947
85948             targets.exit().remove(); // enter/update
85949
85950             targets.enter().append('circle').attr('r', targetRadius).merge(targets).attr('class', function (d) {
85951               return 'node midpoint target ' + fillClass + d.id;
85952             }).attr('transform', getTransform);
85953           }
85954
85955           function drawMidpoints(selection, graph, entities, filter, extent) {
85956             var drawLayer = selection.selectAll('.layer-osm.points .points-group.midpoints');
85957             var touchLayer = selection.selectAll('.layer-touch.points');
85958             var mode = context.mode();
85959
85960             if (mode && mode.id !== 'select' || !context.map().withinEditableZoom()) {
85961               drawLayer.selectAll('.midpoint').remove();
85962               touchLayer.selectAll('.midpoint.target').remove();
85963               return;
85964             }
85965
85966             var poly = extent.polygon();
85967             var midpoints = {};
85968
85969             for (var i = 0; i < entities.length; i++) {
85970               var entity = entities[i];
85971               if (entity.type !== 'way') continue;
85972               if (!filter(entity)) continue;
85973               if (context.selectedIDs().indexOf(entity.id) < 0) continue;
85974               var nodes = graph.childNodes(entity);
85975
85976               for (var j = 0; j < nodes.length - 1; j++) {
85977                 var a = nodes[j];
85978                 var b = nodes[j + 1];
85979                 var id = [a.id, b.id].sort().join('-');
85980
85981                 if (midpoints[id]) {
85982                   midpoints[id].parents.push(entity);
85983                 } else if (geoVecLength(projection(a.loc), projection(b.loc)) > 40) {
85984                   var point = geoVecInterp(a.loc, b.loc, 0.5);
85985                   var loc = null;
85986
85987                   if (extent.intersects(point)) {
85988                     loc = point;
85989                   } else {
85990                     for (var k = 0; k < 4; k++) {
85991                       point = geoLineIntersection([a.loc, b.loc], [poly[k], poly[k + 1]]);
85992
85993                       if (point && geoVecLength(projection(a.loc), projection(point)) > 20 && geoVecLength(projection(b.loc), projection(point)) > 20) {
85994                         loc = point;
85995                         break;
85996                       }
85997                     }
85998                   }
85999
86000                   if (loc) {
86001                     midpoints[id] = {
86002                       type: 'midpoint',
86003                       id: id,
86004                       loc: loc,
86005                       edge: [a.id, b.id],
86006                       parents: [entity]
86007                     };
86008                   }
86009                 }
86010               }
86011             }
86012
86013             function midpointFilter(d) {
86014               if (midpoints[d.id]) return true;
86015
86016               for (var i = 0; i < d.parents.length; i++) {
86017                 if (filter(d.parents[i])) {
86018                   return true;
86019                 }
86020               }
86021
86022               return false;
86023             }
86024
86025             var groups = drawLayer.selectAll('.midpoint').filter(midpointFilter).data(Object.values(midpoints), function (d) {
86026               return d.id;
86027             });
86028             groups.exit().remove();
86029             var enter = groups.enter().insert('g', ':first-child').attr('class', 'midpoint');
86030             enter.append('polygon').attr('points', '-6,8 10,0 -6,-8').attr('class', 'shadow');
86031             enter.append('polygon').attr('points', '-3,4 5,0 -3,-4').attr('class', 'fill');
86032             groups = groups.merge(enter).attr('transform', function (d) {
86033               var translate = svgPointTransform(projection);
86034               var a = graph.entity(d.edge[0]);
86035               var b = graph.entity(d.edge[1]);
86036               var angle = geoAngle(a, b, projection) * (180 / Math.PI);
86037               return translate(d) + ' rotate(' + angle + ')';
86038             }).call(svgTagClasses().tags(function (d) {
86039               return d.parents[0].tags;
86040             })); // Propagate data bindings.
86041
86042             groups.select('polygon.shadow');
86043             groups.select('polygon.fill'); // Draw touch targets..
86044
86045             touchLayer.call(drawTargets, graph, Object.values(midpoints), midpointFilter);
86046           }
86047
86048           return drawMidpoints;
86049         }
86050
86051         function svgPoints(projection, context) {
86052           function markerPath(selection, klass) {
86053             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');
86054           }
86055
86056           function sortY(a, b) {
86057             return b.loc[1] - a.loc[1];
86058           } // Avoid exit/enter if we're just moving stuff around.
86059           // The node will get a new version but we only need to run the update selection.
86060
86061
86062           function fastEntityKey(d) {
86063             var mode = context.mode();
86064             var isMoving = mode && /^(add|draw|drag|move|rotate)/.test(mode.id);
86065             return isMoving ? d.id : osmEntity.key(d);
86066           }
86067
86068           function drawTargets(selection, graph, entities, filter) {
86069             var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
86070             var getTransform = svgPointTransform(projection).geojson;
86071             var activeID = context.activeID();
86072             var data = [];
86073             entities.forEach(function (node) {
86074               if (activeID === node.id) return; // draw no target on the activeID
86075
86076               data.push({
86077                 type: 'Feature',
86078                 id: node.id,
86079                 properties: {
86080                   target: true,
86081                   entity: node
86082                 },
86083                 geometry: node.asGeoJSON()
86084               });
86085             });
86086             var targets = selection.selectAll('.point.target').filter(function (d) {
86087               return filter(d.properties.entity);
86088             }).data(data, function key(d) {
86089               return d.id;
86090             }); // exit
86091
86092             targets.exit().remove(); // enter/update
86093
86094             targets.enter().append('rect').attr('x', -10).attr('y', -26).attr('width', 20).attr('height', 30).merge(targets).attr('class', function (d) {
86095               return 'node point target ' + fillClass + d.id;
86096             }).attr('transform', getTransform);
86097           }
86098
86099           function drawPoints(selection, graph, entities, filter) {
86100             var wireframe = context.surface().classed('fill-wireframe');
86101             var zoom = geoScaleToZoom(projection.scale());
86102             var base = context.history().base(); // Points with a direction will render as vertices at higher zooms..
86103
86104             function renderAsPoint(entity) {
86105               return entity.geometry(graph) === 'point' && !(zoom >= 18 && entity.directions(graph, projection).length);
86106             } // All points will render as vertices in wireframe mode too..
86107
86108
86109             var points = wireframe ? [] : entities.filter(renderAsPoint);
86110             points.sort(sortY);
86111             var drawLayer = selection.selectAll('.layer-osm.points .points-group.points');
86112             var touchLayer = selection.selectAll('.layer-touch.points'); // Draw points..
86113
86114             var groups = drawLayer.selectAll('g.point').filter(filter).data(points, fastEntityKey);
86115             groups.exit().remove();
86116             var enter = groups.enter().append('g').attr('class', function (d) {
86117               return 'node point ' + d.id;
86118             }).order();
86119             enter.append('path').call(markerPath, 'shadow');
86120             enter.append('ellipse').attr('cx', 0.5).attr('cy', 1).attr('rx', 6.5).attr('ry', 3).attr('class', 'stroke');
86121             enter.append('path').call(markerPath, 'stroke');
86122             enter.append('use').attr('transform', 'translate(-5, -19)').attr('class', 'icon').attr('width', '11px').attr('height', '11px');
86123             groups = groups.merge(enter).attr('transform', svgPointTransform(projection)).classed('added', function (d) {
86124               return !base.entities[d.id]; // if it doesn't exist in the base graph, it's new
86125             }).classed('moved', function (d) {
86126               return base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].loc, base.entities[d.id].loc);
86127             }).classed('retagged', function (d) {
86128               return base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].tags, base.entities[d.id].tags);
86129             }).call(svgTagClasses());
86130             groups.select('.shadow'); // propagate bound data
86131
86132             groups.select('.stroke'); // propagate bound data
86133
86134             groups.select('.icon') // propagate bound data
86135             .attr('xlink:href', function (entity) {
86136               var preset = _mainPresetIndex.match(entity, graph);
86137               var picon = preset && preset.icon;
86138
86139               if (!picon) {
86140                 return '';
86141               } else {
86142                 var isMaki = /^maki-/.test(picon);
86143                 return '#' + picon + (isMaki ? '-11' : '');
86144               }
86145             }); // Draw touch targets..
86146
86147             touchLayer.call(drawTargets, graph, points, filter);
86148           }
86149
86150           return drawPoints;
86151         }
86152
86153         function svgTurns(projection, context) {
86154           function icon(turn) {
86155             var u = turn.u ? '-u' : '';
86156             if (turn.no) return '#iD-turn-no' + u;
86157             if (turn.only) return '#iD-turn-only' + u;
86158             return '#iD-turn-yes' + u;
86159           }
86160
86161           function drawTurns(selection, graph, turns) {
86162             function turnTransform(d) {
86163               var pxRadius = 50;
86164               var toWay = graph.entity(d.to.way);
86165               var toPoints = graph.childNodes(toWay).map(function (n) {
86166                 return n.loc;
86167               }).map(projection);
86168               var toLength = geoPathLength(toPoints);
86169               var mid = toLength / 2; // midpoint of destination way
86170
86171               var toNode = graph.entity(d.to.node);
86172               var toVertex = graph.entity(d.to.vertex);
86173               var a = geoAngle(toVertex, toNode, projection);
86174               var o = projection(toVertex.loc);
86175               var r = d.u ? 0 // u-turn: no radius
86176               : !toWay.__via ? pxRadius // leaf way: put marker at pxRadius
86177               : Math.min(mid, pxRadius); // via way: prefer pxRadius, fallback to mid for very short ways
86178
86179               return 'translate(' + (r * Math.cos(a) + o[0]) + ',' + (r * Math.sin(a) + o[1]) + ') ' + 'rotate(' + a * 180 / Math.PI + ')';
86180             }
86181
86182             var drawLayer = selection.selectAll('.layer-osm.points .points-group.turns');
86183             var touchLayer = selection.selectAll('.layer-touch.turns'); // Draw turns..
86184
86185             var groups = drawLayer.selectAll('g.turn').data(turns, function (d) {
86186               return d.key;
86187             }); // exit
86188
86189             groups.exit().remove(); // enter
86190
86191             var groupsEnter = groups.enter().append('g').attr('class', function (d) {
86192               return 'turn ' + d.key;
86193             });
86194             var turnsEnter = groupsEnter.filter(function (d) {
86195               return !d.u;
86196             });
86197             turnsEnter.append('rect').attr('transform', 'translate(-22, -12)').attr('width', '44').attr('height', '24');
86198             turnsEnter.append('use').attr('transform', 'translate(-22, -12)').attr('width', '44').attr('height', '24');
86199             var uEnter = groupsEnter.filter(function (d) {
86200               return d.u;
86201             });
86202             uEnter.append('circle').attr('r', '16');
86203             uEnter.append('use').attr('transform', 'translate(-16, -16)').attr('width', '32').attr('height', '32'); // update
86204
86205             groups = groups.merge(groupsEnter).attr('opacity', function (d) {
86206               return d.direct === false ? '0.7' : null;
86207             }).attr('transform', turnTransform);
86208             groups.select('use').attr('xlink:href', icon);
86209             groups.select('rect'); // propagate bound data
86210
86211             groups.select('circle'); // propagate bound data
86212             // Draw touch targets..
86213
86214             var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
86215             groups = touchLayer.selectAll('g.turn').data(turns, function (d) {
86216               return d.key;
86217             }); // exit
86218
86219             groups.exit().remove(); // enter
86220
86221             groupsEnter = groups.enter().append('g').attr('class', function (d) {
86222               return 'turn ' + d.key;
86223             });
86224             turnsEnter = groupsEnter.filter(function (d) {
86225               return !d.u;
86226             });
86227             turnsEnter.append('rect').attr('class', 'target ' + fillClass).attr('transform', 'translate(-22, -12)').attr('width', '44').attr('height', '24');
86228             uEnter = groupsEnter.filter(function (d) {
86229               return d.u;
86230             });
86231             uEnter.append('circle').attr('class', 'target ' + fillClass).attr('r', '16'); // update
86232
86233             groups = groups.merge(groupsEnter).attr('transform', turnTransform);
86234             groups.select('rect'); // propagate bound data
86235
86236             groups.select('circle'); // propagate bound data
86237
86238             return this;
86239           }
86240
86241           return drawTurns;
86242         }
86243
86244         function svgVertices(projection, context) {
86245           var radiuses = {
86246             //       z16-, z17,   z18+,  w/icon
86247             shadow: [6, 7.5, 7.5, 12],
86248             stroke: [2.5, 3.5, 3.5, 8],
86249             fill: [1, 1.5, 1.5, 1.5]
86250           };
86251
86252           var _currHoverTarget;
86253
86254           var _currPersistent = {};
86255           var _currHover = {};
86256           var _prevHover = {};
86257           var _currSelected = {};
86258           var _prevSelected = {};
86259           var _radii = {};
86260
86261           function sortY(a, b) {
86262             return b.loc[1] - a.loc[1];
86263           } // Avoid exit/enter if we're just moving stuff around.
86264           // The node will get a new version but we only need to run the update selection.
86265
86266
86267           function fastEntityKey(d) {
86268             var mode = context.mode();
86269             var isMoving = mode && /^(add|draw|drag|move|rotate)/.test(mode.id);
86270             return isMoving ? d.id : osmEntity.key(d);
86271           }
86272
86273           function draw(selection, graph, vertices, sets, filter) {
86274             sets = sets || {
86275               selected: {},
86276               important: {},
86277               hovered: {}
86278             };
86279             var icons = {};
86280             var directions = {};
86281             var wireframe = context.surface().classed('fill-wireframe');
86282             var zoom = geoScaleToZoom(projection.scale());
86283             var z = zoom < 17 ? 0 : zoom < 18 ? 1 : 2;
86284             var activeID = context.activeID();
86285             var base = context.history().base();
86286
86287             function getIcon(d) {
86288               // always check latest entity, as fastEntityKey avoids enter/exit now
86289               var entity = graph.entity(d.id);
86290               if (entity.id in icons) return icons[entity.id];
86291               icons[entity.id] = entity.hasInterestingTags() && _mainPresetIndex.match(entity, graph).icon;
86292               return icons[entity.id];
86293             } // memoize directions results, return false for empty arrays (for use in filter)
86294
86295
86296             function getDirections(entity) {
86297               if (entity.id in directions) return directions[entity.id];
86298               var angles = entity.directions(graph, projection);
86299               directions[entity.id] = angles.length ? angles : false;
86300               return angles;
86301             }
86302
86303             function updateAttributes(selection) {
86304               ['shadow', 'stroke', 'fill'].forEach(function (klass) {
86305                 var rads = radiuses[klass];
86306                 selection.selectAll('.' + klass).each(function (entity) {
86307                   var i = z && getIcon(entity);
86308                   var r = rads[i ? 3 : z]; // slightly increase the size of unconnected endpoints #3775
86309
86310                   if (entity.id !== activeID && entity.isEndpoint(graph) && !entity.isConnected(graph)) {
86311                     r += 1.5;
86312                   }
86313
86314                   if (klass === 'shadow') {
86315                     // remember this value, so we don't need to
86316                     _radii[entity.id] = r; // recompute it when we draw the touch targets
86317                   }
86318
86319                   select(this).attr('r', r).attr('visibility', i && klass === 'fill' ? 'hidden' : null);
86320                 });
86321               });
86322             }
86323
86324             vertices.sort(sortY);
86325             var groups = selection.selectAll('g.vertex').filter(filter).data(vertices, fastEntityKey); // exit
86326
86327             groups.exit().remove(); // enter
86328
86329             var enter = groups.enter().append('g').attr('class', function (d) {
86330               return 'node vertex ' + d.id;
86331             }).order();
86332             enter.append('circle').attr('class', 'shadow');
86333             enter.append('circle').attr('class', 'stroke'); // Vertices with tags get a fill.
86334
86335             enter.filter(function (d) {
86336               return d.hasInterestingTags();
86337             }).append('circle').attr('class', 'fill'); // update
86338
86339             groups = groups.merge(enter).attr('transform', svgPointTransform(projection)).classed('sibling', function (d) {
86340               return d.id in sets.selected;
86341             }).classed('shared', function (d) {
86342               return graph.isShared(d);
86343             }).classed('endpoint', function (d) {
86344               return d.isEndpoint(graph);
86345             }).classed('added', function (d) {
86346               return !base.entities[d.id]; // if it doesn't exist in the base graph, it's new
86347             }).classed('moved', function (d) {
86348               return base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].loc, base.entities[d.id].loc);
86349             }).classed('retagged', function (d) {
86350               return base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].tags, base.entities[d.id].tags);
86351             }).call(updateAttributes); // Vertices with icons get a `use`.
86352
86353             var iconUse = groups.selectAll('.icon').data(function data(d) {
86354               return zoom >= 17 && getIcon(d) ? [d] : [];
86355             }, fastEntityKey); // exit
86356
86357             iconUse.exit().remove(); // enter
86358
86359             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) {
86360               var picon = getIcon(d);
86361               var isMaki = /^maki-/.test(picon);
86362               return '#' + picon + (isMaki ? '-11' : '');
86363             }); // Vertices with directions get viewfields
86364
86365             var dgroups = groups.selectAll('.viewfieldgroup').data(function data(d) {
86366               return zoom >= 18 && getDirections(d) ? [d] : [];
86367             }, fastEntityKey); // exit
86368
86369             dgroups.exit().remove(); // enter/update
86370
86371             dgroups = dgroups.enter().insert('g', '.shadow').attr('class', 'viewfieldgroup').merge(dgroups);
86372             var viewfields = dgroups.selectAll('.viewfield').data(getDirections, function key(d) {
86373               return osmEntity.key(d);
86374             }); // exit
86375
86376             viewfields.exit().remove(); // enter/update
86377
86378             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) {
86379               return 'rotate(' + d + ')';
86380             });
86381           }
86382
86383           function drawTargets(selection, graph, entities, filter) {
86384             var targetClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
86385             var nopeClass = context.getDebug('target') ? 'red ' : 'nocolor ';
86386             var getTransform = svgPointTransform(projection).geojson;
86387             var activeID = context.activeID();
86388             var data = {
86389               targets: [],
86390               nopes: []
86391             };
86392             entities.forEach(function (node) {
86393               if (activeID === node.id) return; // draw no target on the activeID
86394
86395               var vertexType = svgPassiveVertex(node, graph, activeID);
86396
86397               if (vertexType !== 0) {
86398                 // passive or adjacent - allow to connect
86399                 data.targets.push({
86400                   type: 'Feature',
86401                   id: node.id,
86402                   properties: {
86403                     target: true,
86404                     entity: node
86405                   },
86406                   geometry: node.asGeoJSON()
86407                 });
86408               } else {
86409                 data.nopes.push({
86410                   type: 'Feature',
86411                   id: node.id + '-nope',
86412                   properties: {
86413                     nope: true,
86414                     target: true,
86415                     entity: node
86416                   },
86417                   geometry: node.asGeoJSON()
86418                 });
86419               }
86420             }); // Targets allow hover and vertex snapping
86421
86422             var targets = selection.selectAll('.vertex.target-allowed').filter(function (d) {
86423               return filter(d.properties.entity);
86424             }).data(data.targets, function key(d) {
86425               return d.id;
86426             }); // exit
86427
86428             targets.exit().remove(); // enter/update
86429
86430             targets.enter().append('circle').attr('r', function (d) {
86431               return _radii[d.id] || radiuses.shadow[3];
86432             }).merge(targets).attr('class', function (d) {
86433               return 'node vertex target target-allowed ' + targetClass + d.id;
86434             }).attr('transform', getTransform); // NOPE
86435
86436             var nopes = selection.selectAll('.vertex.target-nope').filter(function (d) {
86437               return filter(d.properties.entity);
86438             }).data(data.nopes, function key(d) {
86439               return d.id;
86440             }); // exit
86441
86442             nopes.exit().remove(); // enter/update
86443
86444             nopes.enter().append('circle').attr('r', function (d) {
86445               return _radii[d.properties.entity.id] || radiuses.shadow[3];
86446             }).merge(nopes).attr('class', function (d) {
86447               return 'node vertex target target-nope ' + nopeClass + d.id;
86448             }).attr('transform', getTransform);
86449           } // Points can also render as vertices:
86450           // 1. in wireframe mode or
86451           // 2. at higher zooms if they have a direction
86452
86453
86454           function renderAsVertex(entity, graph, wireframe, zoom) {
86455             var geometry = entity.geometry(graph);
86456             return geometry === 'vertex' || geometry === 'point' && (wireframe || zoom >= 18 && entity.directions(graph, projection).length);
86457           }
86458
86459           function isEditedNode(node, base, head) {
86460             var baseNode = base.entities[node.id];
86461             var headNode = head.entities[node.id];
86462             return !headNode || !baseNode || !fastDeepEqual(headNode.tags, baseNode.tags) || !fastDeepEqual(headNode.loc, baseNode.loc);
86463           }
86464
86465           function getSiblingAndChildVertices(ids, graph, wireframe, zoom) {
86466             var results = {};
86467             var seenIds = {};
86468
86469             function addChildVertices(entity) {
86470               // avoid redundant work and infinite recursion of circular relations
86471               if (seenIds[entity.id]) return;
86472               seenIds[entity.id] = true;
86473               var geometry = entity.geometry(graph);
86474
86475               if (!context.features().isHiddenFeature(entity, graph, geometry)) {
86476                 var i;
86477
86478                 if (entity.type === 'way') {
86479                   for (i = 0; i < entity.nodes.length; i++) {
86480                     var child = graph.hasEntity(entity.nodes[i]);
86481
86482                     if (child) {
86483                       addChildVertices(child);
86484                     }
86485                   }
86486                 } else if (entity.type === 'relation') {
86487                   for (i = 0; i < entity.members.length; i++) {
86488                     var member = graph.hasEntity(entity.members[i].id);
86489
86490                     if (member) {
86491                       addChildVertices(member);
86492                     }
86493                   }
86494                 } else if (renderAsVertex(entity, graph, wireframe, zoom)) {
86495                   results[entity.id] = entity;
86496                 }
86497               }
86498             }
86499
86500             ids.forEach(function (id) {
86501               var entity = graph.hasEntity(id);
86502               if (!entity) return;
86503
86504               if (entity.type === 'node') {
86505                 if (renderAsVertex(entity, graph, wireframe, zoom)) {
86506                   results[entity.id] = entity;
86507                   graph.parentWays(entity).forEach(function (entity) {
86508                     addChildVertices(entity);
86509                   });
86510                 }
86511               } else {
86512                 // way, relation
86513                 addChildVertices(entity);
86514               }
86515             });
86516             return results;
86517           }
86518
86519           function drawVertices(selection, graph, entities, filter, extent, fullRedraw) {
86520             var wireframe = context.surface().classed('fill-wireframe');
86521             var visualDiff = context.surface().classed('highlight-edited');
86522             var zoom = geoScaleToZoom(projection.scale());
86523             var mode = context.mode();
86524             var isMoving = mode && /^(add|draw|drag|move|rotate)/.test(mode.id);
86525             var base = context.history().base();
86526             var drawLayer = selection.selectAll('.layer-osm.points .points-group.vertices');
86527             var touchLayer = selection.selectAll('.layer-touch.points');
86528
86529             if (fullRedraw) {
86530               _currPersistent = {};
86531               _radii = {};
86532             } // Collect important vertices from the `entities` list..
86533             // (during a partial redraw, it will not contain everything)
86534
86535
86536             for (var i = 0; i < entities.length; i++) {
86537               var entity = entities[i];
86538               var geometry = entity.geometry(graph);
86539               var keep = false; // a point that looks like a vertex..
86540
86541               if (geometry === 'point' && renderAsVertex(entity, graph, wireframe, zoom)) {
86542                 _currPersistent[entity.id] = entity;
86543                 keep = true; // a vertex of some importance..
86544               } else if (geometry === 'vertex' && (entity.hasInterestingTags() || entity.isEndpoint(graph) || entity.isConnected(graph) || visualDiff && isEditedNode(entity, base, graph))) {
86545                 _currPersistent[entity.id] = entity;
86546                 keep = true;
86547               } // whatever this is, it's not a persistent vertex..
86548
86549
86550               if (!keep && !fullRedraw) {
86551                 delete _currPersistent[entity.id];
86552               }
86553             } // 3 sets of vertices to consider:
86554
86555
86556             var sets = {
86557               persistent: _currPersistent,
86558               // persistent = important vertices (render always)
86559               selected: _currSelected,
86560               // selected + siblings of selected (render always)
86561               hovered: _currHover // hovered + siblings of hovered (render only in draw modes)
86562
86563             };
86564             var all = Object.assign({}, isMoving ? _currHover : {}, _currSelected, _currPersistent); // Draw the vertices..
86565             // The filter function controls the scope of what objects d3 will touch (exit/enter/update)
86566             // Adjust the filter function to expand the scope beyond whatever entities were passed in.
86567
86568             var filterRendered = function filterRendered(d) {
86569               return d.id in _currPersistent || d.id in _currSelected || d.id in _currHover || filter(d);
86570             };
86571
86572             drawLayer.call(draw, graph, currentVisible(all), sets, filterRendered); // Draw touch targets..
86573             // When drawing, render all targets (not just those affected by a partial redraw)
86574
86575             var filterTouch = function filterTouch(d) {
86576               return isMoving ? true : filterRendered(d);
86577             };
86578
86579             touchLayer.call(drawTargets, graph, currentVisible(all), filterTouch);
86580
86581             function currentVisible(which) {
86582               return Object.keys(which).map(graph.hasEntity, graph) // the current version of this entity
86583               .filter(function (entity) {
86584                 return entity && entity.intersects(extent, graph);
86585               });
86586             }
86587           } // partial redraw - only update the selected items..
86588
86589
86590           drawVertices.drawSelected = function (selection, graph, extent) {
86591             var wireframe = context.surface().classed('fill-wireframe');
86592             var zoom = geoScaleToZoom(projection.scale());
86593             _prevSelected = _currSelected || {};
86594
86595             if (context.map().isInWideSelection()) {
86596               _currSelected = {};
86597               context.selectedIDs().forEach(function (id) {
86598                 var entity = graph.hasEntity(id);
86599                 if (!entity) return;
86600
86601                 if (entity.type === 'node') {
86602                   if (renderAsVertex(entity, graph, wireframe, zoom)) {
86603                     _currSelected[entity.id] = entity;
86604                   }
86605                 }
86606               });
86607             } else {
86608               _currSelected = getSiblingAndChildVertices(context.selectedIDs(), graph, wireframe, zoom);
86609             } // note that drawVertices will add `_currSelected` automatically if needed..
86610
86611
86612             var filter = function filter(d) {
86613               return d.id in _prevSelected;
86614             };
86615
86616             drawVertices(selection, graph, Object.values(_prevSelected), filter, extent, false);
86617           }; // partial redraw - only update the hovered items..
86618
86619
86620           drawVertices.drawHover = function (selection, graph, target, extent) {
86621             if (target === _currHoverTarget) return; // continue only if something changed
86622
86623             var wireframe = context.surface().classed('fill-wireframe');
86624             var zoom = geoScaleToZoom(projection.scale());
86625             _prevHover = _currHover || {};
86626             _currHoverTarget = target;
86627             var entity = target && target.properties && target.properties.entity;
86628
86629             if (entity) {
86630               _currHover = getSiblingAndChildVertices([entity.id], graph, wireframe, zoom);
86631             } else {
86632               _currHover = {};
86633             } // note that drawVertices will add `_currHover` automatically if needed..
86634
86635
86636             var filter = function filter(d) {
86637               return d.id in _prevHover;
86638             };
86639
86640             drawVertices(selection, graph, Object.values(_prevHover), filter, extent, false);
86641           };
86642
86643           return drawVertices;
86644         }
86645
86646         function utilBindOnce(target, type, listener, capture) {
86647           var typeOnce = type + '.once';
86648
86649           function one() {
86650             target.on(typeOnce, null);
86651             listener.apply(this, arguments);
86652           }
86653
86654           target.on(typeOnce, one, capture);
86655           return this;
86656         }
86657
86658         function defaultFilter(d3_event) {
86659           return !d3_event.ctrlKey && !d3_event.button;
86660         }
86661
86662         function defaultExtent() {
86663           var e = this;
86664
86665           if (e instanceof SVGElement) {
86666             e = e.ownerSVGElement || e;
86667
86668             if (e.hasAttribute('viewBox')) {
86669               e = e.viewBox.baseVal;
86670               return [[e.x, e.y], [e.x + e.width, e.y + e.height]];
86671             }
86672
86673             return [[0, 0], [e.width.baseVal.value, e.height.baseVal.value]];
86674           }
86675
86676           return [[0, 0], [e.clientWidth, e.clientHeight]];
86677         }
86678
86679         function defaultWheelDelta(d3_event) {
86680           return -d3_event.deltaY * (d3_event.deltaMode === 1 ? 0.05 : d3_event.deltaMode ? 1 : 0.002);
86681         }
86682
86683         function defaultConstrain(transform, extent, translateExtent) {
86684           var dx0 = transform.invertX(extent[0][0]) - translateExtent[0][0],
86685               dx1 = transform.invertX(extent[1][0]) - translateExtent[1][0],
86686               dy0 = transform.invertY(extent[0][1]) - translateExtent[0][1],
86687               dy1 = transform.invertY(extent[1][1]) - translateExtent[1][1];
86688           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));
86689         }
86690
86691         function utilZoomPan() {
86692           var filter = defaultFilter,
86693               extent = defaultExtent,
86694               constrain = defaultConstrain,
86695               wheelDelta = defaultWheelDelta,
86696               scaleExtent = [0, Infinity],
86697               translateExtent = [[-Infinity, -Infinity], [Infinity, Infinity]],
86698               interpolate = interpolateZoom,
86699               dispatch = dispatch$8('start', 'zoom', 'end'),
86700               _wheelDelay = 150,
86701               _transform = identity$2,
86702               _activeGesture;
86703
86704           function zoom(selection) {
86705             selection.on('pointerdown.zoom', pointerdown).on('wheel.zoom', wheeled).style('touch-action', 'none').style('-webkit-tap-highlight-color', 'rgba(0,0,0,0)');
86706             select(window).on('pointermove.zoompan', pointermove).on('pointerup.zoompan pointercancel.zoompan', pointerup);
86707           }
86708
86709           zoom.transform = function (collection, transform, point) {
86710             var selection = collection.selection ? collection.selection() : collection;
86711
86712             if (collection !== selection) {
86713               schedule(collection, transform, point);
86714             } else {
86715               selection.interrupt().each(function () {
86716                 gesture(this, arguments).start(null).zoom(null, null, typeof transform === 'function' ? transform.apply(this, arguments) : transform).end(null);
86717               });
86718             }
86719           };
86720
86721           zoom.scaleBy = function (selection, k, p) {
86722             zoom.scaleTo(selection, function () {
86723               var k0 = _transform.k,
86724                   k1 = typeof k === 'function' ? k.apply(this, arguments) : k;
86725               return k0 * k1;
86726             }, p);
86727           };
86728
86729           zoom.scaleTo = function (selection, k, p) {
86730             zoom.transform(selection, function () {
86731               var e = extent.apply(this, arguments),
86732                   t0 = _transform,
86733                   p0 = !p ? centroid(e) : typeof p === 'function' ? p.apply(this, arguments) : p,
86734                   p1 = t0.invert(p0),
86735                   k1 = typeof k === 'function' ? k.apply(this, arguments) : k;
86736               return constrain(translate(scale(t0, k1), p0, p1), e, translateExtent);
86737             }, p);
86738           };
86739
86740           zoom.translateBy = function (selection, x, y) {
86741             zoom.transform(selection, function () {
86742               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);
86743             });
86744           };
86745
86746           zoom.translateTo = function (selection, x, y, p) {
86747             zoom.transform(selection, function () {
86748               var e = extent.apply(this, arguments),
86749                   t = _transform,
86750                   p0 = !p ? centroid(e) : typeof p === 'function' ? p.apply(this, arguments) : p;
86751               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);
86752             }, p);
86753           };
86754
86755           function scale(transform, k) {
86756             k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], k));
86757             return k === transform.k ? transform : new Transform(k, transform.x, transform.y);
86758           }
86759
86760           function translate(transform, p0, p1) {
86761             var x = p0[0] - p1[0] * transform.k,
86762                 y = p0[1] - p1[1] * transform.k;
86763             return x === transform.x && y === transform.y ? transform : new Transform(transform.k, x, y);
86764           }
86765
86766           function centroid(extent) {
86767             return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2];
86768           }
86769
86770           function schedule(transition, transform, point) {
86771             transition.on('start.zoom', function () {
86772               gesture(this, arguments).start(null);
86773             }).on('interrupt.zoom end.zoom', function () {
86774               gesture(this, arguments).end(null);
86775             }).tween('zoom', function () {
86776               var that = this,
86777                   args = arguments,
86778                   g = gesture(that, args),
86779                   e = extent.apply(that, args),
86780                   p = !point ? centroid(e) : typeof point === 'function' ? point.apply(that, args) : point,
86781                   w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]),
86782                   a = _transform,
86783                   b = typeof transform === 'function' ? transform.apply(that, args) : transform,
86784                   i = interpolate(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k));
86785               return function (t) {
86786                 if (t === 1) {
86787                   // Avoid rounding error on end.
86788                   t = b;
86789                 } else {
86790                   var l = i(t);
86791                   var k = w / l[2];
86792                   t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k);
86793                 }
86794
86795                 g.zoom(null, null, t);
86796               };
86797             });
86798           }
86799
86800           function gesture(that, args, clean) {
86801             return !clean && _activeGesture || new Gesture(that, args);
86802           }
86803
86804           function Gesture(that, args) {
86805             this.that = that;
86806             this.args = args;
86807             this.active = 0;
86808             this.extent = extent.apply(that, args);
86809           }
86810
86811           Gesture.prototype = {
86812             start: function start(d3_event) {
86813               if (++this.active === 1) {
86814                 _activeGesture = this;
86815                 dispatch.call('start', this, d3_event);
86816               }
86817
86818               return this;
86819             },
86820             zoom: function zoom(d3_event, key, transform) {
86821               if (this.mouse && key !== 'mouse') this.mouse[1] = transform.invert(this.mouse[0]);
86822               if (this.pointer0 && key !== 'touch') this.pointer0[1] = transform.invert(this.pointer0[0]);
86823               if (this.pointer1 && key !== 'touch') this.pointer1[1] = transform.invert(this.pointer1[0]);
86824               _transform = transform;
86825               dispatch.call('zoom', this, d3_event, key, transform);
86826               return this;
86827             },
86828             end: function end(d3_event) {
86829               if (--this.active === 0) {
86830                 _activeGesture = null;
86831                 dispatch.call('end', this, d3_event);
86832               }
86833
86834               return this;
86835             }
86836           };
86837
86838           function wheeled(d3_event) {
86839             if (!filter.apply(this, arguments)) return;
86840             var g = gesture(this, arguments),
86841                 t = _transform,
86842                 k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], t.k * Math.pow(2, wheelDelta.apply(this, arguments)))),
86843                 p = utilFastMouse(this)(d3_event); // If the mouse is in the same location as before, reuse it.
86844             // If there were recent wheel events, reset the wheel idle timeout.
86845
86846             if (g.wheel) {
86847               if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) {
86848                 g.mouse[1] = t.invert(g.mouse[0] = p);
86849               }
86850
86851               clearTimeout(g.wheel); // Otherwise, capture the mouse point and location at the start.
86852             } else {
86853               g.mouse = [p, t.invert(p)];
86854               interrupt(this);
86855               g.start(d3_event);
86856             }
86857
86858             d3_event.preventDefault();
86859             d3_event.stopImmediatePropagation();
86860             g.wheel = setTimeout(wheelidled, _wheelDelay);
86861             g.zoom(d3_event, 'mouse', constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent, translateExtent));
86862
86863             function wheelidled() {
86864               g.wheel = null;
86865               g.end(d3_event);
86866             }
86867           }
86868
86869           var _downPointerIDs = new Set();
86870
86871           var _pointerLocGetter;
86872
86873           function pointerdown(d3_event) {
86874             _downPointerIDs.add(d3_event.pointerId);
86875
86876             if (!filter.apply(this, arguments)) return;
86877             var g = gesture(this, arguments, _downPointerIDs.size === 1);
86878             var started;
86879             d3_event.stopImmediatePropagation();
86880             _pointerLocGetter = utilFastMouse(this);
86881
86882             var loc = _pointerLocGetter(d3_event);
86883
86884             var p = [loc, _transform.invert(loc), d3_event.pointerId];
86885
86886             if (!g.pointer0) {
86887               g.pointer0 = p;
86888               started = true;
86889             } else if (!g.pointer1 && g.pointer0[2] !== p[2]) {
86890               g.pointer1 = p;
86891             }
86892
86893             if (started) {
86894               interrupt(this);
86895               g.start(d3_event);
86896             }
86897           }
86898
86899           function pointermove(d3_event) {
86900             if (!_downPointerIDs.has(d3_event.pointerId)) return;
86901             if (!_activeGesture || !_pointerLocGetter) return;
86902             var g = gesture(this, arguments);
86903             var isPointer0 = g.pointer0 && g.pointer0[2] === d3_event.pointerId;
86904             var isPointer1 = !isPointer0 && g.pointer1 && g.pointer1[2] === d3_event.pointerId;
86905
86906             if ((isPointer0 || isPointer1) && 'buttons' in d3_event && !d3_event.buttons) {
86907               // The pointer went up without ending the gesture somehow, e.g.
86908               // a down mouse was moved off the map and released. End it here.
86909               if (g.pointer0) _downPointerIDs["delete"](g.pointer0[2]);
86910               if (g.pointer1) _downPointerIDs["delete"](g.pointer1[2]);
86911               g.end(d3_event);
86912               return;
86913             }
86914
86915             d3_event.preventDefault();
86916             d3_event.stopImmediatePropagation();
86917
86918             var loc = _pointerLocGetter(d3_event);
86919
86920             var t, p, l;
86921             if (isPointer0) g.pointer0[0] = loc;else if (isPointer1) g.pointer1[0] = loc;
86922             t = _transform;
86923
86924             if (g.pointer1) {
86925               var p0 = g.pointer0[0],
86926                   l0 = g.pointer0[1],
86927                   p1 = g.pointer1[0],
86928                   l1 = g.pointer1[1],
86929                   dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp,
86930                   dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl;
86931               t = scale(t, Math.sqrt(dp / dl));
86932               p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2];
86933               l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];
86934             } else if (g.pointer0) {
86935               p = g.pointer0[0];
86936               l = g.pointer0[1];
86937             } else {
86938               return;
86939             }
86940
86941             g.zoom(d3_event, 'touch', constrain(translate(t, p, l), g.extent, translateExtent));
86942           }
86943
86944           function pointerup(d3_event) {
86945             if (!_downPointerIDs.has(d3_event.pointerId)) return;
86946
86947             _downPointerIDs["delete"](d3_event.pointerId);
86948
86949             if (!_activeGesture) return;
86950             var g = gesture(this, arguments);
86951             d3_event.stopImmediatePropagation();
86952             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;
86953
86954             if (g.pointer1 && !g.pointer0) {
86955               g.pointer0 = g.pointer1;
86956               delete g.pointer1;
86957             }
86958
86959             if (g.pointer0) {
86960               g.pointer0[1] = _transform.invert(g.pointer0[0]);
86961             } else {
86962               g.end(d3_event);
86963             }
86964           }
86965
86966           zoom.wheelDelta = function (_) {
86967             return arguments.length ? (wheelDelta = utilFunctor(+_), zoom) : wheelDelta;
86968           };
86969
86970           zoom.filter = function (_) {
86971             return arguments.length ? (filter = utilFunctor(!!_), zoom) : filter;
86972           };
86973
86974           zoom.extent = function (_) {
86975             return arguments.length ? (extent = utilFunctor([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent;
86976           };
86977
86978           zoom.scaleExtent = function (_) {
86979             return arguments.length ? (scaleExtent[0] = +_[0], scaleExtent[1] = +_[1], zoom) : [scaleExtent[0], scaleExtent[1]];
86980           };
86981
86982           zoom.translateExtent = function (_) {
86983             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]]];
86984           };
86985
86986           zoom.constrain = function (_) {
86987             return arguments.length ? (constrain = _, zoom) : constrain;
86988           };
86989
86990           zoom.interpolate = function (_) {
86991             return arguments.length ? (interpolate = _, zoom) : interpolate;
86992           };
86993
86994           zoom._transform = function (_) {
86995             return arguments.length ? (_transform = _, zoom) : _transform;
86996           };
86997
86998           return utilRebind(zoom, dispatch, 'on');
86999         }
87000
87001         // if pointer events are supported. Falls back to default `dblclick` event.
87002
87003         function utilDoubleUp() {
87004           var dispatch = dispatch$8('doubleUp');
87005           var _maxTimespan = 500; // milliseconds
87006
87007           var _maxDistance = 20; // web pixels; be somewhat generous to account for touch devices
87008
87009           var _pointer; // object representing the pointer that could trigger double up
87010
87011
87012           function pointerIsValidFor(loc) {
87013             // second pointerup must occur within a small timeframe after the first pointerdown
87014             return new Date().getTime() - _pointer.startTime <= _maxTimespan && // all pointer events must occur within a small distance of the first pointerdown
87015             geoVecLength(_pointer.startLoc, loc) <= _maxDistance;
87016           }
87017
87018           function pointerdown(d3_event) {
87019             // ignore right-click
87020             if (d3_event.ctrlKey || d3_event.button === 2) return;
87021             var loc = [d3_event.clientX, d3_event.clientY]; // Don't rely on pointerId here since it can change between pointerdown
87022             // events on touch devices
87023
87024             if (_pointer && !pointerIsValidFor(loc)) {
87025               // if this pointer is no longer valid, clear it so another can be started
87026               _pointer = undefined;
87027             }
87028
87029             if (!_pointer) {
87030               _pointer = {
87031                 startLoc: loc,
87032                 startTime: new Date().getTime(),
87033                 upCount: 0,
87034                 pointerId: d3_event.pointerId
87035               };
87036             } else {
87037               // double down
87038               _pointer.pointerId = d3_event.pointerId;
87039             }
87040           }
87041
87042           function pointerup(d3_event) {
87043             // ignore right-click
87044             if (d3_event.ctrlKey || d3_event.button === 2) return;
87045             if (!_pointer || _pointer.pointerId !== d3_event.pointerId) return;
87046             _pointer.upCount += 1;
87047
87048             if (_pointer.upCount === 2) {
87049               // double up!
87050               var loc = [d3_event.clientX, d3_event.clientY];
87051
87052               if (pointerIsValidFor(loc)) {
87053                 var locInThis = utilFastMouse(this)(d3_event);
87054                 dispatch.call('doubleUp', this, d3_event, locInThis);
87055               } // clear the pointer info in any case
87056
87057
87058               _pointer = undefined;
87059             }
87060           }
87061
87062           function doubleUp(selection) {
87063             if ('PointerEvent' in window) {
87064               // dblclick isn't well supported on touch devices so manually use
87065               // pointer events if they're available
87066               selection.on('pointerdown.doubleUp', pointerdown).on('pointerup.doubleUp', pointerup);
87067             } else {
87068               // fallback to dblclick
87069               selection.on('dblclick.doubleUp', function (d3_event) {
87070                 dispatch.call('doubleUp', this, d3_event, utilFastMouse(this)(d3_event));
87071               });
87072             }
87073           }
87074
87075           doubleUp.off = function (selection) {
87076             selection.on('pointerdown.doubleUp', null).on('pointerup.doubleUp', null).on('dblclick.doubleUp', null);
87077           };
87078
87079           return utilRebind(doubleUp, dispatch, 'on');
87080         }
87081
87082         var TILESIZE = 256;
87083         var minZoom = 2;
87084         var maxZoom = 24;
87085         var kMin = geoZoomToScale(minZoom, TILESIZE);
87086         var kMax = geoZoomToScale(maxZoom, TILESIZE);
87087
87088         function clamp$1(num, min, max) {
87089           return Math.max(min, Math.min(num, max));
87090         }
87091
87092         function rendererMap(context) {
87093           var dispatch = dispatch$8('move', 'drawn', 'crossEditableZoom', 'hitMinZoom', 'changeHighlighting', 'changeAreaFill');
87094           var projection = context.projection;
87095           var curtainProjection = context.curtainProjection;
87096           var drawLayers;
87097           var drawPoints;
87098           var drawVertices;
87099           var drawLines;
87100           var drawAreas;
87101           var drawMidpoints;
87102           var drawLabels;
87103
87104           var _selection = select(null);
87105
87106           var supersurface = select(null);
87107           var wrapper = select(null);
87108           var surface = select(null);
87109           var _dimensions = [1, 1];
87110           var _dblClickZoomEnabled = true;
87111           var _redrawEnabled = true;
87112
87113           var _gestureTransformStart;
87114
87115           var _transformStart = projection.transform();
87116
87117           var _transformLast;
87118
87119           var _isTransformed = false;
87120           var _minzoom = 0;
87121
87122           var _getMouseCoords;
87123
87124           var _lastPointerEvent;
87125
87126           var _lastWithinEditableZoom; // whether a pointerdown event started the zoom
87127
87128
87129           var _pointerDown = false; // use pointer events on supported platforms; fallback to mouse events
87130
87131           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse'; // use pointer event interaction if supported; fallback to touch/mouse events in d3-zoom
87132
87133
87134           var _zoomerPannerFunction = 'PointerEvent' in window ? utilZoomPan : d3_zoom;
87135
87136           var _zoomerPanner = _zoomerPannerFunction().scaleExtent([kMin, kMax]).interpolate(interpolate$1).filter(zoomEventFilter).on('zoom.map', zoomPan).on('start.map', function (d3_event) {
87137             _pointerDown = d3_event && (d3_event.type === 'pointerdown' || d3_event.sourceEvent && d3_event.sourceEvent.type === 'pointerdown');
87138           }).on('end.map', function () {
87139             _pointerDown = false;
87140           });
87141
87142           var _doubleUpHandler = utilDoubleUp();
87143
87144           var scheduleRedraw = throttle(redraw, 750); // var isRedrawScheduled = false;
87145           // var pendingRedrawCall;
87146           // function scheduleRedraw() {
87147           //     // Only schedule the redraw if one has not already been set.
87148           //     if (isRedrawScheduled) return;
87149           //     isRedrawScheduled = true;
87150           //     var that = this;
87151           //     var args = arguments;
87152           //     pendingRedrawCall = window.requestIdleCallback(function () {
87153           //         // Reset the boolean so future redraws can be set.
87154           //         isRedrawScheduled = false;
87155           //         redraw.apply(that, args);
87156           //     }, { timeout: 1400 });
87157           // }
87158
87159
87160           function cancelPendingRedraw() {
87161             scheduleRedraw.cancel(); // isRedrawScheduled = false;
87162             // window.cancelIdleCallback(pendingRedrawCall);
87163           }
87164
87165           function map(selection) {
87166             _selection = selection;
87167             context.on('change.map', immediateRedraw);
87168             var osm = context.connection();
87169
87170             if (osm) {
87171               osm.on('change.map', immediateRedraw);
87172             }
87173
87174             function didUndoOrRedo(targetTransform) {
87175               var mode = context.mode().id;
87176               if (mode !== 'browse' && mode !== 'select') return;
87177
87178               if (targetTransform) {
87179                 map.transformEase(targetTransform);
87180               }
87181             }
87182
87183             context.history().on('merge.map', function () {
87184               scheduleRedraw();
87185             }).on('change.map', immediateRedraw).on('undone.map', function (stack, fromStack) {
87186               didUndoOrRedo(fromStack.transform);
87187             }).on('redone.map', function (stack) {
87188               didUndoOrRedo(stack.transform);
87189             });
87190             context.background().on('change.map', immediateRedraw);
87191             context.features().on('redraw.map', immediateRedraw);
87192             drawLayers.on('change.map', function () {
87193               context.background().updateImagery();
87194               immediateRedraw();
87195             });
87196             selection.on('wheel.map mousewheel.map', function (d3_event) {
87197               // disable swipe-to-navigate browser pages on trackpad/magic mouse – #5552
87198               d3_event.preventDefault();
87199             }).call(_zoomerPanner).call(_zoomerPanner.transform, projection.transform()).on('dblclick.zoom', null); // override d3-zoom dblclick handling
87200
87201             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
87202             // SVG element: http://bl.ocks.org/jfirebaugh/6fbfbd922552bf776c16
87203
87204             wrapper = supersurface.append('div').attr('class', 'layer layer-data');
87205             map.surface = surface = wrapper.call(drawLayers).selectAll('.surface');
87206             surface.call(drawLabels.observe).call(_doubleUpHandler).on(_pointerPrefix + 'down.zoom', function (d3_event) {
87207               _lastPointerEvent = d3_event;
87208
87209               if (d3_event.button === 2) {
87210                 d3_event.stopPropagation();
87211               }
87212             }, true).on(_pointerPrefix + 'up.zoom', function (d3_event) {
87213               _lastPointerEvent = d3_event;
87214
87215               if (resetTransform()) {
87216                 immediateRedraw();
87217               }
87218             }).on(_pointerPrefix + 'move.map', function (d3_event) {
87219               _lastPointerEvent = d3_event;
87220             }).on(_pointerPrefix + 'over.vertices', function (d3_event) {
87221               if (map.editableDataEnabled() && !_isTransformed) {
87222                 var hover = d3_event.target.__data__;
87223                 surface.call(drawVertices.drawHover, context.graph(), hover, map.extent());
87224                 dispatch.call('drawn', this, {
87225                   full: false
87226                 });
87227               }
87228             }).on(_pointerPrefix + 'out.vertices', function (d3_event) {
87229               if (map.editableDataEnabled() && !_isTransformed) {
87230                 var hover = d3_event.relatedTarget && d3_event.relatedTarget.__data__;
87231                 surface.call(drawVertices.drawHover, context.graph(), hover, map.extent());
87232                 dispatch.call('drawn', this, {
87233                   full: false
87234                 });
87235               }
87236             });
87237             var detected = utilDetect(); // only WebKit supports gesture events
87238
87239             if ('GestureEvent' in window && // Listening for gesture events on iOS 13.4+ breaks double-tapping,
87240             // but we only need to do this on desktop Safari anyway. – #7694
87241             !detected.isMobileWebKit) {
87242               // Desktop Safari sends gesture events for multitouch trackpad pinches.
87243               // We can listen for these and translate them into map zooms.
87244               surface.on('gesturestart.surface', function (d3_event) {
87245                 d3_event.preventDefault();
87246                 _gestureTransformStart = projection.transform();
87247               }).on('gesturechange.surface', gestureChange);
87248             } // must call after surface init
87249
87250
87251             updateAreaFill();
87252
87253             _doubleUpHandler.on('doubleUp.map', function (d3_event, p0) {
87254               if (!_dblClickZoomEnabled) return; // don't zoom if targeting something other than the map itself
87255
87256               if (_typeof(d3_event.target.__data__) === 'object' && // or area fills
87257               !select(d3_event.target).classed('fill')) return;
87258               var zoomOut = d3_event.shiftKey;
87259               var t = projection.transform();
87260               var p1 = t.invert(p0);
87261               t = t.scale(zoomOut ? 0.5 : 2);
87262               t.x = p0[0] - p1[0] * t.k;
87263               t.y = p0[1] - p1[1] * t.k;
87264               map.transformEase(t);
87265             });
87266
87267             context.on('enter.map', function () {
87268               if (!map.editableDataEnabled(true
87269               /* skip zoom check */
87270               )) return;
87271               if (_isTransformed) return; // redraw immediately any objects affected by a change in selectedIDs.
87272
87273               var graph = context.graph();
87274               var selectedAndParents = {};
87275               context.selectedIDs().forEach(function (id) {
87276                 var entity = graph.hasEntity(id);
87277
87278                 if (entity) {
87279                   selectedAndParents[entity.id] = entity;
87280
87281                   if (entity.type === 'node') {
87282                     graph.parentWays(entity).forEach(function (parent) {
87283                       selectedAndParents[parent.id] = parent;
87284                     });
87285                   }
87286                 }
87287               });
87288               var data = Object.values(selectedAndParents);
87289
87290               var filter = function filter(d) {
87291                 return d.id in selectedAndParents;
87292               };
87293
87294               data = context.features().filter(data, graph);
87295               surface.call(drawVertices.drawSelected, graph, map.extent()).call(drawLines, graph, data, filter).call(drawAreas, graph, data, filter).call(drawMidpoints, graph, data, filter, map.trimmedExtent());
87296               dispatch.call('drawn', this, {
87297                 full: false
87298               }); // redraw everything else later
87299
87300               scheduleRedraw();
87301             });
87302             map.dimensions(utilGetDimensions(selection));
87303           }
87304
87305           function zoomEventFilter(d3_event) {
87306             // Fix for #2151, (see also d3/d3-zoom#60, d3/d3-brush#18)
87307             // Intercept `mousedown` and check if there is an orphaned zoom gesture.
87308             // This can happen if a previous `mousedown` occurred without a `mouseup`.
87309             // If we detect this, dispatch `mouseup` to complete the orphaned gesture,
87310             // so that d3-zoom won't stop propagation of new `mousedown` events.
87311             if (d3_event.type === 'mousedown') {
87312               var hasOrphan = false;
87313               var listeners = window.__on;
87314
87315               for (var i = 0; i < listeners.length; i++) {
87316                 var listener = listeners[i];
87317
87318                 if (listener.name === 'zoom' && listener.type === 'mouseup') {
87319                   hasOrphan = true;
87320                   break;
87321                 }
87322               }
87323
87324               if (hasOrphan) {
87325                 var event = window.CustomEvent;
87326
87327                 if (event) {
87328                   event = new event('mouseup');
87329                 } else {
87330                   event = window.document.createEvent('Event');
87331                   event.initEvent('mouseup', false, false);
87332                 } // Event needs to be dispatched with an event.view property.
87333
87334
87335                 event.view = window;
87336                 window.dispatchEvent(event);
87337               }
87338             }
87339
87340             return d3_event.button !== 2; // ignore right clicks
87341           }
87342
87343           function pxCenter() {
87344             return [_dimensions[0] / 2, _dimensions[1] / 2];
87345           }
87346
87347           function drawEditable(difference, extent) {
87348             var mode = context.mode();
87349             var graph = context.graph();
87350             var features = context.features();
87351             var all = context.history().intersects(map.extent());
87352             var fullRedraw = false;
87353             var data;
87354             var set;
87355             var filter;
87356             var applyFeatureLayerFilters = true;
87357
87358             if (map.isInWideSelection()) {
87359               data = [];
87360               utilEntityAndDeepMemberIDs(mode.selectedIDs(), context.graph()).forEach(function (id) {
87361                 var entity = context.hasEntity(id);
87362                 if (entity) data.push(entity);
87363               });
87364               fullRedraw = true;
87365               filter = utilFunctor(true); // selected features should always be visible, so we can skip filtering
87366
87367               applyFeatureLayerFilters = false;
87368             } else if (difference) {
87369               var complete = difference.complete(map.extent());
87370               data = Object.values(complete).filter(Boolean);
87371               set = new Set(Object.keys(complete));
87372
87373               filter = function filter(d) {
87374                 return set.has(d.id);
87375               };
87376
87377               features.clear(data);
87378             } else {
87379               // force a full redraw if gatherStats detects that a feature
87380               // should be auto-hidden (e.g. points or buildings)..
87381               if (features.gatherStats(all, graph, _dimensions)) {
87382                 extent = undefined;
87383               }
87384
87385               if (extent) {
87386                 data = context.history().intersects(map.extent().intersection(extent));
87387                 set = new Set(data.map(function (entity) {
87388                   return entity.id;
87389                 }));
87390
87391                 filter = function filter(d) {
87392                   return set.has(d.id);
87393                 };
87394               } else {
87395                 data = all;
87396                 fullRedraw = true;
87397                 filter = utilFunctor(true);
87398               }
87399             }
87400
87401             if (applyFeatureLayerFilters) {
87402               data = features.filter(data, graph);
87403             } else {
87404               context.features().resetStats();
87405             }
87406
87407             if (mode && mode.id === 'select') {
87408               // update selected vertices - the user might have just double-clicked a way,
87409               // creating a new vertex, triggering a partial redraw without a mode change
87410               surface.call(drawVertices.drawSelected, graph, map.extent());
87411             }
87412
87413             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);
87414             dispatch.call('drawn', this, {
87415               full: true
87416             });
87417           }
87418
87419           map.init = function () {
87420             drawLayers = svgLayers(projection, context);
87421             drawPoints = svgPoints(projection, context);
87422             drawVertices = svgVertices(projection, context);
87423             drawLines = svgLines(projection, context);
87424             drawAreas = svgAreas(projection, context);
87425             drawMidpoints = svgMidpoints(projection, context);
87426             drawLabels = svgLabels(projection, context);
87427           };
87428
87429           function editOff() {
87430             context.features().resetStats();
87431             surface.selectAll('.layer-osm *').remove();
87432             surface.selectAll('.layer-touch:not(.markers) *').remove();
87433             var allowed = {
87434               'browse': true,
87435               'save': true,
87436               'select-note': true,
87437               'select-data': true,
87438               'select-error': true
87439             };
87440             var mode = context.mode();
87441
87442             if (mode && !allowed[mode.id]) {
87443               context.enter(modeBrowse(context));
87444             }
87445
87446             dispatch.call('drawn', this, {
87447               full: true
87448             });
87449           }
87450
87451           function gestureChange(d3_event) {
87452             // Remap Safari gesture events to wheel events - #5492
87453             // We want these disabled most places, but enabled for zoom/unzoom on map surface
87454             // https://developer.mozilla.org/en-US/docs/Web/API/GestureEvent
87455             var e = d3_event;
87456             e.preventDefault();
87457             var props = {
87458               deltaMode: 0,
87459               // dummy values to ignore in zoomPan
87460               deltaY: 1,
87461               // dummy values to ignore in zoomPan
87462               clientX: e.clientX,
87463               clientY: e.clientY,
87464               screenX: e.screenX,
87465               screenY: e.screenY,
87466               x: e.x,
87467               y: e.y
87468             };
87469             var e2 = new WheelEvent('wheel', props);
87470             e2._scale = e.scale; // preserve the original scale
87471
87472             e2._rotation = e.rotation; // preserve the original rotation
87473
87474             _selection.node().dispatchEvent(e2);
87475           }
87476
87477           function zoomPan(event, key, transform) {
87478             var source = event && event.sourceEvent || event;
87479             var eventTransform = transform || event && event.transform;
87480             var x = eventTransform.x;
87481             var y = eventTransform.y;
87482             var k = eventTransform.k; // Special handling of 'wheel' events:
87483             // They might be triggered by the user scrolling the mouse wheel,
87484             // or 2-finger pinch/zoom gestures, the transform may need adjustment.
87485
87486             if (source && source.type === 'wheel') {
87487               // assume that the gesture is already handled by pointer events
87488               if (_pointerDown) return;
87489               var detected = utilDetect();
87490               var dX = source.deltaX;
87491               var dY = source.deltaY;
87492               var x2 = x;
87493               var y2 = y;
87494               var k2 = k;
87495               var t0, p0, p1; // Normalize mousewheel scroll speed (Firefox) - #3029
87496               // If wheel delta is provided in LINE units, recalculate it in PIXEL units
87497               // We are essentially redoing the calculations that occur here:
87498               //   https://github.com/d3/d3-zoom/blob/78563a8348aa4133b07cac92e2595c2227ca7cd7/src/zoom.js#L203
87499               // See this for more info:
87500               //   https://github.com/basilfx/normalize-wheel/blob/master/src/normalizeWheel.js
87501
87502               if (source.deltaMode === 1
87503               /* LINE */
87504               ) {
87505                 // Convert from lines to pixels, more if the user is scrolling fast.
87506                 // (I made up the exp function to roughly match Firefox to what Chrome does)
87507                 // These numbers should be floats, because integers are treated as pan gesture below.
87508                 var lines = Math.abs(source.deltaY);
87509                 var sign = source.deltaY > 0 ? 1 : -1;
87510                 dY = sign * clamp$1(Math.exp((lines - 1) * 0.75) * 4.000244140625, 4.000244140625, // min
87511                 350.000244140625 // max
87512                 ); // On Firefox Windows and Linux we always get +/- the scroll line amount (default 3)
87513                 // There doesn't seem to be any scroll acceleration.
87514                 // This multiplier increases the speed a little bit - #5512
87515
87516                 if (detected.os !== 'mac') {
87517                   dY *= 5;
87518                 } // recalculate x2,y2,k2
87519
87520
87521                 t0 = _isTransformed ? _transformLast : _transformStart;
87522                 p0 = _getMouseCoords(source);
87523                 p1 = t0.invert(p0);
87524                 k2 = t0.k * Math.pow(2, -dY / 500);
87525                 k2 = clamp$1(k2, kMin, kMax);
87526                 x2 = p0[0] - p1[0] * k2;
87527                 y2 = p0[1] - p1[1] * k2; // 2 finger map pinch zooming (Safari) - #5492
87528                 // These are fake `wheel` events we made from Safari `gesturechange` events..
87529               } else if (source._scale) {
87530                 // recalculate x2,y2,k2
87531                 t0 = _gestureTransformStart;
87532                 p0 = _getMouseCoords(source);
87533                 p1 = t0.invert(p0);
87534                 k2 = t0.k * source._scale;
87535                 k2 = clamp$1(k2, kMin, kMax);
87536                 x2 = p0[0] - p1[0] * k2;
87537                 y2 = p0[1] - p1[1] * k2; // 2 finger map pinch zooming (all browsers except Safari) - #5492
87538                 // Pinch zooming via the `wheel` event will always have:
87539                 // - `ctrlKey = true`
87540                 // - `deltaY` is not round integer pixels (ignore `deltaX`)
87541               } else if (source.ctrlKey && !isInteger(dY)) {
87542                 dY *= 6; // slightly scale up whatever the browser gave us
87543                 // recalculate x2,y2,k2
87544
87545                 t0 = _isTransformed ? _transformLast : _transformStart;
87546                 p0 = _getMouseCoords(source);
87547                 p1 = t0.invert(p0);
87548                 k2 = t0.k * Math.pow(2, -dY / 500);
87549                 k2 = clamp$1(k2, kMin, kMax);
87550                 x2 = p0[0] - p1[0] * k2;
87551                 y2 = p0[1] - p1[1] * k2; // Trackpad scroll zooming with shift or alt/option key down
87552               } else if ((source.altKey || source.shiftKey) && isInteger(dY)) {
87553                 // recalculate x2,y2,k2
87554                 t0 = _isTransformed ? _transformLast : _transformStart;
87555                 p0 = _getMouseCoords(source);
87556                 p1 = t0.invert(p0);
87557                 k2 = t0.k * Math.pow(2, -dY / 500);
87558                 k2 = clamp$1(k2, kMin, kMax);
87559                 x2 = p0[0] - p1[0] * k2;
87560                 y2 = p0[1] - p1[1] * k2; // 2 finger map panning (Mac only, all browsers except Firefox #8595) - #5492, #5512
87561                 // Panning via the `wheel` event will always have:
87562                 // - `ctrlKey = false`
87563                 // - `deltaX`,`deltaY` are round integer pixels
87564               } else if (detected.os === 'mac' && detected.browser !== 'Firefox' && !source.ctrlKey && isInteger(dX) && isInteger(dY)) {
87565                 p1 = projection.translate();
87566                 x2 = p1[0] - dX;
87567                 y2 = p1[1] - dY;
87568                 k2 = projection.scale();
87569                 k2 = clamp$1(k2, kMin, kMax);
87570               } // something changed - replace the event transform
87571
87572
87573               if (x2 !== x || y2 !== y || k2 !== k) {
87574                 x = x2;
87575                 y = y2;
87576                 k = k2;
87577                 eventTransform = identity$2.translate(x2, y2).scale(k2);
87578
87579                 if (_zoomerPanner._transform) {
87580                   // utilZoomPan interface
87581                   _zoomerPanner._transform(eventTransform);
87582                 } else {
87583                   // d3_zoom interface
87584                   _selection.node().__zoom = eventTransform;
87585                 }
87586               }
87587             }
87588
87589             if (_transformStart.x === x && _transformStart.y === y && _transformStart.k === k) {
87590               return; // no change
87591             }
87592
87593             if (geoScaleToZoom(k, TILESIZE) < _minzoom) {
87594               surface.interrupt();
87595               dispatch.call('hitMinZoom', this, map);
87596               setCenterZoom(map.center(), context.minEditableZoom(), 0, true);
87597               scheduleRedraw();
87598               dispatch.call('move', this, map);
87599               return;
87600             }
87601
87602             projection.transform(eventTransform);
87603             var withinEditableZoom = map.withinEditableZoom();
87604
87605             if (_lastWithinEditableZoom !== withinEditableZoom) {
87606               if (_lastWithinEditableZoom !== undefined) {
87607                 // notify that the map zoomed in or out over the editable zoom threshold
87608                 dispatch.call('crossEditableZoom', this, withinEditableZoom);
87609               }
87610
87611               _lastWithinEditableZoom = withinEditableZoom;
87612             }
87613
87614             var scale = k / _transformStart.k;
87615             var tX = (x / scale - _transformStart.x) * scale;
87616             var tY = (y / scale - _transformStart.y) * scale;
87617
87618             if (context.inIntro()) {
87619               curtainProjection.transform({
87620                 x: x - tX,
87621                 y: y - tY,
87622                 k: k
87623               });
87624             }
87625
87626             if (source) {
87627               _lastPointerEvent = event;
87628             }
87629
87630             _isTransformed = true;
87631             _transformLast = eventTransform;
87632             utilSetTransform(supersurface, tX, tY, scale);
87633             scheduleRedraw();
87634             dispatch.call('move', this, map);
87635
87636             function isInteger(val) {
87637               return typeof val === 'number' && isFinite(val) && Math.floor(val) === val;
87638             }
87639           }
87640
87641           function resetTransform() {
87642             if (!_isTransformed) return false;
87643             utilSetTransform(supersurface, 0, 0);
87644             _isTransformed = false;
87645
87646             if (context.inIntro()) {
87647               curtainProjection.transform(projection.transform());
87648             }
87649
87650             return true;
87651           }
87652
87653           function redraw(difference, extent) {
87654             if (surface.empty() || !_redrawEnabled) return; // If we are in the middle of a zoom/pan, we can't do differenced redraws.
87655             // It would result in artifacts where differenced entities are redrawn with
87656             // one transform and unchanged entities with another.
87657
87658             if (resetTransform()) {
87659               difference = extent = undefined;
87660             }
87661
87662             var zoom = map.zoom();
87663             var z = String(~~zoom);
87664
87665             if (surface.attr('data-zoom') !== z) {
87666               surface.attr('data-zoom', z);
87667             } // class surface as `lowzoom` around z17-z18.5 (based on latitude)
87668
87669
87670             var lat = map.center()[1];
87671             var lowzoom = linear().domain([-60, 0, 60]).range([17, 18.5, 17]).clamp(true);
87672             surface.classed('low-zoom', zoom <= lowzoom(lat));
87673
87674             if (!difference) {
87675               supersurface.call(context.background());
87676               wrapper.call(drawLayers);
87677             } // OSM
87678
87679
87680             if (map.editableDataEnabled() || map.isInWideSelection()) {
87681               context.loadTiles(projection);
87682               drawEditable(difference, extent);
87683             } else {
87684               editOff();
87685             }
87686
87687             _transformStart = projection.transform();
87688             return map;
87689           }
87690
87691           var immediateRedraw = function immediateRedraw(difference, extent) {
87692             if (!difference && !extent) cancelPendingRedraw();
87693             redraw(difference, extent);
87694           };
87695
87696           map.lastPointerEvent = function () {
87697             return _lastPointerEvent;
87698           };
87699
87700           map.mouse = function (d3_event) {
87701             var event = d3_event || _lastPointerEvent;
87702
87703             if (event) {
87704               var s;
87705
87706               while (s = event.sourceEvent) {
87707                 event = s;
87708               }
87709
87710               return _getMouseCoords(event);
87711             }
87712
87713             return null;
87714           }; // returns Lng/Lat
87715
87716
87717           map.mouseCoordinates = function () {
87718             var coord = map.mouse() || pxCenter();
87719             return projection.invert(coord);
87720           };
87721
87722           map.dblclickZoomEnable = function (val) {
87723             if (!arguments.length) return _dblClickZoomEnabled;
87724             _dblClickZoomEnabled = val;
87725             return map;
87726           };
87727
87728           map.redrawEnable = function (val) {
87729             if (!arguments.length) return _redrawEnabled;
87730             _redrawEnabled = val;
87731             return map;
87732           };
87733
87734           map.isTransformed = function () {
87735             return _isTransformed;
87736           };
87737
87738           function setTransform(t2, duration, force) {
87739             var t = projection.transform();
87740             if (!force && t2.k === t.k && t2.x === t.x && t2.y === t.y) return false;
87741
87742             if (duration) {
87743               _selection.transition().duration(duration).on('start', function () {
87744                 map.startEase();
87745               }).call(_zoomerPanner.transform, identity$2.translate(t2.x, t2.y).scale(t2.k));
87746             } else {
87747               projection.transform(t2);
87748               _transformStart = t2;
87749
87750               _selection.call(_zoomerPanner.transform, _transformStart);
87751             }
87752
87753             return true;
87754           }
87755
87756           function setCenterZoom(loc2, z2, duration, force) {
87757             var c = map.center();
87758             var z = map.zoom();
87759             if (loc2[0] === c[0] && loc2[1] === c[1] && z2 === z && !force) return false;
87760             var proj = geoRawMercator().transform(projection.transform()); // copy projection
87761
87762             var k2 = clamp$1(geoZoomToScale(z2, TILESIZE), kMin, kMax);
87763             proj.scale(k2);
87764             var t = proj.translate();
87765             var point = proj(loc2);
87766             var center = pxCenter();
87767             t[0] += center[0] - point[0];
87768             t[1] += center[1] - point[1];
87769             return setTransform(identity$2.translate(t[0], t[1]).scale(k2), duration, force);
87770           }
87771
87772           map.pan = function (delta, duration) {
87773             var t = projection.translate();
87774             var k = projection.scale();
87775             t[0] += delta[0];
87776             t[1] += delta[1];
87777
87778             if (duration) {
87779               _selection.transition().duration(duration).on('start', function () {
87780                 map.startEase();
87781               }).call(_zoomerPanner.transform, identity$2.translate(t[0], t[1]).scale(k));
87782             } else {
87783               projection.translate(t);
87784               _transformStart = projection.transform();
87785
87786               _selection.call(_zoomerPanner.transform, _transformStart);
87787
87788               dispatch.call('move', this, map);
87789               immediateRedraw();
87790             }
87791
87792             return map;
87793           };
87794
87795           map.dimensions = function (val) {
87796             if (!arguments.length) return _dimensions;
87797             _dimensions = val;
87798             drawLayers.dimensions(_dimensions);
87799             context.background().dimensions(_dimensions);
87800             projection.clipExtent([[0, 0], _dimensions]);
87801             _getMouseCoords = utilFastMouse(supersurface.node());
87802             scheduleRedraw();
87803             return map;
87804           };
87805
87806           function zoomIn(delta) {
87807             setCenterZoom(map.center(), ~~map.zoom() + delta, 250, true);
87808           }
87809
87810           function zoomOut(delta) {
87811             setCenterZoom(map.center(), ~~map.zoom() - delta, 250, true);
87812           }
87813
87814           map.zoomIn = function () {
87815             zoomIn(1);
87816           };
87817
87818           map.zoomInFurther = function () {
87819             zoomIn(4);
87820           };
87821
87822           map.canZoomIn = function () {
87823             return map.zoom() < maxZoom;
87824           };
87825
87826           map.zoomOut = function () {
87827             zoomOut(1);
87828           };
87829
87830           map.zoomOutFurther = function () {
87831             zoomOut(4);
87832           };
87833
87834           map.canZoomOut = function () {
87835             return map.zoom() > minZoom;
87836           };
87837
87838           map.center = function (loc2) {
87839             if (!arguments.length) {
87840               return projection.invert(pxCenter());
87841             }
87842
87843             if (setCenterZoom(loc2, map.zoom())) {
87844               dispatch.call('move', this, map);
87845             }
87846
87847             scheduleRedraw();
87848             return map;
87849           };
87850
87851           map.unobscuredCenterZoomEase = function (loc, zoom) {
87852             var offset = map.unobscuredOffsetPx();
87853             var proj = geoRawMercator().transform(projection.transform()); // copy projection
87854             // use the target zoom to calculate the offset center
87855
87856             proj.scale(geoZoomToScale(zoom, TILESIZE));
87857             var locPx = proj(loc);
87858             var offsetLocPx = [locPx[0] + offset[0], locPx[1] + offset[1]];
87859             var offsetLoc = proj.invert(offsetLocPx);
87860             map.centerZoomEase(offsetLoc, zoom);
87861           };
87862
87863           map.unobscuredOffsetPx = function () {
87864             var openPane = context.container().select('.map-panes .map-pane.shown');
87865
87866             if (!openPane.empty()) {
87867               return [openPane.node().offsetWidth / 2, 0];
87868             }
87869
87870             return [0, 0];
87871           };
87872
87873           map.zoom = function (z2) {
87874             if (!arguments.length) {
87875               return Math.max(geoScaleToZoom(projection.scale(), TILESIZE), 0);
87876             }
87877
87878             if (z2 < _minzoom) {
87879               surface.interrupt();
87880               dispatch.call('hitMinZoom', this, map);
87881               z2 = context.minEditableZoom();
87882             }
87883
87884             if (setCenterZoom(map.center(), z2)) {
87885               dispatch.call('move', this, map);
87886             }
87887
87888             scheduleRedraw();
87889             return map;
87890           };
87891
87892           map.centerZoom = function (loc2, z2) {
87893             if (setCenterZoom(loc2, z2)) {
87894               dispatch.call('move', this, map);
87895             }
87896
87897             scheduleRedraw();
87898             return map;
87899           };
87900
87901           map.zoomTo = function (entity) {
87902             var extent = entity.extent(context.graph());
87903             if (!isFinite(extent.area())) return map;
87904             var z2 = clamp$1(map.trimmedExtentZoom(extent), 0, 20);
87905             return map.centerZoom(extent.center(), z2);
87906           };
87907
87908           map.centerEase = function (loc2, duration) {
87909             duration = duration || 250;
87910             setCenterZoom(loc2, map.zoom(), duration);
87911             return map;
87912           };
87913
87914           map.zoomEase = function (z2, duration) {
87915             duration = duration || 250;
87916             setCenterZoom(map.center(), z2, duration, false);
87917             return map;
87918           };
87919
87920           map.centerZoomEase = function (loc2, z2, duration) {
87921             duration = duration || 250;
87922             setCenterZoom(loc2, z2, duration, false);
87923             return map;
87924           };
87925
87926           map.transformEase = function (t2, duration) {
87927             duration = duration || 250;
87928             setTransform(t2, duration, false
87929             /* don't force */
87930             );
87931             return map;
87932           };
87933
87934           map.zoomToEase = function (obj, duration) {
87935             var extent;
87936
87937             if (Array.isArray(obj)) {
87938               obj.forEach(function (entity) {
87939                 var entityExtent = entity.extent(context.graph());
87940
87941                 if (!extent) {
87942                   extent = entityExtent;
87943                 } else {
87944                   extent = extent.extend(entityExtent);
87945                 }
87946               });
87947             } else {
87948               extent = obj.extent(context.graph());
87949             }
87950
87951             if (!isFinite(extent.area())) return map;
87952             var z2 = clamp$1(map.trimmedExtentZoom(extent), 0, 20);
87953             return map.centerZoomEase(extent.center(), z2, duration);
87954           };
87955
87956           map.startEase = function () {
87957             utilBindOnce(surface, _pointerPrefix + 'down.ease', function () {
87958               map.cancelEase();
87959             });
87960             return map;
87961           };
87962
87963           map.cancelEase = function () {
87964             _selection.interrupt();
87965
87966             return map;
87967           };
87968
87969           map.extent = function (val) {
87970             if (!arguments.length) {
87971               return new geoExtent(projection.invert([0, _dimensions[1]]), projection.invert([_dimensions[0], 0]));
87972             } else {
87973               var extent = geoExtent(val);
87974               map.centerZoom(extent.center(), map.extentZoom(extent));
87975             }
87976           };
87977
87978           map.trimmedExtent = function (val) {
87979             if (!arguments.length) {
87980               var headerY = 71;
87981               var footerY = 30;
87982               var pad = 10;
87983               return new geoExtent(projection.invert([pad, _dimensions[1] - footerY - pad]), projection.invert([_dimensions[0] - pad, headerY + pad]));
87984             } else {
87985               var extent = geoExtent(val);
87986               map.centerZoom(extent.center(), map.trimmedExtentZoom(extent));
87987             }
87988           };
87989
87990           function calcExtentZoom(extent, dim) {
87991             var tl = projection([extent[0][0], extent[1][1]]);
87992             var br = projection([extent[1][0], extent[0][1]]); // Calculate maximum zoom that fits extent
87993
87994             var hFactor = (br[0] - tl[0]) / dim[0];
87995             var vFactor = (br[1] - tl[1]) / dim[1];
87996             var hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2;
87997             var vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2;
87998             var newZoom = map.zoom() - Math.max(hZoomDiff, vZoomDiff);
87999             return newZoom;
88000           }
88001
88002           map.extentZoom = function (val) {
88003             return calcExtentZoom(geoExtent(val), _dimensions);
88004           };
88005
88006           map.trimmedExtentZoom = function (val) {
88007             var trimY = 120;
88008             var trimX = 40;
88009             var trimmed = [_dimensions[0] - trimX, _dimensions[1] - trimY];
88010             return calcExtentZoom(geoExtent(val), trimmed);
88011           };
88012
88013           map.withinEditableZoom = function () {
88014             return map.zoom() >= context.minEditableZoom();
88015           };
88016
88017           map.isInWideSelection = function () {
88018             return !map.withinEditableZoom() && context.selectedIDs().length;
88019           };
88020
88021           map.editableDataEnabled = function (skipZoomCheck) {
88022             var layer = context.layers().layer('osm');
88023             if (!layer || !layer.enabled()) return false;
88024             return skipZoomCheck || map.withinEditableZoom();
88025           };
88026
88027           map.notesEditable = function () {
88028             var layer = context.layers().layer('notes');
88029             if (!layer || !layer.enabled()) return false;
88030             return map.withinEditableZoom();
88031           };
88032
88033           map.minzoom = function (val) {
88034             if (!arguments.length) return _minzoom;
88035             _minzoom = val;
88036             return map;
88037           };
88038
88039           map.toggleHighlightEdited = function () {
88040             surface.classed('highlight-edited', !surface.classed('highlight-edited'));
88041             map.pan([0, 0]); // trigger a redraw
88042
88043             dispatch.call('changeHighlighting', this);
88044           };
88045
88046           map.areaFillOptions = ['wireframe', 'partial', 'full'];
88047
88048           map.activeAreaFill = function (val) {
88049             if (!arguments.length) return corePreferences('area-fill') || 'partial';
88050             corePreferences('area-fill', val);
88051
88052             if (val !== 'wireframe') {
88053               corePreferences('area-fill-toggle', val);
88054             }
88055
88056             updateAreaFill();
88057             map.pan([0, 0]); // trigger a redraw
88058
88059             dispatch.call('changeAreaFill', this);
88060             return map;
88061           };
88062
88063           map.toggleWireframe = function () {
88064             var activeFill = map.activeAreaFill();
88065
88066             if (activeFill === 'wireframe') {
88067               activeFill = corePreferences('area-fill-toggle') || 'partial';
88068             } else {
88069               activeFill = 'wireframe';
88070             }
88071
88072             map.activeAreaFill(activeFill);
88073           };
88074
88075           function updateAreaFill() {
88076             var activeFill = map.activeAreaFill();
88077             map.areaFillOptions.forEach(function (opt) {
88078               surface.classed('fill-' + opt, Boolean(opt === activeFill));
88079             });
88080           }
88081
88082           map.layers = function () {
88083             return drawLayers;
88084           };
88085
88086           map.doubleUpHandler = function () {
88087             return _doubleUpHandler;
88088           };
88089
88090           return utilRebind(map, dispatch, 'on');
88091         }
88092
88093         function rendererPhotos(context) {
88094           var dispatch = dispatch$8('change');
88095           var _layerIDs = ['streetside', 'mapillary', 'mapillary-map-features', 'mapillary-signs', 'kartaview'];
88096           var _allPhotoTypes = ['flat', 'panoramic'];
88097
88098           var _shownPhotoTypes = _allPhotoTypes.slice(); // shallow copy
88099
88100
88101           var _dateFilters = ['fromDate', 'toDate'];
88102
88103           var _fromDate;
88104
88105           var _toDate;
88106
88107           var _usernames;
88108
88109           function photos() {}
88110
88111           function updateStorage() {
88112             if (window.mocha) return;
88113             var hash = utilStringQs(window.location.hash);
88114             var enabled = context.layers().all().filter(function (d) {
88115               return _layerIDs.indexOf(d.id) !== -1 && d.layer && d.layer.supported() && d.layer.enabled();
88116             }).map(function (d) {
88117               return d.id;
88118             });
88119
88120             if (enabled.length) {
88121               hash.photo_overlay = enabled.join(',');
88122             } else {
88123               delete hash.photo_overlay;
88124             }
88125
88126             window.location.replace('#' + utilQsString(hash, true));
88127           }
88128
88129           photos.overlayLayerIDs = function () {
88130             return _layerIDs;
88131           };
88132
88133           photos.allPhotoTypes = function () {
88134             return _allPhotoTypes;
88135           };
88136
88137           photos.dateFilters = function () {
88138             return _dateFilters;
88139           };
88140
88141           photos.dateFilterValue = function (val) {
88142             return val === _dateFilters[0] ? _fromDate : _toDate;
88143           };
88144
88145           photos.setDateFilter = function (type, val, updateUrl) {
88146             // validate the date
88147             var date = val && new Date(val);
88148
88149             if (date && !isNaN(date)) {
88150               val = date.toISOString().substr(0, 10);
88151             } else {
88152               val = null;
88153             }
88154
88155             if (type === _dateFilters[0]) {
88156               _fromDate = val;
88157
88158               if (_fromDate && _toDate && new Date(_toDate) < new Date(_fromDate)) {
88159                 _toDate = _fromDate;
88160               }
88161             }
88162
88163             if (type === _dateFilters[1]) {
88164               _toDate = val;
88165
88166               if (_fromDate && _toDate && new Date(_toDate) < new Date(_fromDate)) {
88167                 _fromDate = _toDate;
88168               }
88169             }
88170
88171             dispatch.call('change', this);
88172
88173             if (updateUrl) {
88174               var rangeString;
88175
88176               if (_fromDate || _toDate) {
88177                 rangeString = (_fromDate || '') + '_' + (_toDate || '');
88178               }
88179
88180               setUrlFilterValue('photo_dates', rangeString);
88181             }
88182           };
88183
88184           photos.setUsernameFilter = function (val, updateUrl) {
88185             if (val && typeof val === 'string') val = val.replace(/;/g, ',').split(',');
88186
88187             if (val) {
88188               val = val.map(function (d) {
88189                 return d.trim();
88190               }).filter(Boolean);
88191
88192               if (!val.length) {
88193                 val = null;
88194               }
88195             }
88196
88197             _usernames = val;
88198             dispatch.call('change', this);
88199
88200             if (updateUrl) {
88201               var hashString;
88202
88203               if (_usernames) {
88204                 hashString = _usernames.join(',');
88205               }
88206
88207               setUrlFilterValue('photo_username', hashString);
88208             }
88209           };
88210
88211           function setUrlFilterValue(property, val) {
88212             if (!window.mocha) {
88213               var hash = utilStringQs(window.location.hash);
88214
88215               if (val) {
88216                 if (hash[property] === val) return;
88217                 hash[property] = val;
88218               } else {
88219                 if (!(property in hash)) return;
88220                 delete hash[property];
88221               }
88222
88223               window.location.replace('#' + utilQsString(hash, true));
88224             }
88225           }
88226
88227           function showsLayer(id) {
88228             var layer = context.layers().layer(id);
88229             return layer && layer.supported() && layer.enabled();
88230           }
88231
88232           photos.shouldFilterByDate = function () {
88233             return showsLayer('mapillary') || showsLayer('kartaview') || showsLayer('streetside');
88234           };
88235
88236           photos.shouldFilterByPhotoType = function () {
88237             return showsLayer('mapillary') || showsLayer('streetside') && showsLayer('kartaview');
88238           };
88239
88240           photos.shouldFilterByUsername = function () {
88241             return !showsLayer('mapillary') && showsLayer('kartaview') && !showsLayer('streetside');
88242           };
88243
88244           photos.showsPhotoType = function (val) {
88245             if (!photos.shouldFilterByPhotoType()) return true;
88246             return _shownPhotoTypes.indexOf(val) !== -1;
88247           };
88248
88249           photos.showsFlat = function () {
88250             return photos.showsPhotoType('flat');
88251           };
88252
88253           photos.showsPanoramic = function () {
88254             return photos.showsPhotoType('panoramic');
88255           };
88256
88257           photos.fromDate = function () {
88258             return _fromDate;
88259           };
88260
88261           photos.toDate = function () {
88262             return _toDate;
88263           };
88264
88265           photos.togglePhotoType = function (val) {
88266             var index = _shownPhotoTypes.indexOf(val);
88267
88268             if (index !== -1) {
88269               _shownPhotoTypes.splice(index, 1);
88270             } else {
88271               _shownPhotoTypes.push(val);
88272             }
88273
88274             dispatch.call('change', this);
88275             return photos;
88276           };
88277
88278           photos.usernames = function () {
88279             return _usernames;
88280           };
88281
88282           photos.init = function () {
88283             var hash = utilStringQs(window.location.hash);
88284
88285             if (hash.photo_dates) {
88286               // expect format like `photo_dates=2019-01-01_2020-12-31`, but allow a couple different separators
88287               var parts = /^(.*)[–_](.*)$/g.exec(hash.photo_dates.trim());
88288               this.setDateFilter('fromDate', parts && parts.length >= 2 && parts[1], false);
88289               this.setDateFilter('toDate', parts && parts.length >= 3 && parts[2], false);
88290             }
88291
88292             if (hash.photo_username) {
88293               this.setUsernameFilter(hash.photo_username, false);
88294             }
88295
88296             if (hash.photo_overlay) {
88297               // support enabling photo layers by default via a URL parameter, e.g. `photo_overlay=kartaview;mapillary;streetside`
88298               var hashOverlayIDs = hash.photo_overlay.replace(/;/g, ',').split(',');
88299               hashOverlayIDs.forEach(function (id) {
88300                 if (id === 'openstreetcam') id = 'kartaview'; // legacy alias
88301
88302                 var layer = _layerIDs.indexOf(id) !== -1 && context.layers().layer(id);
88303                 if (layer && !layer.enabled()) layer.enabled(true);
88304               });
88305             }
88306
88307             if (hash.photo) {
88308               // support opening a photo via a URL parameter, e.g. `photo=mapillary-fztgSDtLpa08ohPZFZjeRQ`
88309               var photoIds = hash.photo.replace(/;/g, ',').split(',');
88310               var photoId = photoIds.length && photoIds[0].trim();
88311               var results = /(.*)\/(.*)/g.exec(photoId);
88312
88313               if (results && results.length >= 3) {
88314                 var serviceId = results[1];
88315                 if (serviceId === 'openstreetcam') serviceId = 'kartaview'; // legacy alias
88316
88317                 var photoKey = results[2];
88318                 var service = services[serviceId];
88319
88320                 if (service && service.ensureViewerLoaded) {
88321                   // if we're showing a photo then make sure its layer is enabled too
88322                   var layer = _layerIDs.indexOf(serviceId) !== -1 && context.layers().layer(serviceId);
88323                   if (layer && !layer.enabled()) layer.enabled(true);
88324                   var baselineTime = Date.now();
88325                   service.on('loadedImages.rendererPhotos', function () {
88326                     // don't open the viewer if too much time has elapsed
88327                     if (Date.now() - baselineTime > 45000) {
88328                       service.on('loadedImages.rendererPhotos', null);
88329                       return;
88330                     }
88331
88332                     if (!service.cachedImage(photoKey)) return;
88333                     service.on('loadedImages.rendererPhotos', null);
88334                     service.ensureViewerLoaded(context).then(function () {
88335                       service.selectImage(context, photoKey).showViewer(context);
88336                     });
88337                   });
88338                 }
88339               }
88340             }
88341
88342             context.layers().on('change.rendererPhotos', updateStorage);
88343           };
88344
88345           return utilRebind(photos, dispatch, 'on');
88346         }
88347
88348         function uiAccount(context) {
88349           var osm = context.connection();
88350
88351           function update(selection) {
88352             if (!osm) return;
88353
88354             if (!osm.authenticated()) {
88355               selection.selectAll('.userLink, .logoutLink').classed('hide', true);
88356               return;
88357             }
88358
88359             osm.userDetails(function (err, details) {
88360               var userLink = selection.select('.userLink'),
88361                   logoutLink = selection.select('.logoutLink');
88362               userLink.html('');
88363               logoutLink.html('');
88364               if (err || !details) return;
88365               selection.selectAll('.userLink, .logoutLink').classed('hide', false); // Link
88366
88367               var userLinkA = userLink.append('a').attr('href', osm.userURL(details.display_name)).attr('target', '_blank'); // Add thumbnail or dont
88368
88369               if (details.image_url) {
88370                 userLinkA.append('img').attr('class', 'icon pre-text user-icon').attr('src', details.image_url);
88371               } else {
88372                 userLinkA.call(svgIcon('#iD-icon-avatar', 'pre-text light'));
88373               } // Add user name
88374
88375
88376               userLinkA.append('span').attr('class', 'label').html(details.display_name);
88377               logoutLink.append('a').attr('class', 'logout').attr('href', '#').call(_t.append('logout')).on('click.logout', function (d3_event) {
88378                 d3_event.preventDefault();
88379                 osm.logout();
88380               });
88381             });
88382           }
88383
88384           return function (selection) {
88385             selection.append('li').attr('class', 'userLink').classed('hide', true);
88386             selection.append('li').attr('class', 'logoutLink').classed('hide', true);
88387
88388             if (osm) {
88389               osm.on('change.account', function () {
88390                 update(selection);
88391               });
88392               update(selection);
88393             }
88394           };
88395         }
88396
88397         function uiAttribution(context) {
88398           var _selection = select(null);
88399
88400           function render(selection, data, klass) {
88401             var div = selection.selectAll(".".concat(klass)).data([0]);
88402             div = div.enter().append('div').attr('class', klass).merge(div);
88403             var attributions = div.selectAll('.attribution').data(data, function (d) {
88404               return d.id;
88405             });
88406             attributions.exit().remove();
88407             attributions = attributions.enter().append('span').attr('class', 'attribution').each(function (d, i, nodes) {
88408               var attribution = select(nodes[i]);
88409
88410               if (d.terms_html) {
88411                 attribution.html(d.terms_html);
88412                 return;
88413               }
88414
88415               if (d.terms_url) {
88416                 attribution = attribution.append('a').attr('href', d.terms_url).attr('target', '_blank');
88417               }
88418
88419               var sourceID = d.id.replace(/\./g, '<TX_DOT>');
88420               var terms_text = _t("imagery.".concat(sourceID, ".attribution.text"), {
88421                 "default": d.terms_text || d.id || d.name()
88422               });
88423
88424               if (d.icon && !d.overlay) {
88425                 attribution.append('img').attr('class', 'source-image').attr('src', d.icon);
88426               }
88427
88428               attribution.append('span').attr('class', 'attribution-text').text(terms_text);
88429             }).merge(attributions);
88430             var copyright = attributions.selectAll('.copyright-notice').data(function (d) {
88431               var notice = d.copyrightNotices(context.map().zoom(), context.map().extent());
88432               return notice ? [notice] : [];
88433             });
88434             copyright.exit().remove();
88435             copyright = copyright.enter().append('span').attr('class', 'copyright-notice').merge(copyright);
88436             copyright.text(String);
88437           }
88438
88439           function update() {
88440             var baselayer = context.background().baseLayerSource();
88441
88442             _selection.call(render, baselayer ? [baselayer] : [], 'base-layer-attribution');
88443
88444             var z = context.map().zoom();
88445             var overlays = context.background().overlayLayerSources() || [];
88446
88447             _selection.call(render, overlays.filter(function (s) {
88448               return s.validZoom(z);
88449             }), 'overlay-layer-attribution');
88450           }
88451
88452           return function (selection) {
88453             _selection = selection;
88454             context.background().on('change.attribution', update);
88455             context.map().on('move.attribution', throttle(update, 400, {
88456               leading: false
88457             }));
88458             update();
88459           };
88460         }
88461
88462         function uiContributors(context) {
88463           var osm = context.connection(),
88464               debouncedUpdate = debounce(function () {
88465             update();
88466           }, 1000),
88467               limit = 4,
88468               hidden = false,
88469               wrap = select(null);
88470
88471           function update() {
88472             if (!osm) return;
88473             var users = {},
88474                 entities = context.history().intersects(context.map().extent());
88475             entities.forEach(function (entity) {
88476               if (entity && entity.user) users[entity.user] = true;
88477             });
88478             var u = Object.keys(users),
88479                 subset = u.slice(0, u.length > limit ? limit - 1 : limit);
88480             wrap.html('').call(svgIcon('#iD-icon-nearby', 'pre-text light'));
88481             var userList = select(document.createElement('span'));
88482             userList.selectAll().data(subset).enter().append('a').attr('class', 'user-link').attr('href', function (d) {
88483               return osm.userURL(d);
88484             }).attr('target', '_blank').text(String);
88485
88486             if (u.length > limit) {
88487               var count = select(document.createElement('span'));
88488               var othersNum = u.length - limit + 1;
88489               count.append('a').attr('target', '_blank').attr('href', function () {
88490                 return osm.changesetsURL(context.map().center(), context.map().zoom());
88491               }).text(othersNum);
88492               wrap.append('span').html(_t.html('contributors.truncated_list', {
88493                 n: othersNum,
88494                 users: {
88495                   html: userList.html()
88496                 },
88497                 count: {
88498                   html: count.html()
88499                 }
88500               }));
88501             } else {
88502               wrap.append('span').html(_t.html('contributors.list', {
88503                 users: {
88504                   html: userList.html()
88505                 }
88506               }));
88507             }
88508
88509             if (!u.length) {
88510               hidden = true;
88511               wrap.transition().style('opacity', 0);
88512             } else if (hidden) {
88513               wrap.transition().style('opacity', 1);
88514             }
88515           }
88516
88517           return function (selection) {
88518             if (!osm) return;
88519             wrap = selection;
88520             update();
88521             osm.on('loaded.contributors', debouncedUpdate);
88522             context.map().on('move.contributors', debouncedUpdate);
88523           };
88524         }
88525
88526         var _popoverID = 0;
88527         function uiPopover(klass) {
88528           var _id = _popoverID++;
88529
88530           var _anchorSelection = select(null);
88531
88532           var popover = function popover(selection) {
88533             _anchorSelection = selection;
88534             selection.each(setup);
88535           };
88536
88537           var _animation = utilFunctor(false);
88538
88539           var _placement = utilFunctor('top'); // top, bottom, left, right
88540
88541
88542           var _alignment = utilFunctor('center'); // leading, center, trailing
88543
88544
88545           var _scrollContainer = utilFunctor(select(null));
88546
88547           var _content;
88548
88549           var _displayType = utilFunctor('');
88550
88551           var _hasArrow = utilFunctor(true); // use pointer events on supported platforms; fallback to mouse events
88552
88553
88554           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
88555
88556           popover.displayType = function (val) {
88557             if (arguments.length) {
88558               _displayType = utilFunctor(val);
88559               return popover;
88560             } else {
88561               return _displayType;
88562             }
88563           };
88564
88565           popover.hasArrow = function (val) {
88566             if (arguments.length) {
88567               _hasArrow = utilFunctor(val);
88568               return popover;
88569             } else {
88570               return _hasArrow;
88571             }
88572           };
88573
88574           popover.placement = function (val) {
88575             if (arguments.length) {
88576               _placement = utilFunctor(val);
88577               return popover;
88578             } else {
88579               return _placement;
88580             }
88581           };
88582
88583           popover.alignment = function (val) {
88584             if (arguments.length) {
88585               _alignment = utilFunctor(val);
88586               return popover;
88587             } else {
88588               return _alignment;
88589             }
88590           };
88591
88592           popover.scrollContainer = function (val) {
88593             if (arguments.length) {
88594               _scrollContainer = utilFunctor(val);
88595               return popover;
88596             } else {
88597               return _scrollContainer;
88598             }
88599           };
88600
88601           popover.content = function (val) {
88602             if (arguments.length) {
88603               _content = val;
88604               return popover;
88605             } else {
88606               return _content;
88607             }
88608           };
88609
88610           popover.isShown = function () {
88611             var popoverSelection = _anchorSelection.select('.popover-' + _id);
88612
88613             return !popoverSelection.empty() && popoverSelection.classed('in');
88614           };
88615
88616           popover.show = function () {
88617             _anchorSelection.each(show);
88618           };
88619
88620           popover.updateContent = function () {
88621             _anchorSelection.each(updateContent);
88622           };
88623
88624           popover.hide = function () {
88625             _anchorSelection.each(hide);
88626           };
88627
88628           popover.toggle = function () {
88629             _anchorSelection.each(toggle);
88630           };
88631
88632           popover.destroy = function (selection, selector) {
88633             // by default, just destroy the current popover
88634             selector = selector || '.popover-' + _id;
88635             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 () {
88636               return this.getAttribute('data-original-title') || this.getAttribute('title');
88637             }).attr('data-original-title', null).selectAll(selector).remove();
88638           };
88639
88640           popover.destroyAny = function (selection) {
88641             selection.call(popover.destroy, '.popover');
88642           };
88643
88644           function setup() {
88645             var anchor = select(this);
88646
88647             var animate = _animation.apply(this, arguments);
88648
88649             var popoverSelection = anchor.selectAll('.popover-' + _id).data([0]);
88650             var enter = popoverSelection.enter().append('div').attr('class', 'popover popover-' + _id + ' ' + (klass ? klass : '')).classed('arrowed', _hasArrow.apply(this, arguments));
88651             enter.append('div').attr('class', 'popover-arrow');
88652             enter.append('div').attr('class', 'popover-inner');
88653             popoverSelection = enter.merge(popoverSelection);
88654
88655             if (animate) {
88656               popoverSelection.classed('fade', true);
88657             }
88658
88659             var display = _displayType.apply(this, arguments);
88660
88661             if (display === 'hover') {
88662               var _lastNonMouseEnterTime;
88663
88664               anchor.on(_pointerPrefix + 'enter.popover', function (d3_event) {
88665                 if (d3_event.pointerType) {
88666                   if (d3_event.pointerType !== 'mouse') {
88667                     _lastNonMouseEnterTime = d3_event.timeStamp; // only allow hover behavior for mouse input
88668
88669                     return;
88670                   } else if (_lastNonMouseEnterTime && d3_event.timeStamp - _lastNonMouseEnterTime < 1500) {
88671                     // HACK: iOS 13.4 sends an erroneous `mouse` type pointerenter
88672                     // event for non-mouse interactions right after sending
88673                     // the correct type pointerenter event. Workaround by discarding
88674                     // any mouse event that occurs immediately after a non-mouse event.
88675                     return;
88676                   }
88677                 } // don't show if buttons are pressed, e.g. during click and drag of map
88678
88679
88680                 if (d3_event.buttons !== 0) return;
88681                 show.apply(this, arguments);
88682               }).on(_pointerPrefix + 'leave.popover', function () {
88683                 hide.apply(this, arguments);
88684               }) // show on focus too for better keyboard navigation support
88685               .on('focus.popover', function () {
88686                 show.apply(this, arguments);
88687               }).on('blur.popover', function () {
88688                 hide.apply(this, arguments);
88689               });
88690             } else if (display === 'clickFocus') {
88691               anchor.on(_pointerPrefix + 'down.popover', function (d3_event) {
88692                 d3_event.preventDefault();
88693                 d3_event.stopPropagation();
88694               }).on(_pointerPrefix + 'up.popover', function (d3_event) {
88695                 d3_event.preventDefault();
88696                 d3_event.stopPropagation();
88697               }).on('click.popover', toggle);
88698               popoverSelection // This attribute lets the popover take focus
88699               .attr('tabindex', 0).on('blur.popover', function () {
88700                 anchor.each(function () {
88701                   hide.apply(this, arguments);
88702                 });
88703               });
88704             }
88705           }
88706
88707           function show() {
88708             var anchor = select(this);
88709             var popoverSelection = anchor.selectAll('.popover-' + _id);
88710
88711             if (popoverSelection.empty()) {
88712               // popover was removed somehow, put it back
88713               anchor.call(popover.destroy);
88714               anchor.each(setup);
88715               popoverSelection = anchor.selectAll('.popover-' + _id);
88716             }
88717
88718             popoverSelection.classed('in', true);
88719
88720             var displayType = _displayType.apply(this, arguments);
88721
88722             if (displayType === 'clickFocus') {
88723               anchor.classed('active', true);
88724               popoverSelection.node().focus();
88725             }
88726
88727             anchor.each(updateContent);
88728           }
88729
88730           function updateContent() {
88731             var anchor = select(this);
88732
88733             if (_content) {
88734               anchor.selectAll('.popover-' + _id + ' > .popover-inner').call(_content.apply(this, arguments));
88735             }
88736
88737             updatePosition.apply(this, arguments); // hack: update multiple times to fix instances where the absolute offset is
88738             // set before the dynamic popover size is calculated by the browser
88739
88740             updatePosition.apply(this, arguments);
88741             updatePosition.apply(this, arguments);
88742           }
88743
88744           function updatePosition() {
88745             var anchor = select(this);
88746             var popoverSelection = anchor.selectAll('.popover-' + _id);
88747
88748             var scrollContainer = _scrollContainer && _scrollContainer.apply(this, arguments);
88749
88750             var scrollNode = scrollContainer && !scrollContainer.empty() && scrollContainer.node();
88751             var scrollLeft = scrollNode ? scrollNode.scrollLeft : 0;
88752             var scrollTop = scrollNode ? scrollNode.scrollTop : 0;
88753
88754             var placement = _placement.apply(this, arguments);
88755
88756             popoverSelection.classed('left', false).classed('right', false).classed('top', false).classed('bottom', false).classed(placement, true);
88757
88758             var alignment = _alignment.apply(this, arguments);
88759
88760             var alignFactor = 0.5;
88761
88762             if (alignment === 'leading') {
88763               alignFactor = 0;
88764             } else if (alignment === 'trailing') {
88765               alignFactor = 1;
88766             }
88767
88768             var anchorFrame = getFrame(anchor.node());
88769             var popoverFrame = getFrame(popoverSelection.node());
88770             var position;
88771
88772             switch (placement) {
88773               case 'top':
88774                 position = {
88775                   x: anchorFrame.x + (anchorFrame.w - popoverFrame.w) * alignFactor,
88776                   y: anchorFrame.y - popoverFrame.h
88777                 };
88778                 break;
88779
88780               case 'bottom':
88781                 position = {
88782                   x: anchorFrame.x + (anchorFrame.w - popoverFrame.w) * alignFactor,
88783                   y: anchorFrame.y + anchorFrame.h
88784                 };
88785                 break;
88786
88787               case 'left':
88788                 position = {
88789                   x: anchorFrame.x - popoverFrame.w,
88790                   y: anchorFrame.y + (anchorFrame.h - popoverFrame.h) * alignFactor
88791                 };
88792                 break;
88793
88794               case 'right':
88795                 position = {
88796                   x: anchorFrame.x + anchorFrame.w,
88797                   y: anchorFrame.y + (anchorFrame.h - popoverFrame.h) * alignFactor
88798                 };
88799                 break;
88800             }
88801
88802             if (position) {
88803               if (scrollNode && (placement === 'top' || placement === 'bottom')) {
88804                 var initialPosX = position.x;
88805
88806                 if (position.x + popoverFrame.w > scrollNode.offsetWidth - 10) {
88807                   position.x = scrollNode.offsetWidth - 10 - popoverFrame.w;
88808                 } else if (position.x < 10) {
88809                   position.x = 10;
88810                 }
88811
88812                 var arrow = anchor.selectAll('.popover-' + _id + ' > .popover-arrow'); // keep the arrow centered on the button, or as close as possible
88813
88814                 var arrowPosX = Math.min(Math.max(popoverFrame.w / 2 - (position.x - initialPosX), 10), popoverFrame.w - 10);
88815                 arrow.style('left', ~~arrowPosX + 'px');
88816               }
88817
88818               popoverSelection.style('left', ~~position.x + 'px').style('top', ~~position.y + 'px');
88819             } else {
88820               popoverSelection.style('left', null).style('top', null);
88821             }
88822
88823             function getFrame(node) {
88824               var positionStyle = select(node).style('position');
88825
88826               if (positionStyle === 'absolute' || positionStyle === 'static') {
88827                 return {
88828                   x: node.offsetLeft - scrollLeft,
88829                   y: node.offsetTop - scrollTop,
88830                   w: node.offsetWidth,
88831                   h: node.offsetHeight
88832                 };
88833               } else {
88834                 return {
88835                   x: 0,
88836                   y: 0,
88837                   w: node.offsetWidth,
88838                   h: node.offsetHeight
88839                 };
88840               }
88841             }
88842           }
88843
88844           function hide() {
88845             var anchor = select(this);
88846
88847             if (_displayType.apply(this, arguments) === 'clickFocus') {
88848               anchor.classed('active', false);
88849             }
88850
88851             anchor.selectAll('.popover-' + _id).classed('in', false);
88852           }
88853
88854           function toggle() {
88855             if (select(this).select('.popover-' + _id).classed('in')) {
88856               hide.apply(this, arguments);
88857             } else {
88858               show.apply(this, arguments);
88859             }
88860           }
88861
88862           return popover;
88863         }
88864
88865         function uiTooltip(klass) {
88866           var tooltip = uiPopover((klass || '') + ' tooltip').displayType('hover');
88867
88868           var _title = function _title() {
88869             var title = this.getAttribute('data-original-title');
88870
88871             if (title) {
88872               return title;
88873             } else {
88874               title = this.getAttribute('title');
88875               this.removeAttribute('title');
88876               this.setAttribute('data-original-title', title);
88877             }
88878
88879             return title;
88880           };
88881
88882           var _heading = utilFunctor(null);
88883
88884           var _keys = utilFunctor(null);
88885
88886           tooltip.title = function (val) {
88887             if (!arguments.length) return _title;
88888             _title = utilFunctor(val);
88889             return tooltip;
88890           };
88891
88892           tooltip.heading = function (val) {
88893             if (!arguments.length) return _heading;
88894             _heading = utilFunctor(val);
88895             return tooltip;
88896           };
88897
88898           tooltip.keys = function (val) {
88899             if (!arguments.length) return _keys;
88900             _keys = utilFunctor(val);
88901             return tooltip;
88902           };
88903
88904           tooltip.content(function () {
88905             var heading = _heading.apply(this, arguments);
88906
88907             var text = _title.apply(this, arguments);
88908
88909             var keys = _keys.apply(this, arguments);
88910
88911             return function (selection) {
88912               var headingSelect = selection.selectAll('.tooltip-heading').data(heading ? [heading] : []);
88913               headingSelect.exit().remove();
88914               headingSelect.enter().append('div').attr('class', 'tooltip-heading').merge(headingSelect).html(heading);
88915               var textSelect = selection.selectAll('.tooltip-text').data(text ? [text] : []);
88916               textSelect.exit().remove();
88917               textSelect.enter().append('div').attr('class', 'tooltip-text').merge(textSelect).html(text);
88918               var keyhintWrap = selection.selectAll('.keyhint-wrap').data(keys && keys.length ? [0] : []);
88919               keyhintWrap.exit().remove();
88920               var keyhintWrapEnter = keyhintWrap.enter().append('div').attr('class', 'keyhint-wrap');
88921               keyhintWrapEnter.append('span').call(_t.append('tooltip_keyhint'));
88922               keyhintWrap = keyhintWrapEnter.merge(keyhintWrap);
88923               keyhintWrap.selectAll('kbd.shortcut').data(keys && keys.length ? keys : []).enter().append('kbd').attr('class', 'shortcut').html(function (d) {
88924                 return d;
88925               });
88926             };
88927           });
88928           return tooltip;
88929         }
88930
88931         function uiEditMenu(context) {
88932           var dispatch = dispatch$8('toggled');
88933
88934           var _menu = select(null);
88935
88936           var _operations = []; // the position the menu should be displayed relative to
88937
88938           var _anchorLoc = [0, 0];
88939           var _anchorLocLonLat = [0, 0]; // a string indicating how the menu was opened
88940
88941           var _triggerType = '';
88942           var _vpTopMargin = 85; // viewport top margin
88943
88944           var _vpBottomMargin = 45; // viewport bottom margin
88945
88946           var _vpSideMargin = 35; // viewport side margin
88947
88948           var _menuTop = false;
88949
88950           var _menuHeight;
88951
88952           var _menuWidth; // hardcode these values to make menu positioning easier
88953
88954
88955           var _verticalPadding = 4; // see also `.edit-menu .tooltip` CSS; include margin
88956
88957           var _tooltipWidth = 210; // offset the menu slightly from the target location
88958
88959           var _menuSideMargin = 10;
88960           var _tooltips = [];
88961
88962           var editMenu = function editMenu(selection) {
88963             var isTouchMenu = _triggerType.includes('touch') || _triggerType.includes('pen');
88964
88965             var ops = _operations.filter(function (op) {
88966               return !isTouchMenu || !op.mouseOnly;
88967             });
88968
88969             if (!ops.length) return;
88970             _tooltips = []; // Position the menu above the anchor for stylus and finger input
88971             // since the mapper's hand likely obscures the screen below the anchor
88972
88973             _menuTop = isTouchMenu; // Show labels for touch input since there aren't hover tooltips
88974
88975             var showLabels = isTouchMenu;
88976             var buttonHeight = showLabels ? 32 : 34;
88977
88978             if (showLabels) {
88979               // Get a general idea of the width based on the length of the label
88980               _menuWidth = 52 + Math.min(120, 6 * Math.max.apply(Math, ops.map(function (op) {
88981                 return op.title.length;
88982               })));
88983             } else {
88984               _menuWidth = 44;
88985             }
88986
88987             _menuHeight = _verticalPadding * 2 + ops.length * buttonHeight;
88988             _menu = selection.append('div').attr('class', 'edit-menu').classed('touch-menu', isTouchMenu).style('padding', _verticalPadding + 'px 0');
88989
88990             var buttons = _menu.selectAll('.edit-menu-item').data(ops); // enter
88991
88992
88993             var buttonsEnter = buttons.enter().append('button').attr('class', function (d) {
88994               return 'edit-menu-item edit-menu-item-' + d.id;
88995             }).style('height', buttonHeight + 'px').on('click', click) // don't listen for `mouseup` because we only care about non-mouse pointer types
88996             .on('pointerup', pointerup).on('pointerdown mousedown', function pointerdown(d3_event) {
88997               // don't let button presses also act as map input - #1869
88998               d3_event.stopPropagation();
88999             }).on('mouseenter.highlight', function (d3_event, d) {
89000               if (!d.relatedEntityIds || select(this).classed('disabled')) return;
89001               utilHighlightEntities(d.relatedEntityIds(), true, context);
89002             }).on('mouseleave.highlight', function (d3_event, d) {
89003               if (!d.relatedEntityIds) return;
89004               utilHighlightEntities(d.relatedEntityIds(), false, context);
89005             });
89006             buttonsEnter.each(function (d) {
89007               var tooltip = uiTooltip().heading(d.title).title(d.tooltip()).keys([d.keys[0]]);
89008
89009               _tooltips.push(tooltip);
89010
89011               select(this).call(tooltip).append('div').attr('class', 'icon-wrap').call(svgIcon(d.icon && d.icon() || '#iD-operation-' + d.id, 'operation'));
89012             });
89013
89014             if (showLabels) {
89015               buttonsEnter.append('span').attr('class', 'label').html(function (d) {
89016                 return d.title;
89017               });
89018             } // update
89019
89020
89021             buttonsEnter.merge(buttons).classed('disabled', function (d) {
89022               return d.disabled();
89023             });
89024             updatePosition();
89025             var initialScale = context.projection.scale();
89026             context.map().on('move.edit-menu', function () {
89027               if (initialScale !== context.projection.scale()) {
89028                 editMenu.close();
89029               }
89030             }).on('drawn.edit-menu', function (info) {
89031               if (info.full) updatePosition();
89032             });
89033             var lastPointerUpType; // `pointerup` is always called before `click`
89034
89035             function pointerup(d3_event) {
89036               lastPointerUpType = d3_event.pointerType;
89037             }
89038
89039             function click(d3_event, operation) {
89040               d3_event.stopPropagation();
89041
89042               if (operation.relatedEntityIds) {
89043                 utilHighlightEntities(operation.relatedEntityIds(), false, context);
89044               }
89045
89046               if (operation.disabled()) {
89047                 if (lastPointerUpType === 'touch' || lastPointerUpType === 'pen') {
89048                   // there are no tooltips for touch interactions so flash feedback instead
89049                   context.ui().flash.duration(4000).iconName('#iD-operation-' + operation.id).iconClass('operation disabled').label(operation.tooltip)();
89050                 }
89051               } else {
89052                 if (lastPointerUpType === 'touch' || lastPointerUpType === 'pen') {
89053                   context.ui().flash.duration(2000).iconName('#iD-operation-' + operation.id).iconClass('operation').label(operation.annotation() || operation.title)();
89054                 }
89055
89056                 operation();
89057                 editMenu.close();
89058               }
89059
89060               lastPointerUpType = null;
89061             }
89062
89063             dispatch.call('toggled', this, true);
89064           };
89065
89066           function updatePosition() {
89067             if (!_menu || _menu.empty()) return;
89068             var anchorLoc = context.projection(_anchorLocLonLat);
89069             var viewport = context.surfaceRect();
89070
89071             if (anchorLoc[0] < 0 || anchorLoc[0] > viewport.width || anchorLoc[1] < 0 || anchorLoc[1] > viewport.height) {
89072               // close the menu if it's gone offscreen
89073               editMenu.close();
89074               return;
89075             }
89076
89077             var menuLeft = displayOnLeft(viewport);
89078             var offset = [0, 0];
89079             offset[0] = menuLeft ? -1 * (_menuSideMargin + _menuWidth) : _menuSideMargin;
89080
89081             if (_menuTop) {
89082               if (anchorLoc[1] - _menuHeight < _vpTopMargin) {
89083                 // menu is near top viewport edge, shift downward
89084                 offset[1] = -anchorLoc[1] + _vpTopMargin;
89085               } else {
89086                 offset[1] = -_menuHeight;
89087               }
89088             } else {
89089               if (anchorLoc[1] + _menuHeight > viewport.height - _vpBottomMargin) {
89090                 // menu is near bottom viewport edge, shift upwards
89091                 offset[1] = -anchorLoc[1] - _menuHeight + viewport.height - _vpBottomMargin;
89092               } else {
89093                 offset[1] = 0;
89094               }
89095             }
89096
89097             var origin = geoVecAdd(anchorLoc, offset);
89098
89099             _menu.style('left', origin[0] + 'px').style('top', origin[1] + 'px');
89100
89101             var tooltipSide = tooltipPosition(viewport, menuLeft);
89102
89103             _tooltips.forEach(function (tooltip) {
89104               tooltip.placement(tooltipSide);
89105             });
89106
89107             function displayOnLeft(viewport) {
89108               if (_mainLocalizer.textDirection() === 'ltr') {
89109                 if (anchorLoc[0] + _menuSideMargin + _menuWidth > viewport.width - _vpSideMargin) {
89110                   // right menu would be too close to the right viewport edge, go left
89111                   return true;
89112                 } // prefer right menu
89113
89114
89115                 return false;
89116               } else {
89117                 // rtl
89118                 if (anchorLoc[0] - _menuSideMargin - _menuWidth < _vpSideMargin) {
89119                   // left menu would be too close to the left viewport edge, go right
89120                   return false;
89121                 } // prefer left menu
89122
89123
89124                 return true;
89125               }
89126             }
89127
89128             function tooltipPosition(viewport, menuLeft) {
89129               if (_mainLocalizer.textDirection() === 'ltr') {
89130                 if (menuLeft) {
89131                   // if there's not room for a right-side menu then there definitely
89132                   // isn't room for right-side tooltips
89133                   return 'left';
89134                 }
89135
89136                 if (anchorLoc[0] + _menuSideMargin + _menuWidth + _tooltipWidth > viewport.width - _vpSideMargin) {
89137                   // right tooltips would be too close to the right viewport edge, go left
89138                   return 'left';
89139                 } // prefer right tooltips
89140
89141
89142                 return 'right';
89143               } else {
89144                 // rtl
89145                 if (!menuLeft) {
89146                   return 'right';
89147                 }
89148
89149                 if (anchorLoc[0] - _menuSideMargin - _menuWidth - _tooltipWidth < _vpSideMargin) {
89150                   // left tooltips would be too close to the left viewport edge, go right
89151                   return 'right';
89152                 } // prefer left tooltips
89153
89154
89155                 return 'left';
89156               }
89157             }
89158           }
89159
89160           editMenu.close = function () {
89161             context.map().on('move.edit-menu', null).on('drawn.edit-menu', null);
89162
89163             _menu.remove();
89164
89165             _tooltips = [];
89166             dispatch.call('toggled', this, false);
89167           };
89168
89169           editMenu.anchorLoc = function (val) {
89170             if (!arguments.length) return _anchorLoc;
89171             _anchorLoc = val;
89172             _anchorLocLonLat = context.projection.invert(_anchorLoc);
89173             return editMenu;
89174           };
89175
89176           editMenu.triggerType = function (val) {
89177             if (!arguments.length) return _triggerType;
89178             _triggerType = val;
89179             return editMenu;
89180           };
89181
89182           editMenu.operations = function (val) {
89183             if (!arguments.length) return _operations;
89184             _operations = val;
89185             return editMenu;
89186           };
89187
89188           return utilRebind(editMenu, dispatch, 'on');
89189         }
89190
89191         function uiFeatureInfo(context) {
89192           function update(selection) {
89193             var features = context.features();
89194             var stats = features.stats();
89195             var count = 0;
89196             var hiddenList = features.hidden().map(function (k) {
89197               if (stats[k]) {
89198                 count += stats[k];
89199                 return _t.html('inspector.title_count', {
89200                   title: {
89201                     html: _t.html('feature.' + k + '.description')
89202                   },
89203                   count: stats[k]
89204                 });
89205               }
89206
89207               return null;
89208             }).filter(Boolean);
89209             selection.html('');
89210
89211             if (hiddenList.length) {
89212               var tooltipBehavior = uiTooltip().placement('top').title(function () {
89213                 return hiddenList.join('<br/>');
89214               });
89215               selection.append('a').attr('class', 'chip').attr('href', '#').call(_t.append('feature_info.hidden_warning', {
89216                 count: count
89217               })).call(tooltipBehavior).on('click', function (d3_event) {
89218                 tooltipBehavior.hide();
89219                 d3_event.preventDefault(); // open the Map Data pane
89220
89221                 context.ui().togglePanes(context.container().select('.map-panes .map-data-pane'));
89222               });
89223             }
89224
89225             selection.classed('hide', !hiddenList.length);
89226           }
89227
89228           return function (selection) {
89229             update(selection);
89230             context.features().on('change.feature_info', function () {
89231               update(selection);
89232             });
89233           };
89234         }
89235
89236         function uiFlash(context) {
89237           var _flashTimer;
89238
89239           var _duration = 2000;
89240           var _iconName = '#iD-icon-no';
89241           var _iconClass = 'disabled';
89242           var _label = '';
89243
89244           function flash() {
89245             if (_flashTimer) {
89246               _flashTimer.stop();
89247             }
89248
89249             context.container().select('.main-footer-wrap').classed('footer-hide', true).classed('footer-show', false);
89250             context.container().select('.flash-wrap').classed('footer-hide', false).classed('footer-show', true);
89251             var content = context.container().select('.flash-wrap').selectAll('.flash-content').data([0]); // Enter
89252
89253             var contentEnter = content.enter().append('div').attr('class', 'flash-content');
89254             var iconEnter = contentEnter.append('svg').attr('class', 'flash-icon icon').append('g').attr('transform', 'translate(10,10)');
89255             iconEnter.append('circle').attr('r', 9);
89256             iconEnter.append('use').attr('transform', 'translate(-7,-7)').attr('width', '14').attr('height', '14');
89257             contentEnter.append('div').attr('class', 'flash-text'); // Update
89258
89259             content = content.merge(contentEnter);
89260             content.selectAll('.flash-icon').attr('class', 'icon flash-icon ' + (_iconClass || ''));
89261             content.selectAll('.flash-icon use').attr('xlink:href', _iconName);
89262             content.selectAll('.flash-text').attr('class', 'flash-text').html(_label);
89263             _flashTimer = d3_timeout(function () {
89264               _flashTimer = null;
89265               context.container().select('.main-footer-wrap').classed('footer-hide', false).classed('footer-show', true);
89266               context.container().select('.flash-wrap').classed('footer-hide', true).classed('footer-show', false);
89267             }, _duration);
89268             return content;
89269           }
89270
89271           flash.duration = function (_) {
89272             if (!arguments.length) return _duration;
89273             _duration = _;
89274             return flash;
89275           };
89276
89277           flash.label = function (_) {
89278             if (!arguments.length) return _label;
89279             _label = _;
89280             return flash;
89281           };
89282
89283           flash.iconName = function (_) {
89284             if (!arguments.length) return _iconName;
89285             _iconName = _;
89286             return flash;
89287           };
89288
89289           flash.iconClass = function (_) {
89290             if (!arguments.length) return _iconClass;
89291             _iconClass = _;
89292             return flash;
89293           };
89294
89295           return flash;
89296         }
89297
89298         function uiFullScreen(context) {
89299           var element = context.container().node(); // var button = d3_select(null);
89300
89301           function getFullScreenFn() {
89302             if (element.requestFullscreen) {
89303               return element.requestFullscreen;
89304             } else if (element.msRequestFullscreen) {
89305               return element.msRequestFullscreen;
89306             } else if (element.mozRequestFullScreen) {
89307               return element.mozRequestFullScreen;
89308             } else if (element.webkitRequestFullscreen) {
89309               return element.webkitRequestFullscreen;
89310             }
89311           }
89312
89313           function getExitFullScreenFn() {
89314             if (document.exitFullscreen) {
89315               return document.exitFullscreen;
89316             } else if (document.msExitFullscreen) {
89317               return document.msExitFullscreen;
89318             } else if (document.mozCancelFullScreen) {
89319               return document.mozCancelFullScreen;
89320             } else if (document.webkitExitFullscreen) {
89321               return document.webkitExitFullscreen;
89322             }
89323           }
89324
89325           function isFullScreen() {
89326             return document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement;
89327           }
89328
89329           function isSupported() {
89330             return !!getFullScreenFn();
89331           }
89332
89333           function fullScreen(d3_event) {
89334             d3_event.preventDefault();
89335
89336             if (!isFullScreen()) {
89337               // button.classed('active', true);
89338               getFullScreenFn().apply(element);
89339             } else {
89340               // button.classed('active', false);
89341               getExitFullScreenFn().apply(document);
89342             }
89343           }
89344
89345           return function () {
89346             // selection) {
89347             if (!isSupported()) return; // button = selection.append('button')
89348             //     .attr('title', t('full_screen'))
89349             //     .on('click', fullScreen)
89350             //     .call(tooltip);
89351             // button.append('span')
89352             //     .attr('class', 'icon full-screen');
89353
89354             var detected = utilDetect();
89355             var keys = detected.os === 'mac' ? [uiCmd('⌃⌘F'), 'f11'] : ['f11'];
89356             context.keybinding().on(keys, fullScreen);
89357           };
89358         }
89359
89360         function uiGeolocate(context) {
89361           var _geolocationOptions = {
89362             // prioritize speed and power usage over precision
89363             enableHighAccuracy: false,
89364             // don't hang indefinitely getting the location
89365             timeout: 6000 // 6sec
89366
89367           };
89368
89369           var _locating = uiLoading(context).message(_t.html('geolocate.locating')).blocking(true);
89370
89371           var _layer = context.layers().layer('geolocate');
89372
89373           var _position;
89374
89375           var _extent;
89376
89377           var _timeoutID;
89378
89379           var _button = select(null);
89380
89381           function click() {
89382             if (context.inIntro()) return;
89383
89384             if (!_layer.enabled() && !_locating.isShown()) {
89385               // This timeout ensures that we still call finish() even if
89386               // the user declines to share their location in Firefox
89387               _timeoutID = setTimeout(error, 10000
89388               /* 10sec */
89389               );
89390               context.container().call(_locating); // get the latest position even if we already have one
89391
89392               navigator.geolocation.getCurrentPosition(success, error, _geolocationOptions);
89393             } else {
89394               _locating.close();
89395
89396               _layer.enabled(null, false);
89397
89398               updateButtonState();
89399             }
89400           }
89401
89402           function zoomTo() {
89403             context.enter(modeBrowse(context));
89404             var map = context.map();
89405
89406             _layer.enabled(_position, true);
89407
89408             updateButtonState();
89409             map.centerZoomEase(_extent.center(), Math.min(20, map.extentZoom(_extent)));
89410           }
89411
89412           function success(geolocation) {
89413             _position = geolocation;
89414             var coords = _position.coords;
89415             _extent = geoExtent([coords.longitude, coords.latitude]).padByMeters(coords.accuracy);
89416             zoomTo();
89417             finish();
89418           }
89419
89420           function error() {
89421             if (_position) {
89422               // use the position from a previous call if we have one
89423               zoomTo();
89424             } else {
89425               context.ui().flash.label(_t.html('geolocate.location_unavailable')).iconName('#iD-icon-geolocate')();
89426             }
89427
89428             finish();
89429           }
89430
89431           function finish() {
89432             _locating.close(); // unblock ui
89433
89434
89435             if (_timeoutID) {
89436               clearTimeout(_timeoutID);
89437             }
89438
89439             _timeoutID = undefined;
89440           }
89441
89442           function updateButtonState() {
89443             _button.classed('active', _layer.enabled());
89444
89445             _button.attr('aria-pressed', _layer.enabled());
89446           }
89447
89448           return function (selection) {
89449             if (!navigator.geolocation || !navigator.geolocation.getCurrentPosition) return;
89450             _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')]));
89451             context.keybinding().on(_t('geolocate.key'), click);
89452           };
89453         }
89454
89455         function uiPanelBackground(context) {
89456           var background = context.background();
89457           var _currSourceName = null;
89458           var _metadata = {};
89459           var _metadataKeys = ['zoom', 'vintage', 'source', 'description', 'resolution', 'accuracy'];
89460
89461           var debouncedRedraw = debounce(redraw, 250);
89462
89463           function redraw(selection) {
89464             var source = background.baseLayerSource();
89465             if (!source) return;
89466             var isDG = source.id.match(/^DigitalGlobe/i) !== null;
89467             var sourceLabel = source.label();
89468
89469             if (_currSourceName !== sourceLabel) {
89470               _currSourceName = sourceLabel;
89471               _metadata = {};
89472             }
89473
89474             selection.html('');
89475             var list = selection.append('ul').attr('class', 'background-info');
89476             list.append('li').html(_currSourceName);
89477
89478             _metadataKeys.forEach(function (k) {
89479               // DigitalGlobe vintage is available in raster layers for now.
89480               if (isDG && k === 'vintage') return;
89481               list.append('li').attr('class', 'background-info-list-' + k).classed('hide', !_metadata[k]).call(_t.append('info_panels.background.' + k, {
89482                 suffix: ':'
89483               })).append('span').attr('class', 'background-info-span-' + k).text(_metadata[k]);
89484             });
89485
89486             debouncedGetMetadata(selection);
89487             var toggleTiles = context.getDebug('tile') ? 'hide_tiles' : 'show_tiles';
89488             selection.append('a').call(_t.append('info_panels.background.' + toggleTiles)).attr('href', '#').attr('class', 'button button-toggle-tiles').on('click', function (d3_event) {
89489               d3_event.preventDefault();
89490               context.setDebug('tile', !context.getDebug('tile'));
89491               selection.call(redraw);
89492             });
89493
89494             if (isDG) {
89495               var key = source.id + '-vintage';
89496               var sourceVintage = context.background().findSource(key);
89497               var showsVintage = context.background().showsLayer(sourceVintage);
89498               var toggleVintage = showsVintage ? 'hide_vintage' : 'show_vintage';
89499               selection.append('a').call(_t.append('info_panels.background.' + toggleVintage)).attr('href', '#').attr('class', 'button button-toggle-vintage').on('click', function (d3_event) {
89500                 d3_event.preventDefault();
89501                 context.background().toggleOverlayLayer(sourceVintage);
89502                 selection.call(redraw);
89503               });
89504             } // disable if necessary
89505
89506
89507             ['DigitalGlobe-Premium', 'DigitalGlobe-Standard'].forEach(function (layerId) {
89508               if (source.id !== layerId) {
89509                 var key = layerId + '-vintage';
89510                 var sourceVintage = context.background().findSource(key);
89511
89512                 if (context.background().showsLayer(sourceVintage)) {
89513                   context.background().toggleOverlayLayer(sourceVintage);
89514                 }
89515               }
89516             });
89517           }
89518
89519           var debouncedGetMetadata = debounce(getMetadata, 250);
89520
89521           function getMetadata(selection) {
89522             var tile = context.container().select('.layer-background img.tile-center'); // tile near viewport center
89523
89524             if (tile.empty()) return;
89525             var sourceName = _currSourceName;
89526             var d = tile.datum();
89527             var zoom = d && d.length >= 3 && d[2] || Math.floor(context.map().zoom());
89528             var center = context.map().center(); // update zoom
89529
89530             _metadata.zoom = String(zoom);
89531             selection.selectAll('.background-info-list-zoom').classed('hide', false).selectAll('.background-info-span-zoom').text(_metadata.zoom);
89532             if (!d || !d.length >= 3) return;
89533             background.baseLayerSource().getMetadata(center, d, function (err, result) {
89534               if (err || _currSourceName !== sourceName) return; // update vintage
89535
89536               var vintage = result.vintage;
89537               _metadata.vintage = vintage && vintage.range || _t('info_panels.background.unknown');
89538               selection.selectAll('.background-info-list-vintage').classed('hide', false).selectAll('.background-info-span-vintage').text(_metadata.vintage); // update other _metadata
89539
89540               _metadataKeys.forEach(function (k) {
89541                 if (k === 'zoom' || k === 'vintage') return; // done already
89542
89543                 var val = result[k];
89544                 _metadata[k] = val;
89545                 selection.selectAll('.background-info-list-' + k).classed('hide', !val).selectAll('.background-info-span-' + k).text(val);
89546               });
89547             });
89548           }
89549
89550           var panel = function panel(selection) {
89551             selection.call(redraw);
89552             context.map().on('drawn.info-background', function () {
89553               selection.call(debouncedRedraw);
89554             }).on('move.info-background', function () {
89555               selection.call(debouncedGetMetadata);
89556             });
89557           };
89558
89559           panel.off = function () {
89560             context.map().on('drawn.info-background', null).on('move.info-background', null);
89561           };
89562
89563           panel.id = 'background';
89564           panel.label = _t.html('info_panels.background.title');
89565           panel.key = _t('info_panels.background.key');
89566           return panel;
89567         }
89568
89569         function uiPanelHistory(context) {
89570           var osm;
89571
89572           function displayTimestamp(timestamp) {
89573             if (!timestamp) return _t('info_panels.history.unknown');
89574             var options = {
89575               day: 'numeric',
89576               month: 'short',
89577               year: 'numeric',
89578               hour: 'numeric',
89579               minute: 'numeric',
89580               second: 'numeric'
89581             };
89582             var d = new Date(timestamp);
89583             if (isNaN(d.getTime())) return _t('info_panels.history.unknown');
89584             return d.toLocaleString(_mainLocalizer.localeCode(), options);
89585           }
89586
89587           function displayUser(selection, userName) {
89588             if (!userName) {
89589               selection.append('span').call(_t.append('info_panels.history.unknown'));
89590               return;
89591             }
89592
89593             selection.append('span').attr('class', 'user-name').text(userName);
89594             var links = selection.append('div').attr('class', 'links');
89595
89596             if (osm) {
89597               links.append('a').attr('class', 'user-osm-link').attr('href', osm.userURL(userName)).attr('target', '_blank').call(_t.append('info_panels.history.profile_link'));
89598             }
89599
89600             links.append('a').attr('class', 'user-hdyc-link').attr('href', 'https://hdyc.neis-one.org/?' + userName).attr('target', '_blank').attr('tabindex', -1).text('HDYC');
89601           }
89602
89603           function displayChangeset(selection, changeset) {
89604             if (!changeset) {
89605               selection.append('span').call(_t.append('info_panels.history.unknown'));
89606               return;
89607             }
89608
89609             selection.append('span').attr('class', 'changeset-id').text(changeset);
89610             var links = selection.append('div').attr('class', 'links');
89611
89612             if (osm) {
89613               links.append('a').attr('class', 'changeset-osm-link').attr('href', osm.changesetURL(changeset)).attr('target', '_blank').call(_t.append('info_panels.history.changeset_link'));
89614             }
89615
89616             links.append('a').attr('class', 'changeset-osmcha-link').attr('href', 'https://osmcha.org/changesets/' + changeset).attr('target', '_blank').text('OSMCha');
89617             links.append('a').attr('class', 'changeset-achavi-link').attr('href', 'https://overpass-api.de/achavi/?changeset=' + changeset).attr('target', '_blank').text('Achavi');
89618           }
89619
89620           function redraw(selection) {
89621             var selectedNoteID = context.selectedNoteID();
89622             osm = context.connection();
89623             var selected, note, entity;
89624
89625             if (selectedNoteID && osm) {
89626               // selected 1 note
89627               selected = [_t.html('note.note') + ' ' + selectedNoteID];
89628               note = osm.getNote(selectedNoteID);
89629             } else {
89630               // selected 1..n entities
89631               selected = context.selectedIDs().filter(function (e) {
89632                 return context.hasEntity(e);
89633               });
89634
89635               if (selected.length) {
89636                 entity = context.entity(selected[0]);
89637               }
89638             }
89639
89640             var singular = selected.length === 1 ? selected[0] : null;
89641             selection.html('');
89642
89643             if (singular) {
89644               selection.append('h4').attr('class', 'history-heading').html(singular);
89645             } else {
89646               selection.append('h4').attr('class', 'history-heading').call(_t.append('info_panels.selected', {
89647                 n: selected.length
89648               }));
89649             }
89650
89651             if (!singular) return;
89652
89653             if (entity) {
89654               selection.call(redrawEntity, entity);
89655             } else if (note) {
89656               selection.call(redrawNote, note);
89657             }
89658           }
89659
89660           function redrawNote(selection, note) {
89661             if (!note || note.isNew()) {
89662               selection.append('div').call(_t.append('info_panels.history.note_no_history'));
89663               return;
89664             }
89665
89666             var list = selection.append('ul');
89667             list.append('li').call(_t.append('info_panels.history.note_comments', {
89668               suffix: ':'
89669             })).append('span').text(note.comments.length);
89670
89671             if (note.comments.length) {
89672               list.append('li').call(_t.append('info_panels.history.note_created_date', {
89673                 suffix: ':'
89674               })).append('span').text(displayTimestamp(note.comments[0].date));
89675               list.append('li').call(_t.append('info_panels.history.note_created_user', {
89676                 suffix: ':'
89677               })).call(displayUser, note.comments[0].user);
89678             }
89679
89680             if (osm) {
89681               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'));
89682             }
89683           }
89684
89685           function redrawEntity(selection, entity) {
89686             if (!entity || entity.isNew()) {
89687               selection.append('div').call(_t.append('info_panels.history.no_history'));
89688               return;
89689             }
89690
89691             var links = selection.append('div').attr('class', 'links');
89692
89693             if (osm) {
89694               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'));
89695             }
89696
89697             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');
89698             var list = selection.append('ul');
89699             list.append('li').call(_t.append('info_panels.history.version', {
89700               suffix: ':'
89701             })).append('span').text(entity.version);
89702             list.append('li').call(_t.append('info_panels.history.last_edit', {
89703               suffix: ':'
89704             })).append('span').text(displayTimestamp(entity.timestamp));
89705             list.append('li').call(_t.append('info_panels.history.edited_by', {
89706               suffix: ':'
89707             })).call(displayUser, entity.user);
89708             list.append('li').call(_t.append('info_panels.history.changeset', {
89709               suffix: ':'
89710             })).call(displayChangeset, entity.changeset);
89711           }
89712
89713           var panel = function panel(selection) {
89714             selection.call(redraw);
89715             context.map().on('drawn.info-history', function () {
89716               selection.call(redraw);
89717             });
89718             context.on('enter.info-history', function () {
89719               selection.call(redraw);
89720             });
89721           };
89722
89723           panel.off = function () {
89724             context.map().on('drawn.info-history', null);
89725             context.on('enter.info-history', null);
89726           };
89727
89728           panel.id = 'history';
89729           panel.label = _t.html('info_panels.history.title');
89730           panel.key = _t('info_panels.history.key');
89731           return panel;
89732         }
89733
89734         var OSM_PRECISION = 7;
89735         /**
89736          * Returns a localized representation of the given length measurement.
89737          *
89738          * @param {Number} m area in meters
89739          * @param {Boolean} isImperial true for U.S. customary units; false for metric
89740          */
89741
89742         function displayLength(m, isImperial) {
89743           var d = m * (isImperial ? 3.28084 : 1);
89744           var unit;
89745
89746           if (isImperial) {
89747             if (d >= 5280) {
89748               d /= 5280;
89749               unit = 'miles';
89750             } else {
89751               unit = 'feet';
89752             }
89753           } else {
89754             if (d >= 1000) {
89755               d /= 1000;
89756               unit = 'kilometers';
89757             } else {
89758               unit = 'meters';
89759             }
89760           }
89761
89762           return _t('units.' + unit, {
89763             quantity: d.toLocaleString(_mainLocalizer.localeCode(), {
89764               maximumSignificantDigits: 4
89765             })
89766           });
89767         }
89768         /**
89769          * Returns a localized representation of the given area measurement.
89770          *
89771          * @param {Number} m2 area in square meters
89772          * @param {Boolean} isImperial true for U.S. customary units; false for metric
89773          */
89774
89775         function displayArea(m2, isImperial) {
89776           var locale = _mainLocalizer.localeCode();
89777           var d = m2 * (isImperial ? 10.7639111056 : 1);
89778           var d1, d2, area;
89779           var unit1 = '';
89780           var unit2 = '';
89781
89782           if (isImperial) {
89783             if (d >= 6969600) {
89784               // > 0.25mi² show mi²
89785               d1 = d / 27878400;
89786               unit1 = 'square_miles';
89787             } else {
89788               d1 = d;
89789               unit1 = 'square_feet';
89790             }
89791
89792             if (d > 4356 && d < 43560000) {
89793               // 0.1 - 1000 acres
89794               d2 = d / 43560;
89795               unit2 = 'acres';
89796             }
89797           } else {
89798             if (d >= 250000) {
89799               // > 0.25km² show km²
89800               d1 = d / 1000000;
89801               unit1 = 'square_kilometers';
89802             } else {
89803               d1 = d;
89804               unit1 = 'square_meters';
89805             }
89806
89807             if (d > 1000 && d < 10000000) {
89808               // 0.1 - 1000 hectares
89809               d2 = d / 10000;
89810               unit2 = 'hectares';
89811             }
89812           }
89813
89814           area = _t('units.' + unit1, {
89815             quantity: d1.toLocaleString(locale, {
89816               maximumSignificantDigits: 4
89817             })
89818           });
89819
89820           if (d2) {
89821             return _t('units.area_pair', {
89822               area1: area,
89823               area2: _t('units.' + unit2, {
89824                 quantity: d2.toLocaleString(locale, {
89825                   maximumSignificantDigits: 2
89826                 })
89827               })
89828             });
89829           } else {
89830             return area;
89831           }
89832         }
89833
89834         function wrap(x, min, max) {
89835           var d = max - min;
89836           return ((x - min) % d + d) % d + min;
89837         }
89838
89839         function clamp(x, min, max) {
89840           return Math.max(min, Math.min(x, max));
89841         }
89842
89843         function displayCoordinate(deg, pos, neg) {
89844           var locale = _mainLocalizer.localeCode();
89845           var min = (Math.abs(deg) - Math.floor(Math.abs(deg))) * 60;
89846           var sec = (min - Math.floor(min)) * 60;
89847           var displayDegrees = _t('units.arcdegrees', {
89848             quantity: Math.floor(Math.abs(deg)).toLocaleString(locale)
89849           });
89850           var displayCoordinate;
89851
89852           if (Math.floor(sec) > 0) {
89853             displayCoordinate = displayDegrees + _t('units.arcminutes', {
89854               quantity: Math.floor(min).toLocaleString(locale)
89855             }) + _t('units.arcseconds', {
89856               quantity: Math.round(sec).toLocaleString(locale)
89857             });
89858           } else if (Math.floor(min) > 0) {
89859             displayCoordinate = displayDegrees + _t('units.arcminutes', {
89860               quantity: Math.round(min).toLocaleString(locale)
89861             });
89862           } else {
89863             displayCoordinate = _t('units.arcdegrees', {
89864               quantity: Math.round(Math.abs(deg)).toLocaleString(locale)
89865             });
89866           }
89867
89868           if (deg === 0) {
89869             return displayCoordinate;
89870           } else {
89871             return _t('units.coordinate', {
89872               coordinate: displayCoordinate,
89873               direction: _t('units.' + (deg > 0 ? pos : neg))
89874             });
89875           }
89876         }
89877         /**
89878          * Returns given coordinate pair in degree-minute-second format.
89879          *
89880          * @param {Array<Number>} coord longitude and latitude
89881          */
89882
89883
89884         function dmsCoordinatePair(coord) {
89885           return _t('units.coordinate_pair', {
89886             latitude: displayCoordinate(clamp(coord[1], -90, 90), 'north', 'south'),
89887             longitude: displayCoordinate(wrap(coord[0], -180, 180), 'east', 'west')
89888           });
89889         }
89890         /**
89891          * Returns the given coordinate pair in decimal format.
89892          * note: unlocalized to avoid comma ambiguity - see #4765
89893          *
89894          * @param {Array<Number>} coord longitude and latitude
89895          */
89896
89897         function decimalCoordinatePair(coord) {
89898           return _t('units.coordinate_pair', {
89899             latitude: clamp(coord[1], -90, 90).toFixed(OSM_PRECISION),
89900             longitude: wrap(coord[0], -180, 180).toFixed(OSM_PRECISION)
89901           });
89902         }
89903
89904         function uiPanelLocation(context) {
89905           var currLocation = '';
89906
89907           function redraw(selection) {
89908             selection.html('');
89909             var list = selection.append('ul'); // Mouse coordinates
89910
89911             var coord = context.map().mouseCoordinates();
89912
89913             if (coord.some(isNaN)) {
89914               coord = context.map().center();
89915             }
89916
89917             list.append('li').text(dmsCoordinatePair(coord)).append('li').text(decimalCoordinatePair(coord)); // Location Info
89918
89919             selection.append('div').attr('class', 'location-info').text(currLocation || ' ');
89920             debouncedGetLocation(selection, coord);
89921           }
89922
89923           var debouncedGetLocation = debounce(getLocation, 250);
89924
89925           function getLocation(selection, coord) {
89926             if (!services.geocoder) {
89927               currLocation = _t('info_panels.location.unknown_location');
89928               selection.selectAll('.location-info').text(currLocation);
89929             } else {
89930               services.geocoder.reverse(coord, function (err, result) {
89931                 currLocation = result ? result.display_name : _t('info_panels.location.unknown_location');
89932                 selection.selectAll('.location-info').text(currLocation);
89933               });
89934             }
89935           }
89936
89937           var panel = function panel(selection) {
89938             selection.call(redraw);
89939             context.surface().on(('PointerEvent' in window ? 'pointer' : 'mouse') + 'move.info-location', function () {
89940               selection.call(redraw);
89941             });
89942           };
89943
89944           panel.off = function () {
89945             context.surface().on('.info-location', null);
89946           };
89947
89948           panel.id = 'location';
89949           panel.label = _t.html('info_panels.location.title');
89950           panel.key = _t('info_panels.location.key');
89951           return panel;
89952         }
89953
89954         function uiPanelMeasurement(context) {
89955           function radiansToMeters(r) {
89956             // using WGS84 authalic radius (6371007.1809 m)
89957             return r * 6371007.1809;
89958           }
89959
89960           function steradiansToSqmeters(r) {
89961             // http://gis.stackexchange.com/a/124857/40446
89962             return r / (4 * Math.PI) * 510065621724000;
89963           }
89964
89965           function toLineString(feature) {
89966             if (feature.type === 'LineString') return feature;
89967             var result = {
89968               type: 'LineString',
89969               coordinates: []
89970             };
89971
89972             if (feature.type === 'Polygon') {
89973               result.coordinates = feature.coordinates[0];
89974             } else if (feature.type === 'MultiPolygon') {
89975               result.coordinates = feature.coordinates[0][0];
89976             }
89977
89978             return result;
89979           }
89980
89981           var _isImperial = !_mainLocalizer.usesMetric();
89982
89983           function redraw(selection) {
89984             var graph = context.graph();
89985             var selectedNoteID = context.selectedNoteID();
89986             var osm = services.osm;
89987             var localeCode = _mainLocalizer.localeCode();
89988             var heading;
89989             var center, location, centroid;
89990             var closed, geometry;
89991             var totalNodeCount,
89992                 length = 0,
89993                 area = 0,
89994                 distance;
89995
89996             if (selectedNoteID && osm) {
89997               // selected 1 note
89998               var note = osm.getNote(selectedNoteID);
89999               heading = _t.html('note.note') + ' ' + selectedNoteID;
90000               location = note.loc;
90001               geometry = 'note';
90002             } else {
90003               // selected 1..n entities
90004               var selectedIDs = context.selectedIDs().filter(function (id) {
90005                 return context.hasEntity(id);
90006               });
90007               var selected = selectedIDs.map(function (id) {
90008                 return context.entity(id);
90009               });
90010               heading = selected.length === 1 ? selected[0].id : _t.html('info_panels.selected', {
90011                 n: selected.length
90012               });
90013
90014               if (selected.length) {
90015                 var extent = geoExtent();
90016
90017                 for (var i in selected) {
90018                   var entity = selected[i];
90019
90020                   extent._extend(entity.extent(graph));
90021
90022                   geometry = entity.geometry(graph);
90023
90024                   if (geometry === 'line' || geometry === 'area') {
90025                     closed = entity.type === 'relation' || entity.isClosed() && !entity.isDegenerate();
90026                     var feature = entity.asGeoJSON(graph);
90027                     length += radiansToMeters(d3_geoLength(toLineString(feature)));
90028                     centroid = d3_geoPath(context.projection).centroid(entity.asGeoJSON(graph));
90029                     centroid = centroid && context.projection.invert(centroid);
90030
90031                     if (!centroid || !isFinite(centroid[0]) || !isFinite(centroid[1])) {
90032                       centroid = entity.extent(graph).center();
90033                     }
90034
90035                     if (closed) {
90036                       area += steradiansToSqmeters(entity.area(graph));
90037                     }
90038                   }
90039                 }
90040
90041                 if (selected.length > 1) {
90042                   geometry = null;
90043                   closed = null;
90044                   centroid = null;
90045                 }
90046
90047                 if (selected.length === 2 && selected[0].type === 'node' && selected[1].type === 'node') {
90048                   distance = geoSphericalDistance(selected[0].loc, selected[1].loc);
90049                 }
90050
90051                 if (selected.length === 1 && selected[0].type === 'node') {
90052                   location = selected[0].loc;
90053                 } else {
90054                   totalNodeCount = utilGetAllNodes(selectedIDs, context.graph()).length;
90055                 }
90056
90057                 if (!location && !centroid) {
90058                   center = extent.center();
90059                 }
90060               }
90061             }
90062
90063             selection.html('');
90064
90065             if (heading) {
90066               selection.append('h4').attr('class', 'measurement-heading').html(heading);
90067             }
90068
90069             var list = selection.append('ul');
90070             var coordItem;
90071
90072             if (geometry) {
90073               list.append('li').call(_t.append('info_panels.measurement.geometry', {
90074                 suffix: ':'
90075               })).append('span').html(closed ? _t.html('info_panels.measurement.closed_' + geometry) : _t.html('geometry.' + geometry));
90076             }
90077
90078             if (totalNodeCount) {
90079               list.append('li').call(_t.append('info_panels.measurement.node_count', {
90080                 suffix: ':'
90081               })).append('span').text(totalNodeCount.toLocaleString(localeCode));
90082             }
90083
90084             if (area) {
90085               list.append('li').call(_t.append('info_panels.measurement.area', {
90086                 suffix: ':'
90087               })).append('span').text(displayArea(area, _isImperial));
90088             }
90089
90090             if (length) {
90091               list.append('li').call(_t.append('info_panels.measurement.' + (closed ? 'perimeter' : 'length'), {
90092                 suffix: ':'
90093               })).append('span').text(displayLength(length, _isImperial));
90094             }
90095
90096             if (typeof distance === 'number') {
90097               list.append('li').call(_t.append('info_panels.measurement.distance', {
90098                 suffix: ':'
90099               })).append('span').text(displayLength(distance, _isImperial));
90100             }
90101
90102             if (location) {
90103               coordItem = list.append('li').call(_t.append('info_panels.measurement.location', {
90104                 suffix: ':'
90105               }));
90106               coordItem.append('span').text(dmsCoordinatePair(location));
90107               coordItem.append('span').text(decimalCoordinatePair(location));
90108             }
90109
90110             if (centroid) {
90111               coordItem = list.append('li').call(_t.append('info_panels.measurement.centroid', {
90112                 suffix: ':'
90113               }));
90114               coordItem.append('span').text(dmsCoordinatePair(centroid));
90115               coordItem.append('span').text(decimalCoordinatePair(centroid));
90116             }
90117
90118             if (center) {
90119               coordItem = list.append('li').call(_t.append('info_panels.measurement.center', {
90120                 suffix: ':'
90121               }));
90122               coordItem.append('span').text(dmsCoordinatePair(center));
90123               coordItem.append('span').text(decimalCoordinatePair(center));
90124             }
90125
90126             if (length || area || typeof distance === 'number') {
90127               var toggle = _isImperial ? 'imperial' : 'metric';
90128               selection.append('a').call(_t.append('info_panels.measurement.' + toggle)).attr('href', '#').attr('class', 'button button-toggle-units').on('click', function (d3_event) {
90129                 d3_event.preventDefault();
90130                 _isImperial = !_isImperial;
90131                 selection.call(redraw);
90132               });
90133             }
90134           }
90135
90136           var panel = function panel(selection) {
90137             selection.call(redraw);
90138             context.map().on('drawn.info-measurement', function () {
90139               selection.call(redraw);
90140             });
90141             context.on('enter.info-measurement', function () {
90142               selection.call(redraw);
90143             });
90144           };
90145
90146           panel.off = function () {
90147             context.map().on('drawn.info-measurement', null);
90148             context.on('enter.info-measurement', null);
90149           };
90150
90151           panel.id = 'measurement';
90152           panel.label = _t.html('info_panels.measurement.title');
90153           panel.key = _t('info_panels.measurement.key');
90154           return panel;
90155         }
90156
90157         var uiInfoPanels = {
90158           background: uiPanelBackground,
90159           history: uiPanelHistory,
90160           location: uiPanelLocation,
90161           measurement: uiPanelMeasurement
90162         };
90163
90164         function uiInfo(context) {
90165           var ids = Object.keys(uiInfoPanels);
90166           var wasActive = ['measurement'];
90167           var panels = {};
90168           var active = {}; // create panels
90169
90170           ids.forEach(function (k) {
90171             if (!panels[k]) {
90172               panels[k] = uiInfoPanels[k](context);
90173               active[k] = false;
90174             }
90175           });
90176
90177           function info(selection) {
90178             function redraw() {
90179               var activeids = ids.filter(function (k) {
90180                 return active[k];
90181               }).sort();
90182               var containers = infoPanels.selectAll('.panel-container').data(activeids, function (k) {
90183                 return k;
90184               });
90185               containers.exit().style('opacity', 1).transition().duration(200).style('opacity', 0).on('end', function (d) {
90186                 select(this).call(panels[d].off).remove();
90187               });
90188               var enter = containers.enter().append('div').attr('class', function (d) {
90189                 return 'fillD2 panel-container panel-container-' + d;
90190               });
90191               enter.style('opacity', 0).transition().duration(200).style('opacity', 1);
90192               var title = enter.append('div').attr('class', 'panel-title fillD2');
90193               title.append('h3').html(function (d) {
90194                 return panels[d].label;
90195               });
90196               title.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function (d3_event, d) {
90197                 d3_event.stopImmediatePropagation();
90198                 d3_event.preventDefault();
90199                 info.toggle(d);
90200               }).call(svgIcon('#iD-icon-close'));
90201               enter.append('div').attr('class', function (d) {
90202                 return 'panel-content panel-content-' + d;
90203               }); // redraw the panels
90204
90205               infoPanels.selectAll('.panel-content').each(function (d) {
90206                 select(this).call(panels[d]);
90207               });
90208             }
90209
90210             info.toggle = function (which) {
90211               var activeids = ids.filter(function (k) {
90212                 return active[k];
90213               });
90214
90215               if (which) {
90216                 // toggle one
90217                 active[which] = !active[which];
90218
90219                 if (activeids.length === 1 && activeids[0] === which) {
90220                   // none active anymore
90221                   wasActive = [which];
90222                 }
90223
90224                 context.container().select('.' + which + '-panel-toggle-item').classed('active', active[which]).select('input').property('checked', active[which]);
90225               } else {
90226                 // toggle all
90227                 if (activeids.length) {
90228                   wasActive = activeids;
90229                   activeids.forEach(function (k) {
90230                     active[k] = false;
90231                   });
90232                 } else {
90233                   wasActive.forEach(function (k) {
90234                     active[k] = true;
90235                   });
90236                 }
90237               }
90238
90239               redraw();
90240             };
90241
90242             var infoPanels = selection.selectAll('.info-panels').data([0]);
90243             infoPanels = infoPanels.enter().append('div').attr('class', 'info-panels').merge(infoPanels);
90244             redraw();
90245             context.keybinding().on(uiCmd('⌘' + _t('info_panels.key')), function (d3_event) {
90246               d3_event.stopImmediatePropagation();
90247               d3_event.preventDefault();
90248               info.toggle();
90249             });
90250             ids.forEach(function (k) {
90251               var key = _t('info_panels.' + k + '.key', {
90252                 "default": null
90253               });
90254               if (!key) return;
90255               context.keybinding().on(uiCmd('⌘⇧' + key), function (d3_event) {
90256                 d3_event.stopImmediatePropagation();
90257                 d3_event.preventDefault();
90258                 info.toggle(k);
90259               });
90260             });
90261           }
90262
90263           return info;
90264         }
90265
90266         function pointBox(loc, context) {
90267           var rect = context.surfaceRect();
90268           var point = context.curtainProjection(loc);
90269           return {
90270             left: point[0] + rect.left - 40,
90271             top: point[1] + rect.top - 60,
90272             width: 80,
90273             height: 90
90274           };
90275         }
90276         function pad(locOrBox, padding, context) {
90277           var box;
90278
90279           if (locOrBox instanceof Array) {
90280             var rect = context.surfaceRect();
90281             var point = context.curtainProjection(locOrBox);
90282             box = {
90283               left: point[0] + rect.left,
90284               top: point[1] + rect.top
90285             };
90286           } else {
90287             box = locOrBox;
90288           }
90289
90290           return {
90291             left: box.left - padding,
90292             top: box.top - padding,
90293             width: (box.width || 0) + 2 * padding,
90294             height: (box.width || 0) + 2 * padding
90295           };
90296         }
90297         function icon(name, svgklass, useklass) {
90298           return '<svg class="icon ' + (svgklass || '') + '">' + '<use xlink:href="' + name + '"' + (useklass ? ' class="' + useklass + '"' : '') + '></use></svg>';
90299         }
90300         var helpStringReplacements; // Returns the localized HTML element for `id` with a standardized set of icon, key, and
90301         // label replacements suitable for tutorials and documentation. Optionally supplemented
90302         // with custom `replacements`
90303
90304         function helpHtml(id, replacements) {
90305           // only load these the first time
90306           if (!helpStringReplacements) {
90307             helpStringReplacements = {
90308               // insert icons corresponding to various UI elements
90309               point_icon: icon('#iD-icon-point', 'inline'),
90310               line_icon: icon('#iD-icon-line', 'inline'),
90311               area_icon: icon('#iD-icon-area', 'inline'),
90312               note_icon: icon('#iD-icon-note', 'inline add-note'),
90313               plus: icon('#iD-icon-plus', 'inline'),
90314               minus: icon('#iD-icon-minus', 'inline'),
90315               layers_icon: icon('#iD-icon-layers', 'inline'),
90316               data_icon: icon('#iD-icon-data', 'inline'),
90317               inspect: icon('#iD-icon-inspect', 'inline'),
90318               help_icon: icon('#iD-icon-help', 'inline'),
90319               undo_icon: icon(_mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-redo' : '#iD-icon-undo', 'inline'),
90320               redo_icon: icon(_mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-undo' : '#iD-icon-redo', 'inline'),
90321               save_icon: icon('#iD-icon-save', 'inline'),
90322               // operation icons
90323               circularize_icon: icon('#iD-operation-circularize', 'inline operation'),
90324               continue_icon: icon('#iD-operation-continue', 'inline operation'),
90325               copy_icon: icon('#iD-operation-copy', 'inline operation'),
90326               delete_icon: icon('#iD-operation-delete', 'inline operation'),
90327               disconnect_icon: icon('#iD-operation-disconnect', 'inline operation'),
90328               downgrade_icon: icon('#iD-operation-downgrade', 'inline operation'),
90329               extract_icon: icon('#iD-operation-extract', 'inline operation'),
90330               merge_icon: icon('#iD-operation-merge', 'inline operation'),
90331               move_icon: icon('#iD-operation-move', 'inline operation'),
90332               orthogonalize_icon: icon('#iD-operation-orthogonalize', 'inline operation'),
90333               paste_icon: icon('#iD-operation-paste', 'inline operation'),
90334               reflect_long_icon: icon('#iD-operation-reflect-long', 'inline operation'),
90335               reflect_short_icon: icon('#iD-operation-reflect-short', 'inline operation'),
90336               reverse_icon: icon('#iD-operation-reverse', 'inline operation'),
90337               rotate_icon: icon('#iD-operation-rotate', 'inline operation'),
90338               split_icon: icon('#iD-operation-split', 'inline operation'),
90339               straighten_icon: icon('#iD-operation-straighten', 'inline operation'),
90340               // interaction icons
90341               leftclick: icon('#iD-walkthrough-mouse-left', 'inline operation'),
90342               rightclick: icon('#iD-walkthrough-mouse-right', 'inline operation'),
90343               mousewheel_icon: icon('#iD-walkthrough-mousewheel', 'inline operation'),
90344               tap_icon: icon('#iD-walkthrough-tap', 'inline operation'),
90345               doubletap_icon: icon('#iD-walkthrough-doubletap', 'inline operation'),
90346               longpress_icon: icon('#iD-walkthrough-longpress', 'inline operation'),
90347               touchdrag_icon: icon('#iD-walkthrough-touchdrag', 'inline operation'),
90348               pinch_icon: icon('#iD-walkthrough-pinch-apart', 'inline operation'),
90349               // insert keys; may be localized and platform-dependent
90350               shift: uiCmd.display('⇧'),
90351               alt: uiCmd.display('⌥'),
90352               "return": uiCmd.display('↵'),
90353               esc: _t.html('shortcuts.key.esc'),
90354               space: _t.html('shortcuts.key.space'),
90355               add_note_key: _t.html('modes.add_note.key'),
90356               help_key: _t.html('help.key'),
90357               shortcuts_key: _t.html('shortcuts.toggle.key'),
90358               // reference localized UI labels directly so that they'll always match
90359               save: _t.html('save.title'),
90360               undo: _t.html('undo.title'),
90361               redo: _t.html('redo.title'),
90362               upload: _t.html('commit.save'),
90363               point: _t.html('modes.add_point.title'),
90364               line: _t.html('modes.add_line.title'),
90365               area: _t.html('modes.add_area.title'),
90366               note: _t.html('modes.add_note.label'),
90367               circularize: _t.html('operations.circularize.title'),
90368               "continue": _t.html('operations.continue.title'),
90369               copy: _t.html('operations.copy.title'),
90370               "delete": _t.html('operations.delete.title'),
90371               disconnect: _t.html('operations.disconnect.title'),
90372               downgrade: _t.html('operations.downgrade.title'),
90373               extract: _t.html('operations.extract.title'),
90374               merge: _t.html('operations.merge.title'),
90375               move: _t.html('operations.move.title'),
90376               orthogonalize: _t.html('operations.orthogonalize.title'),
90377               paste: _t.html('operations.paste.title'),
90378               reflect_long: _t.html('operations.reflect.title.long'),
90379               reflect_short: _t.html('operations.reflect.title.short'),
90380               reverse: _t.html('operations.reverse.title'),
90381               rotate: _t.html('operations.rotate.title'),
90382               split: _t.html('operations.split.title'),
90383               straighten: _t.html('operations.straighten.title'),
90384               map_data: _t.html('map_data.title'),
90385               osm_notes: _t.html('map_data.layers.notes.title'),
90386               fields: _t.html('inspector.fields'),
90387               tags: _t.html('inspector.tags'),
90388               relations: _t.html('inspector.relations'),
90389               new_relation: _t.html('inspector.new_relation'),
90390               turn_restrictions: _t.html('_tagging.presets.fields.restrictions.label'),
90391               background_settings: _t.html('background.description'),
90392               imagery_offset: _t.html('background.fix_misalignment'),
90393               start_the_walkthrough: _t.html('splash.walkthrough'),
90394               help: _t.html('help.title'),
90395               ok: _t.html('intro.ok')
90396             };
90397
90398             for (var key in helpStringReplacements) {
90399               helpStringReplacements[key] = {
90400                 html: helpStringReplacements[key]
90401               };
90402             }
90403           }
90404
90405           var reps;
90406
90407           if (replacements) {
90408             reps = Object.assign(replacements, helpStringReplacements);
90409           } else {
90410             reps = helpStringReplacements;
90411           }
90412
90413           return _t.html(id, reps) // use keyboard key styling for shortcuts
90414           .replace(/\`(.*?)\`/g, '<kbd>$1</kbd>');
90415         }
90416
90417         function slugify(text) {
90418           return text.toString().toLowerCase().replace(/\s+/g, '-') // Replace spaces with -
90419           .replace(/[^\w\-]+/g, '') // Remove all non-word chars
90420           .replace(/\-\-+/g, '-') // Replace multiple - with single -
90421           .replace(/^-+/, '') // Trim - from start of text
90422           .replace(/-+$/, ''); // Trim - from end of text
90423         } // console warning for missing walkthrough names
90424
90425
90426         var missingStrings = {};
90427
90428         function checkKey(key, text) {
90429           if (_t(key, {
90430             "default": undefined
90431           }) === undefined) {
90432             if (missingStrings.hasOwnProperty(key)) return; // warn once
90433
90434             missingStrings[key] = text;
90435             var missing = key + ': ' + text;
90436             if (typeof console !== 'undefined') console.log(missing); // eslint-disable-line
90437           }
90438         }
90439
90440         function localize(obj) {
90441           var key; // Assign name if entity has one..
90442
90443           var name = obj.tags && obj.tags.name;
90444
90445           if (name) {
90446             key = 'intro.graph.name.' + slugify(name);
90447             obj.tags.name = _t(key, {
90448               "default": name
90449             });
90450             checkKey(key, name);
90451           } // Assign street name if entity has one..
90452
90453
90454           var street = obj.tags && obj.tags['addr:street'];
90455
90456           if (street) {
90457             key = 'intro.graph.name.' + slugify(street);
90458             obj.tags['addr:street'] = _t(key, {
90459               "default": street
90460             });
90461             checkKey(key, street); // Add address details common across walkthrough..
90462
90463             var addrTags = ['block_number', 'city', 'county', 'district', 'hamlet', 'neighbourhood', 'postcode', 'province', 'quarter', 'state', 'subdistrict', 'suburb'];
90464             addrTags.forEach(function (k) {
90465               var key = 'intro.graph.' + k;
90466               var tag = 'addr:' + k;
90467               var val = obj.tags && obj.tags[tag];
90468               var str = _t(key, {
90469                 "default": val
90470               });
90471
90472               if (str) {
90473                 if (str.match(/^<.*>$/) !== null) {
90474                   delete obj.tags[tag];
90475                 } else {
90476                   obj.tags[tag] = str;
90477                 }
90478               }
90479             });
90480           }
90481
90482           return obj;
90483         } // Used to detect squareness.. some duplicataion of code from actionOrthogonalize.
90484
90485         function isMostlySquare(points) {
90486           // note: uses 15 here instead of the 12 from actionOrthogonalize because
90487           // actionOrthogonalize can actually straighten some larger angles as it iterates
90488           var threshold = 15; // degrees within right or straight
90489
90490           var lowerBound = Math.cos((90 - threshold) * Math.PI / 180); // near right
90491
90492           var upperBound = Math.cos(threshold * Math.PI / 180); // near straight
90493
90494           for (var i = 0; i < points.length; i++) {
90495             var a = points[(i - 1 + points.length) % points.length];
90496             var origin = points[i];
90497             var b = points[(i + 1) % points.length];
90498             var dotp = geoVecNormalizedDot(a, b, origin);
90499             var mag = Math.abs(dotp);
90500
90501             if (mag > lowerBound && mag < upperBound) {
90502               return false;
90503             }
90504           }
90505
90506           return true;
90507         }
90508         function selectMenuItem(context, operation) {
90509           return context.container().select('.edit-menu .edit-menu-item-' + operation);
90510         }
90511         function transitionTime(point1, point2) {
90512           var distance = geoSphericalDistance(point1, point2);
90513
90514           if (distance === 0) {
90515             return 0;
90516           } else if (distance < 80) {
90517             return 500;
90518           } else {
90519             return 1000;
90520           }
90521         }
90522
90523         // hide class, which sets display=none, and a d3 transition for opacity.
90524         // this will cause blinking when called repeatedly, so check that the
90525         // value actually changes between calls.
90526
90527         function uiToggle(show, callback) {
90528           return function (selection) {
90529             selection.style('opacity', show ? 0 : 1).classed('hide', false).transition().style('opacity', show ? 1 : 0).on('end', function () {
90530               select(this).classed('hide', !show).style('opacity', null);
90531               if (callback) callback.apply(this);
90532             });
90533           };
90534         }
90535
90536         function uiCurtain(containerNode) {
90537           var surface = select(null),
90538               tooltip = select(null),
90539               darkness = select(null);
90540
90541           function curtain(selection) {
90542             surface = selection.append('svg').attr('class', 'curtain').style('top', 0).style('left', 0);
90543             darkness = surface.append('path').attr('x', 0).attr('y', 0).attr('class', 'curtain-darkness');
90544             select(window).on('resize.curtain', resize);
90545             tooltip = selection.append('div').attr('class', 'tooltip');
90546             tooltip.append('div').attr('class', 'popover-arrow');
90547             tooltip.append('div').attr('class', 'popover-inner');
90548             resize();
90549
90550             function resize() {
90551               surface.attr('width', containerNode.clientWidth).attr('height', containerNode.clientHeight);
90552               curtain.cut(darkness.datum());
90553             }
90554           }
90555           /**
90556            * Reveal cuts the curtain to highlight the given box,
90557            * and shows a tooltip with instructions next to the box.
90558            *
90559            * @param  {String|ClientRect} [box]   box used to cut the curtain
90560            * @param  {String}    [text]          text for a tooltip
90561            * @param  {Object}    [options]
90562            * @param  {string}    [options.tooltipClass]    optional class to add to the tooltip
90563            * @param  {integer}   [options.duration]        transition time in milliseconds
90564            * @param  {string}    [options.buttonText]      if set, create a button with this text label
90565            * @param  {function}  [options.buttonCallback]  if set, the callback for the button
90566            * @param  {function}  [options.padding]         extra margin in px to put around bbox
90567            * @param  {String|ClientRect} [options.tooltipBox]  box for tooltip position, if different from box for the curtain
90568            */
90569
90570
90571           curtain.reveal = function (box, html, options) {
90572             options = options || {};
90573
90574             if (typeof box === 'string') {
90575               box = select(box).node();
90576             }
90577
90578             if (box && box.getBoundingClientRect) {
90579               box = copyBox(box.getBoundingClientRect());
90580               var containerRect = containerNode.getBoundingClientRect();
90581               box.top -= containerRect.top;
90582               box.left -= containerRect.left;
90583             }
90584
90585             if (box && options.padding) {
90586               box.top -= options.padding;
90587               box.left -= options.padding;
90588               box.bottom += options.padding;
90589               box.right += options.padding;
90590               box.height += options.padding * 2;
90591               box.width += options.padding * 2;
90592             }
90593
90594             var tooltipBox;
90595
90596             if (options.tooltipBox) {
90597               tooltipBox = options.tooltipBox;
90598
90599               if (typeof tooltipBox === 'string') {
90600                 tooltipBox = select(tooltipBox).node();
90601               }
90602
90603               if (tooltipBox && tooltipBox.getBoundingClientRect) {
90604                 tooltipBox = copyBox(tooltipBox.getBoundingClientRect());
90605               }
90606             } else {
90607               tooltipBox = box;
90608             }
90609
90610             if (tooltipBox && html) {
90611               if (html.indexOf('**') !== -1) {
90612                 if (html.indexOf('<span') === 0) {
90613                   html = html.replace(/^(<span.*?>)(.+?)(\*\*)/, '$1<span>$2</span>$3');
90614                 } else {
90615                   html = html.replace(/^(.+?)(\*\*)/, '<span>$1</span>$2');
90616                 } // pseudo markdown bold text for the instruction section..
90617
90618
90619                 html = html.replace(/\*\*(.*?)\*\*/g, '<span class="instruction">$1</span>');
90620               }
90621
90622               html = html.replace(/\*(.*?)\*/g, '<em>$1</em>'); // emphasis
90623
90624               html = html.replace(/\{br\}/g, '<br/><br/>'); // linebreak
90625
90626               if (options.buttonText && options.buttonCallback) {
90627                 html += '<div class="button-section">' + '<button href="#" class="button action">' + options.buttonText + '</button></div>';
90628               }
90629
90630               var classes = 'curtain-tooltip popover tooltip arrowed in ' + (options.tooltipClass || '');
90631               tooltip.classed(classes, true).selectAll('.popover-inner').html(html);
90632
90633               if (options.buttonText && options.buttonCallback) {
90634                 var button = tooltip.selectAll('.button-section .button.action');
90635                 button.on('click', function (d3_event) {
90636                   d3_event.preventDefault();
90637                   options.buttonCallback();
90638                 });
90639               }
90640
90641               var tip = copyBox(tooltip.node().getBoundingClientRect()),
90642                   w = containerNode.clientWidth,
90643                   h = containerNode.clientHeight,
90644                   tooltipWidth = 200,
90645                   tooltipArrow = 5,
90646                   side,
90647                   pos; // hack: this will have bottom placement,
90648               // so need to reserve extra space for the tooltip illustration.
90649
90650               if (options.tooltipClass === 'intro-mouse') {
90651                 tip.height += 80;
90652               } // trim box dimensions to just the portion that fits in the container..
90653
90654
90655               if (tooltipBox.top + tooltipBox.height > h) {
90656                 tooltipBox.height -= tooltipBox.top + tooltipBox.height - h;
90657               }
90658
90659               if (tooltipBox.left + tooltipBox.width > w) {
90660                 tooltipBox.width -= tooltipBox.left + tooltipBox.width - w;
90661               } // determine tooltip placement..
90662
90663
90664               if (tooltipBox.top + tooltipBox.height < 100) {
90665                 // tooltip below box..
90666                 side = 'bottom';
90667                 pos = [tooltipBox.left + tooltipBox.width / 2 - tip.width / 2, tooltipBox.top + tooltipBox.height];
90668               } else if (tooltipBox.top > h - 140) {
90669                 // tooltip above box..
90670                 side = 'top';
90671                 pos = [tooltipBox.left + tooltipBox.width / 2 - tip.width / 2, tooltipBox.top - tip.height];
90672               } else {
90673                 // tooltip to the side of the tooltipBox..
90674                 var tipY = tooltipBox.top + tooltipBox.height / 2 - tip.height / 2;
90675
90676                 if (_mainLocalizer.textDirection() === 'rtl') {
90677                   if (tooltipBox.left - tooltipWidth - tooltipArrow < 70) {
90678                     side = 'right';
90679                     pos = [tooltipBox.left + tooltipBox.width + tooltipArrow, tipY];
90680                   } else {
90681                     side = 'left';
90682                     pos = [tooltipBox.left - tooltipWidth - tooltipArrow, tipY];
90683                   }
90684                 } else {
90685                   if (tooltipBox.left + tooltipBox.width + tooltipArrow + tooltipWidth > w - 70) {
90686                     side = 'left';
90687                     pos = [tooltipBox.left - tooltipWidth - tooltipArrow, tipY];
90688                   } else {
90689                     side = 'right';
90690                     pos = [tooltipBox.left + tooltipBox.width + tooltipArrow, tipY];
90691                   }
90692                 }
90693               }
90694
90695               if (options.duration !== 0 || !tooltip.classed(side)) {
90696                 tooltip.call(uiToggle(true));
90697               }
90698
90699               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
90700               // (doesn't affect the placement of the popover-arrow)
90701
90702               var shiftY = 0;
90703
90704               if (side === 'left' || side === 'right') {
90705                 if (pos[1] < 60) {
90706                   shiftY = 60 - pos[1];
90707                 } else if (pos[1] + tip.height > h - 100) {
90708                   shiftY = h - pos[1] - tip.height - 100;
90709                 }
90710               }
90711
90712               tooltip.selectAll('.popover-inner').style('top', shiftY + 'px');
90713             } else {
90714               tooltip.classed('in', false).call(uiToggle(false));
90715             }
90716
90717             curtain.cut(box, options.duration);
90718             return tooltip;
90719           };
90720
90721           curtain.cut = function (datum, duration) {
90722             darkness.datum(datum).interrupt();
90723             var selection;
90724
90725             if (duration === 0) {
90726               selection = darkness;
90727             } else {
90728               selection = darkness.transition().duration(duration || 600).ease(linear$1);
90729             }
90730
90731             selection.attr('d', function (d) {
90732               var containerWidth = containerNode.clientWidth;
90733               var containerHeight = containerNode.clientHeight;
90734               var string = 'M 0,0 L 0,' + containerHeight + ' L ' + containerWidth + ',' + containerHeight + 'L' + containerWidth + ',0 Z';
90735               if (!d) return string;
90736               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';
90737             });
90738           };
90739
90740           curtain.remove = function () {
90741             surface.remove();
90742             tooltip.remove();
90743             select(window).on('resize.curtain', null);
90744           }; // ClientRects are immutable, so copy them to an object,
90745           // in case we need to trim the height/width.
90746
90747
90748           function copyBox(src) {
90749             return {
90750               top: src.top,
90751               right: src.right,
90752               bottom: src.bottom,
90753               left: src.left,
90754               width: src.width,
90755               height: src.height
90756             };
90757           }
90758
90759           return curtain;
90760         }
90761
90762         function uiIntroWelcome(context, reveal) {
90763           var dispatch = dispatch$8('done');
90764           var chapter = {
90765             title: 'intro.welcome.title'
90766           };
90767
90768           function welcome() {
90769             context.map().centerZoom([-85.63591, 41.94285], 19);
90770             reveal('.intro-nav-wrap .chapter-welcome', helpHtml('intro.welcome.welcome'), {
90771               buttonText: _t.html('intro.ok'),
90772               buttonCallback: practice
90773             });
90774           }
90775
90776           function practice() {
90777             reveal('.intro-nav-wrap .chapter-welcome', helpHtml('intro.welcome.practice'), {
90778               buttonText: _t.html('intro.ok'),
90779               buttonCallback: words
90780             });
90781           }
90782
90783           function words() {
90784             reveal('.intro-nav-wrap .chapter-welcome', helpHtml('intro.welcome.words'), {
90785               buttonText: _t.html('intro.ok'),
90786               buttonCallback: chapters
90787             });
90788           }
90789
90790           function chapters() {
90791             dispatch.call('done');
90792             reveal('.intro-nav-wrap .chapter-navigation', helpHtml('intro.welcome.chapters', {
90793               next: _t('intro.navigation.title')
90794             }));
90795           }
90796
90797           chapter.enter = function () {
90798             welcome();
90799           };
90800
90801           chapter.exit = function () {
90802             context.container().select('.curtain-tooltip.intro-mouse').selectAll('.counter').remove();
90803           };
90804
90805           chapter.restart = function () {
90806             chapter.exit();
90807             chapter.enter();
90808           };
90809
90810           return utilRebind(chapter, dispatch, 'on');
90811         }
90812
90813         function uiIntroNavigation(context, reveal) {
90814           var dispatch = dispatch$8('done');
90815           var timeouts = [];
90816           var hallId = 'n2061';
90817           var townHall = [-85.63591, 41.94285];
90818           var springStreetId = 'w397';
90819           var springStreetEndId = 'n1834';
90820           var springStreet = [-85.63582, 41.94255];
90821           var onewayField = _mainPresetIndex.field('oneway');
90822           var maxspeedField = _mainPresetIndex.field('maxspeed');
90823           var chapter = {
90824             title: 'intro.navigation.title'
90825           };
90826
90827           function timeout(f, t) {
90828             timeouts.push(window.setTimeout(f, t));
90829           }
90830
90831           function eventCancel(d3_event) {
90832             d3_event.stopPropagation();
90833             d3_event.preventDefault();
90834           }
90835
90836           function isTownHallSelected() {
90837             var ids = context.selectedIDs();
90838             return ids.length === 1 && ids[0] === hallId;
90839           }
90840
90841           function dragMap() {
90842             context.enter(modeBrowse(context));
90843             context.history().reset('initial');
90844             var msec = transitionTime(townHall, context.map().center());
90845
90846             if (msec) {
90847               reveal(null, null, {
90848                 duration: 0
90849               });
90850             }
90851
90852             context.map().centerZoomEase(townHall, 19, msec);
90853             timeout(function () {
90854               var centerStart = context.map().center();
90855               var textId = context.lastPointerType() === 'mouse' ? 'drag' : 'drag_touch';
90856               var dragString = helpHtml('intro.navigation.map_info') + '{br}' + helpHtml('intro.navigation.' + textId);
90857               reveal('.surface', dragString);
90858               context.map().on('drawn.intro', function () {
90859                 reveal('.surface', dragString, {
90860                   duration: 0
90861                 });
90862               });
90863               context.map().on('move.intro', function () {
90864                 var centerNow = context.map().center();
90865
90866                 if (centerStart[0] !== centerNow[0] || centerStart[1] !== centerNow[1]) {
90867                   context.map().on('move.intro', null);
90868                   timeout(function () {
90869                     continueTo(zoomMap);
90870                   }, 3000);
90871                 }
90872               });
90873             }, msec + 100);
90874
90875             function continueTo(nextStep) {
90876               context.map().on('move.intro drawn.intro', null);
90877               nextStep();
90878             }
90879           }
90880
90881           function zoomMap() {
90882             var zoomStart = context.map().zoom();
90883             var textId = context.lastPointerType() === 'mouse' ? 'zoom' : 'zoom_touch';
90884             var zoomString = helpHtml('intro.navigation.' + textId);
90885             reveal('.surface', zoomString);
90886             context.map().on('drawn.intro', function () {
90887               reveal('.surface', zoomString, {
90888                 duration: 0
90889               });
90890             });
90891             context.map().on('move.intro', function () {
90892               if (context.map().zoom() !== zoomStart) {
90893                 context.map().on('move.intro', null);
90894                 timeout(function () {
90895                   continueTo(features);
90896                 }, 3000);
90897               }
90898             });
90899
90900             function continueTo(nextStep) {
90901               context.map().on('move.intro drawn.intro', null);
90902               nextStep();
90903             }
90904           }
90905
90906           function features() {
90907             var onClick = function onClick() {
90908               continueTo(pointsLinesAreas);
90909             };
90910
90911             reveal('.surface', helpHtml('intro.navigation.features'), {
90912               buttonText: _t.html('intro.ok'),
90913               buttonCallback: onClick
90914             });
90915             context.map().on('drawn.intro', function () {
90916               reveal('.surface', helpHtml('intro.navigation.features'), {
90917                 duration: 0,
90918                 buttonText: _t.html('intro.ok'),
90919                 buttonCallback: onClick
90920               });
90921             });
90922
90923             function continueTo(nextStep) {
90924               context.map().on('drawn.intro', null);
90925               nextStep();
90926             }
90927           }
90928
90929           function pointsLinesAreas() {
90930             var onClick = function onClick() {
90931               continueTo(nodesWays);
90932             };
90933
90934             reveal('.surface', helpHtml('intro.navigation.points_lines_areas'), {
90935               buttonText: _t.html('intro.ok'),
90936               buttonCallback: onClick
90937             });
90938             context.map().on('drawn.intro', function () {
90939               reveal('.surface', helpHtml('intro.navigation.points_lines_areas'), {
90940                 duration: 0,
90941                 buttonText: _t.html('intro.ok'),
90942                 buttonCallback: onClick
90943               });
90944             });
90945
90946             function continueTo(nextStep) {
90947               context.map().on('drawn.intro', null);
90948               nextStep();
90949             }
90950           }
90951
90952           function nodesWays() {
90953             var onClick = function onClick() {
90954               continueTo(clickTownHall);
90955             };
90956
90957             reveal('.surface', helpHtml('intro.navigation.nodes_ways'), {
90958               buttonText: _t.html('intro.ok'),
90959               buttonCallback: onClick
90960             });
90961             context.map().on('drawn.intro', function () {
90962               reveal('.surface', helpHtml('intro.navigation.nodes_ways'), {
90963                 duration: 0,
90964                 buttonText: _t.html('intro.ok'),
90965                 buttonCallback: onClick
90966               });
90967             });
90968
90969             function continueTo(nextStep) {
90970               context.map().on('drawn.intro', null);
90971               nextStep();
90972             }
90973           }
90974
90975           function clickTownHall() {
90976             context.enter(modeBrowse(context));
90977             context.history().reset('initial');
90978             var entity = context.hasEntity(hallId);
90979             if (!entity) return;
90980             reveal(null, null, {
90981               duration: 0
90982             });
90983             context.map().centerZoomEase(entity.loc, 19, 500);
90984             timeout(function () {
90985               var entity = context.hasEntity(hallId);
90986               if (!entity) return;
90987               var box = pointBox(entity.loc, context);
90988               var textId = context.lastPointerType() === 'mouse' ? 'click_townhall' : 'tap_townhall';
90989               reveal(box, helpHtml('intro.navigation.' + textId));
90990               context.map().on('move.intro drawn.intro', function () {
90991                 var entity = context.hasEntity(hallId);
90992                 if (!entity) return;
90993                 var box = pointBox(entity.loc, context);
90994                 reveal(box, helpHtml('intro.navigation.' + textId), {
90995                   duration: 0
90996                 });
90997               });
90998               context.on('enter.intro', function () {
90999                 if (isTownHallSelected()) continueTo(selectedTownHall);
91000               });
91001             }, 550); // after centerZoomEase
91002
91003             context.history().on('change.intro', function () {
91004               if (!context.hasEntity(hallId)) {
91005                 continueTo(clickTownHall);
91006               }
91007             });
91008
91009             function continueTo(nextStep) {
91010               context.on('enter.intro', null);
91011               context.map().on('move.intro drawn.intro', null);
91012               context.history().on('change.intro', null);
91013               nextStep();
91014             }
91015           }
91016
91017           function selectedTownHall() {
91018             if (!isTownHallSelected()) return clickTownHall();
91019             var entity = context.hasEntity(hallId);
91020             if (!entity) return clickTownHall();
91021             var box = pointBox(entity.loc, context);
91022
91023             var onClick = function onClick() {
91024               continueTo(editorTownHall);
91025             };
91026
91027             reveal(box, helpHtml('intro.navigation.selected_townhall'), {
91028               buttonText: _t.html('intro.ok'),
91029               buttonCallback: onClick
91030             });
91031             context.map().on('move.intro drawn.intro', function () {
91032               var entity = context.hasEntity(hallId);
91033               if (!entity) return;
91034               var box = pointBox(entity.loc, context);
91035               reveal(box, helpHtml('intro.navigation.selected_townhall'), {
91036                 duration: 0,
91037                 buttonText: _t.html('intro.ok'),
91038                 buttonCallback: onClick
91039               });
91040             });
91041             context.history().on('change.intro', function () {
91042               if (!context.hasEntity(hallId)) {
91043                 continueTo(clickTownHall);
91044               }
91045             });
91046
91047             function continueTo(nextStep) {
91048               context.map().on('move.intro drawn.intro', null);
91049               context.history().on('change.intro', null);
91050               nextStep();
91051             }
91052           }
91053
91054           function editorTownHall() {
91055             if (!isTownHallSelected()) return clickTownHall(); // disallow scrolling
91056
91057             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
91058
91059             var onClick = function onClick() {
91060               continueTo(presetTownHall);
91061             };
91062
91063             reveal('.entity-editor-pane', helpHtml('intro.navigation.editor_townhall'), {
91064               buttonText: _t.html('intro.ok'),
91065               buttonCallback: onClick
91066             });
91067             context.on('exit.intro', function () {
91068               continueTo(clickTownHall);
91069             });
91070             context.history().on('change.intro', function () {
91071               if (!context.hasEntity(hallId)) {
91072                 continueTo(clickTownHall);
91073               }
91074             });
91075
91076             function continueTo(nextStep) {
91077               context.on('exit.intro', null);
91078               context.history().on('change.intro', null);
91079               context.container().select('.inspector-wrap').on('wheel.intro', null);
91080               nextStep();
91081             }
91082           }
91083
91084           function presetTownHall() {
91085             if (!isTownHallSelected()) return clickTownHall(); // reset pane, in case user happened to change it..
91086
91087             context.container().select('.inspector-wrap .panewrap').style('right', '0%'); // disallow scrolling
91088
91089             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel); // preset match, in case the user happened to change it.
91090
91091             var entity = context.entity(context.selectedIDs()[0]);
91092             var preset = _mainPresetIndex.match(entity, context.graph());
91093
91094             var onClick = function onClick() {
91095               continueTo(fieldsTownHall);
91096             };
91097
91098             reveal('.entity-editor-pane .section-feature-type', helpHtml('intro.navigation.preset_townhall', {
91099               preset: preset.name()
91100             }), {
91101               buttonText: _t.html('intro.ok'),
91102               buttonCallback: onClick
91103             });
91104             context.on('exit.intro', function () {
91105               continueTo(clickTownHall);
91106             });
91107             context.history().on('change.intro', function () {
91108               if (!context.hasEntity(hallId)) {
91109                 continueTo(clickTownHall);
91110               }
91111             });
91112
91113             function continueTo(nextStep) {
91114               context.on('exit.intro', null);
91115               context.history().on('change.intro', null);
91116               context.container().select('.inspector-wrap').on('wheel.intro', null);
91117               nextStep();
91118             }
91119           }
91120
91121           function fieldsTownHall() {
91122             if (!isTownHallSelected()) return clickTownHall(); // reset pane, in case user happened to change it..
91123
91124             context.container().select('.inspector-wrap .panewrap').style('right', '0%'); // disallow scrolling
91125
91126             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
91127
91128             var onClick = function onClick() {
91129               continueTo(closeTownHall);
91130             };
91131
91132             reveal('.entity-editor-pane .section-preset-fields', helpHtml('intro.navigation.fields_townhall'), {
91133               buttonText: _t.html('intro.ok'),
91134               buttonCallback: onClick
91135             });
91136             context.on('exit.intro', function () {
91137               continueTo(clickTownHall);
91138             });
91139             context.history().on('change.intro', function () {
91140               if (!context.hasEntity(hallId)) {
91141                 continueTo(clickTownHall);
91142               }
91143             });
91144
91145             function continueTo(nextStep) {
91146               context.on('exit.intro', null);
91147               context.history().on('change.intro', null);
91148               context.container().select('.inspector-wrap').on('wheel.intro', null);
91149               nextStep();
91150             }
91151           }
91152
91153           function closeTownHall() {
91154             if (!isTownHallSelected()) return clickTownHall();
91155             var selector = '.entity-editor-pane button.close svg use';
91156             var href = select(selector).attr('href') || '#iD-icon-close';
91157             reveal('.entity-editor-pane', helpHtml('intro.navigation.close_townhall', {
91158               button: {
91159                 html: icon(href, 'inline')
91160               }
91161             }));
91162             context.on('exit.intro', function () {
91163               continueTo(searchStreet);
91164             });
91165             context.history().on('change.intro', function () {
91166               // update the close icon in the tooltip if the user edits something.
91167               var selector = '.entity-editor-pane button.close svg use';
91168               var href = select(selector).attr('href') || '#iD-icon-close';
91169               reveal('.entity-editor-pane', helpHtml('intro.navigation.close_townhall', {
91170                 button: {
91171                   html: icon(href, 'inline')
91172                 }
91173               }), {
91174                 duration: 0
91175               });
91176             });
91177
91178             function continueTo(nextStep) {
91179               context.on('exit.intro', null);
91180               context.history().on('change.intro', null);
91181               nextStep();
91182             }
91183           }
91184
91185           function searchStreet() {
91186             context.enter(modeBrowse(context));
91187             context.history().reset('initial'); // ensure spring street exists
91188
91189             var msec = transitionTime(springStreet, context.map().center());
91190
91191             if (msec) {
91192               reveal(null, null, {
91193                 duration: 0
91194               });
91195             }
91196
91197             context.map().centerZoomEase(springStreet, 19, msec); // ..and user can see it
91198
91199             timeout(function () {
91200               reveal('.search-header input', helpHtml('intro.navigation.search_street', {
91201                 name: _t('intro.graph.name.spring-street')
91202               }));
91203               context.container().select('.search-header input').on('keyup.intro', checkSearchResult);
91204             }, msec + 100);
91205           }
91206
91207           function checkSearchResult() {
91208             var first = context.container().select('.feature-list-item:nth-child(0n+2)'); // skip "No Results" item
91209
91210             var firstName = first.select('.entity-name');
91211             var name = _t('intro.graph.name.spring-street');
91212
91213             if (!firstName.empty() && firstName.html() === name) {
91214               reveal(first.node(), helpHtml('intro.navigation.choose_street', {
91215                 name: name
91216               }), {
91217                 duration: 300
91218               });
91219               context.on('exit.intro', function () {
91220                 continueTo(selectedStreet);
91221               });
91222               context.container().select('.search-header input').on('keydown.intro', eventCancel, true).on('keyup.intro', null);
91223             }
91224
91225             function continueTo(nextStep) {
91226               context.on('exit.intro', null);
91227               context.container().select('.search-header input').on('keydown.intro', null).on('keyup.intro', null);
91228               nextStep();
91229             }
91230           }
91231
91232           function selectedStreet() {
91233             if (!context.hasEntity(springStreetEndId) || !context.hasEntity(springStreetId)) {
91234               return searchStreet();
91235             }
91236
91237             var onClick = function onClick() {
91238               continueTo(editorStreet);
91239             };
91240
91241             var entity = context.entity(springStreetEndId);
91242             var box = pointBox(entity.loc, context);
91243             box.height = 500;
91244             reveal(box, helpHtml('intro.navigation.selected_street', {
91245               name: _t('intro.graph.name.spring-street')
91246             }), {
91247               duration: 600,
91248               buttonText: _t.html('intro.ok'),
91249               buttonCallback: onClick
91250             });
91251             timeout(function () {
91252               context.map().on('move.intro drawn.intro', function () {
91253                 var entity = context.hasEntity(springStreetEndId);
91254                 if (!entity) return;
91255                 var box = pointBox(entity.loc, context);
91256                 box.height = 500;
91257                 reveal(box, helpHtml('intro.navigation.selected_street', {
91258                   name: _t('intro.graph.name.spring-street')
91259                 }), {
91260                   duration: 0,
91261                   buttonText: _t.html('intro.ok'),
91262                   buttonCallback: onClick
91263                 });
91264               });
91265             }, 600); // after reveal.
91266
91267             context.on('enter.intro', function (mode) {
91268               if (!context.hasEntity(springStreetId)) {
91269                 return continueTo(searchStreet);
91270               }
91271
91272               var ids = context.selectedIDs();
91273
91274               if (mode.id !== 'select' || !ids.length || ids[0] !== springStreetId) {
91275                 // keep Spring Street selected..
91276                 context.enter(modeSelect(context, [springStreetId]));
91277               }
91278             });
91279             context.history().on('change.intro', function () {
91280               if (!context.hasEntity(springStreetEndId) || !context.hasEntity(springStreetId)) {
91281                 timeout(function () {
91282                   continueTo(searchStreet);
91283                 }, 300); // after any transition (e.g. if user deleted intersection)
91284               }
91285             });
91286
91287             function continueTo(nextStep) {
91288               context.map().on('move.intro drawn.intro', null);
91289               context.on('enter.intro', null);
91290               context.history().on('change.intro', null);
91291               nextStep();
91292             }
91293           }
91294
91295           function editorStreet() {
91296             var selector = '.entity-editor-pane button.close svg use';
91297             var href = select(selector).attr('href') || '#iD-icon-close';
91298             reveal('.entity-editor-pane', helpHtml('intro.navigation.street_different_fields') + '{br}' + helpHtml('intro.navigation.editor_street', {
91299               button: {
91300                 html: icon(href, 'inline')
91301               },
91302               field1: {
91303                 html: onewayField.label()
91304               },
91305               field2: {
91306                 html: maxspeedField.label()
91307               }
91308             }));
91309             context.on('exit.intro', function () {
91310               continueTo(play);
91311             });
91312             context.history().on('change.intro', function () {
91313               // update the close icon in the tooltip if the user edits something.
91314               var selector = '.entity-editor-pane button.close svg use';
91315               var href = select(selector).attr('href') || '#iD-icon-close';
91316               reveal('.entity-editor-pane', helpHtml('intro.navigation.street_different_fields') + '{br}' + helpHtml('intro.navigation.editor_street', {
91317                 button: {
91318                   html: icon(href, 'inline')
91319                 },
91320                 field1: {
91321                   html: onewayField.label()
91322                 },
91323                 field2: {
91324                   html: maxspeedField.label()
91325                 }
91326               }), {
91327                 duration: 0
91328               });
91329             });
91330
91331             function continueTo(nextStep) {
91332               context.on('exit.intro', null);
91333               context.history().on('change.intro', null);
91334               nextStep();
91335             }
91336           }
91337
91338           function play() {
91339             dispatch.call('done');
91340             reveal('.ideditor', helpHtml('intro.navigation.play', {
91341               next: _t('intro.points.title')
91342             }), {
91343               tooltipBox: '.intro-nav-wrap .chapter-point',
91344               buttonText: _t.html('intro.ok'),
91345               buttonCallback: function buttonCallback() {
91346                 reveal('.ideditor');
91347               }
91348             });
91349           }
91350
91351           chapter.enter = function () {
91352             dragMap();
91353           };
91354
91355           chapter.exit = function () {
91356             timeouts.forEach(window.clearTimeout);
91357             context.on('enter.intro exit.intro', null);
91358             context.map().on('move.intro drawn.intro', null);
91359             context.history().on('change.intro', null);
91360             context.container().select('.inspector-wrap').on('wheel.intro', null);
91361             context.container().select('.search-header input').on('keydown.intro keyup.intro', null);
91362           };
91363
91364           chapter.restart = function () {
91365             chapter.exit();
91366             chapter.enter();
91367           };
91368
91369           return utilRebind(chapter, dispatch, 'on');
91370         }
91371
91372         function uiIntroPoint(context, reveal) {
91373           var dispatch = dispatch$8('done');
91374           var timeouts = [];
91375           var intersection = [-85.63279, 41.94394];
91376           var building = [-85.632422, 41.944045];
91377           var cafePreset = _mainPresetIndex.item('amenity/cafe');
91378           var _pointID = null;
91379           var chapter = {
91380             title: 'intro.points.title'
91381           };
91382
91383           function timeout(f, t) {
91384             timeouts.push(window.setTimeout(f, t));
91385           }
91386
91387           function eventCancel(d3_event) {
91388             d3_event.stopPropagation();
91389             d3_event.preventDefault();
91390           }
91391
91392           function addPoint() {
91393             context.enter(modeBrowse(context));
91394             context.history().reset('initial');
91395             var msec = transitionTime(intersection, context.map().center());
91396
91397             if (msec) {
91398               reveal(null, null, {
91399                 duration: 0
91400               });
91401             }
91402
91403             context.map().centerZoomEase(intersection, 19, msec);
91404             timeout(function () {
91405               var tooltip = reveal('button.add-point', helpHtml('intro.points.points_info') + '{br}' + helpHtml('intro.points.add_point'));
91406               _pointID = null;
91407               tooltip.selectAll('.popover-inner').insert('svg', 'span').attr('class', 'tooltip-illustration').append('use').attr('xlink:href', '#iD-graphic-points');
91408               context.on('enter.intro', function (mode) {
91409                 if (mode.id !== 'add-point') return;
91410                 continueTo(placePoint);
91411               });
91412             }, msec + 100);
91413
91414             function continueTo(nextStep) {
91415               context.on('enter.intro', null);
91416               nextStep();
91417             }
91418           }
91419
91420           function placePoint() {
91421             if (context.mode().id !== 'add-point') {
91422               return chapter.restart();
91423             }
91424
91425             var pointBox = pad(building, 150, context);
91426             var textId = context.lastPointerType() === 'mouse' ? 'place_point' : 'place_point_touch';
91427             reveal(pointBox, helpHtml('intro.points.' + textId));
91428             context.map().on('move.intro drawn.intro', function () {
91429               pointBox = pad(building, 150, context);
91430               reveal(pointBox, helpHtml('intro.points.' + textId), {
91431                 duration: 0
91432               });
91433             });
91434             context.on('enter.intro', function (mode) {
91435               if (mode.id !== 'select') return chapter.restart();
91436               _pointID = context.mode().selectedIDs()[0];
91437               continueTo(searchPreset);
91438             });
91439
91440             function continueTo(nextStep) {
91441               context.map().on('move.intro drawn.intro', null);
91442               context.on('enter.intro', null);
91443               nextStep();
91444             }
91445           }
91446
91447           function searchPreset() {
91448             if (context.mode().id !== 'select' || !_pointID || !context.hasEntity(_pointID)) {
91449               return addPoint();
91450             } // disallow scrolling
91451
91452
91453             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
91454             context.container().select('.preset-search-input').on('keydown.intro', null).on('keyup.intro', checkPresetSearch);
91455             reveal('.preset-search-input', helpHtml('intro.points.search_cafe', {
91456               preset: cafePreset.name()
91457             }));
91458             context.on('enter.intro', function (mode) {
91459               if (!_pointID || !context.hasEntity(_pointID)) {
91460                 return continueTo(addPoint);
91461               }
91462
91463               var ids = context.selectedIDs();
91464
91465               if (mode.id !== 'select' || !ids.length || ids[0] !== _pointID) {
91466                 // keep the user's point selected..
91467                 context.enter(modeSelect(context, [_pointID])); // disallow scrolling
91468
91469                 context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
91470                 context.container().select('.preset-search-input').on('keydown.intro', null).on('keyup.intro', checkPresetSearch);
91471                 reveal('.preset-search-input', helpHtml('intro.points.search_cafe', {
91472                   preset: cafePreset.name()
91473                 }));
91474                 context.history().on('change.intro', null);
91475               }
91476             });
91477
91478             function checkPresetSearch() {
91479               var first = context.container().select('.preset-list-item:first-child');
91480
91481               if (first.classed('preset-amenity-cafe')) {
91482                 context.container().select('.preset-search-input').on('keydown.intro', eventCancel, true).on('keyup.intro', null);
91483                 reveal(first.select('.preset-list-button').node(), helpHtml('intro.points.choose_cafe', {
91484                   preset: cafePreset.name()
91485                 }), {
91486                   duration: 300
91487                 });
91488                 context.history().on('change.intro', function () {
91489                   continueTo(aboutFeatureEditor);
91490                 });
91491               }
91492             }
91493
91494             function continueTo(nextStep) {
91495               context.on('enter.intro', null);
91496               context.history().on('change.intro', null);
91497               context.container().select('.inspector-wrap').on('wheel.intro', null);
91498               context.container().select('.preset-search-input').on('keydown.intro keyup.intro', null);
91499               nextStep();
91500             }
91501           }
91502
91503           function aboutFeatureEditor() {
91504             if (context.mode().id !== 'select' || !_pointID || !context.hasEntity(_pointID)) {
91505               return addPoint();
91506             }
91507
91508             timeout(function () {
91509               reveal('.entity-editor-pane', helpHtml('intro.points.feature_editor'), {
91510                 tooltipClass: 'intro-points-describe',
91511                 buttonText: _t.html('intro.ok'),
91512                 buttonCallback: function buttonCallback() {
91513                   continueTo(addName);
91514                 }
91515               });
91516             }, 400);
91517             context.on('exit.intro', function () {
91518               // if user leaves select mode here, just continue with the tutorial.
91519               continueTo(reselectPoint);
91520             });
91521
91522             function continueTo(nextStep) {
91523               context.on('exit.intro', null);
91524               nextStep();
91525             }
91526           }
91527
91528           function addName() {
91529             if (context.mode().id !== 'select' || !_pointID || !context.hasEntity(_pointID)) {
91530               return addPoint();
91531             } // reset pane, in case user happened to change it..
91532
91533
91534             context.container().select('.inspector-wrap .panewrap').style('right', '0%');
91535             var addNameString = helpHtml('intro.points.fields_info') + '{br}' + helpHtml('intro.points.add_name');
91536             timeout(function () {
91537               // It's possible for the user to add a name in a previous step..
91538               // If so, don't tell them to add the name in this step.
91539               // Give them an OK button instead.
91540               var entity = context.entity(_pointID);
91541
91542               if (entity.tags.name) {
91543                 var tooltip = reveal('.entity-editor-pane', addNameString, {
91544                   tooltipClass: 'intro-points-describe',
91545                   buttonText: _t.html('intro.ok'),
91546                   buttonCallback: function buttonCallback() {
91547                     continueTo(addCloseEditor);
91548                   }
91549                 });
91550                 tooltip.select('.instruction').style('display', 'none');
91551               } else {
91552                 reveal('.entity-editor-pane', addNameString, {
91553                   tooltipClass: 'intro-points-describe'
91554                 });
91555               }
91556             }, 400);
91557             context.history().on('change.intro', function () {
91558               continueTo(addCloseEditor);
91559             });
91560             context.on('exit.intro', function () {
91561               // if user leaves select mode here, just continue with the tutorial.
91562               continueTo(reselectPoint);
91563             });
91564
91565             function continueTo(nextStep) {
91566               context.on('exit.intro', null);
91567               context.history().on('change.intro', null);
91568               nextStep();
91569             }
91570           }
91571
91572           function addCloseEditor() {
91573             // reset pane, in case user happened to change it..
91574             context.container().select('.inspector-wrap .panewrap').style('right', '0%');
91575             var selector = '.entity-editor-pane button.close svg use';
91576             var href = select(selector).attr('href') || '#iD-icon-close';
91577             context.on('exit.intro', function () {
91578               continueTo(reselectPoint);
91579             });
91580             reveal('.entity-editor-pane', helpHtml('intro.points.add_close', {
91581               button: {
91582                 html: icon(href, 'inline')
91583               }
91584             }));
91585
91586             function continueTo(nextStep) {
91587               context.on('exit.intro', null);
91588               nextStep();
91589             }
91590           }
91591
91592           function reselectPoint() {
91593             if (!_pointID) return chapter.restart();
91594             var entity = context.hasEntity(_pointID);
91595             if (!entity) return chapter.restart(); // make sure it's still a cafe, in case user somehow changed it..
91596
91597             var oldPreset = _mainPresetIndex.match(entity, context.graph());
91598             context.replace(actionChangePreset(_pointID, oldPreset, cafePreset));
91599             context.enter(modeBrowse(context));
91600             var msec = transitionTime(entity.loc, context.map().center());
91601
91602             if (msec) {
91603               reveal(null, null, {
91604                 duration: 0
91605               });
91606             }
91607
91608             context.map().centerEase(entity.loc, msec);
91609             timeout(function () {
91610               var box = pointBox(entity.loc, context);
91611               reveal(box, helpHtml('intro.points.reselect'), {
91612                 duration: 600
91613               });
91614               timeout(function () {
91615                 context.map().on('move.intro drawn.intro', function () {
91616                   var entity = context.hasEntity(_pointID);
91617                   if (!entity) return chapter.restart();
91618                   var box = pointBox(entity.loc, context);
91619                   reveal(box, helpHtml('intro.points.reselect'), {
91620                     duration: 0
91621                   });
91622                 });
91623               }, 600); // after reveal..
91624
91625               context.on('enter.intro', function (mode) {
91626                 if (mode.id !== 'select') return;
91627                 continueTo(updatePoint);
91628               });
91629             }, msec + 100);
91630
91631             function continueTo(nextStep) {
91632               context.map().on('move.intro drawn.intro', null);
91633               context.on('enter.intro', null);
91634               nextStep();
91635             }
91636           }
91637
91638           function updatePoint() {
91639             if (context.mode().id !== 'select' || !_pointID || !context.hasEntity(_pointID)) {
91640               return continueTo(reselectPoint);
91641             } // reset pane, in case user happened to untag the point..
91642
91643
91644             context.container().select('.inspector-wrap .panewrap').style('right', '0%');
91645             context.on('exit.intro', function () {
91646               continueTo(reselectPoint);
91647             });
91648             context.history().on('change.intro', function () {
91649               continueTo(updateCloseEditor);
91650             });
91651             timeout(function () {
91652               reveal('.entity-editor-pane', helpHtml('intro.points.update'), {
91653                 tooltipClass: 'intro-points-describe'
91654               });
91655             }, 400);
91656
91657             function continueTo(nextStep) {
91658               context.on('exit.intro', null);
91659               context.history().on('change.intro', null);
91660               nextStep();
91661             }
91662           }
91663
91664           function updateCloseEditor() {
91665             if (context.mode().id !== 'select' || !_pointID || !context.hasEntity(_pointID)) {
91666               return continueTo(reselectPoint);
91667             } // reset pane, in case user happened to change it..
91668
91669
91670             context.container().select('.inspector-wrap .panewrap').style('right', '0%');
91671             context.on('exit.intro', function () {
91672               continueTo(rightClickPoint);
91673             });
91674             timeout(function () {
91675               reveal('.entity-editor-pane', helpHtml('intro.points.update_close', {
91676                 button: {
91677                   html: icon('#iD-icon-close', 'inline')
91678                 }
91679               }));
91680             }, 500);
91681
91682             function continueTo(nextStep) {
91683               context.on('exit.intro', null);
91684               nextStep();
91685             }
91686           }
91687
91688           function rightClickPoint() {
91689             if (!_pointID) return chapter.restart();
91690             var entity = context.hasEntity(_pointID);
91691             if (!entity) return chapter.restart();
91692             context.enter(modeBrowse(context));
91693             var box = pointBox(entity.loc, context);
91694             var textId = context.lastPointerType() === 'mouse' ? 'rightclick' : 'edit_menu_touch';
91695             reveal(box, helpHtml('intro.points.' + textId), {
91696               duration: 600
91697             });
91698             timeout(function () {
91699               context.map().on('move.intro', function () {
91700                 var entity = context.hasEntity(_pointID);
91701                 if (!entity) return chapter.restart();
91702                 var box = pointBox(entity.loc, context);
91703                 reveal(box, helpHtml('intro.points.' + textId), {
91704                   duration: 0
91705                 });
91706               });
91707             }, 600); // after reveal
91708
91709             context.on('enter.intro', function (mode) {
91710               if (mode.id !== 'select') return;
91711               var ids = context.selectedIDs();
91712               if (ids.length !== 1 || ids[0] !== _pointID) return;
91713               timeout(function () {
91714                 var node = selectMenuItem(context, 'delete').node();
91715                 if (!node) return;
91716                 continueTo(enterDelete);
91717               }, 50); // after menu visible
91718             });
91719
91720             function continueTo(nextStep) {
91721               context.on('enter.intro', null);
91722               context.map().on('move.intro', null);
91723               nextStep();
91724             }
91725           }
91726
91727           function enterDelete() {
91728             if (!_pointID) return chapter.restart();
91729             var entity = context.hasEntity(_pointID);
91730             if (!entity) return chapter.restart();
91731             var node = selectMenuItem(context, 'delete').node();
91732
91733             if (!node) {
91734               return continueTo(rightClickPoint);
91735             }
91736
91737             reveal('.edit-menu', helpHtml('intro.points.delete'), {
91738               padding: 50
91739             });
91740             timeout(function () {
91741               context.map().on('move.intro', function () {
91742                 reveal('.edit-menu', helpHtml('intro.points.delete'), {
91743                   duration: 0,
91744                   padding: 50
91745                 });
91746               });
91747             }, 300); // after menu visible
91748
91749             context.on('exit.intro', function () {
91750               if (!_pointID) return chapter.restart();
91751               var entity = context.hasEntity(_pointID);
91752               if (entity) return continueTo(rightClickPoint); // point still exists
91753             });
91754             context.history().on('change.intro', function (changed) {
91755               if (changed.deleted().length) {
91756                 continueTo(undo);
91757               }
91758             });
91759
91760             function continueTo(nextStep) {
91761               context.map().on('move.intro', null);
91762               context.history().on('change.intro', null);
91763               context.on('exit.intro', null);
91764               nextStep();
91765             }
91766           }
91767
91768           function undo() {
91769             context.history().on('change.intro', function () {
91770               continueTo(play);
91771             });
91772             reveal('.top-toolbar button.undo-button', helpHtml('intro.points.undo'));
91773
91774             function continueTo(nextStep) {
91775               context.history().on('change.intro', null);
91776               nextStep();
91777             }
91778           }
91779
91780           function play() {
91781             dispatch.call('done');
91782             reveal('.ideditor', helpHtml('intro.points.play', {
91783               next: _t('intro.areas.title')
91784             }), {
91785               tooltipBox: '.intro-nav-wrap .chapter-area',
91786               buttonText: _t.html('intro.ok'),
91787               buttonCallback: function buttonCallback() {
91788                 reveal('.ideditor');
91789               }
91790             });
91791           }
91792
91793           chapter.enter = function () {
91794             addPoint();
91795           };
91796
91797           chapter.exit = function () {
91798             timeouts.forEach(window.clearTimeout);
91799             context.on('enter.intro exit.intro', null);
91800             context.map().on('move.intro drawn.intro', null);
91801             context.history().on('change.intro', null);
91802             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
91803             context.container().select('.preset-search-input').on('keydown.intro keyup.intro', null);
91804           };
91805
91806           chapter.restart = function () {
91807             chapter.exit();
91808             chapter.enter();
91809           };
91810
91811           return utilRebind(chapter, dispatch, 'on');
91812         }
91813
91814         function uiIntroArea(context, reveal) {
91815           var dispatch = dispatch$8('done');
91816           var playground = [-85.63552, 41.94159];
91817           var playgroundPreset = _mainPresetIndex.item('leisure/playground');
91818           var nameField = _mainPresetIndex.field('name');
91819           var descriptionField = _mainPresetIndex.field('description');
91820           var timeouts = [];
91821
91822           var _areaID;
91823
91824           var chapter = {
91825             title: 'intro.areas.title'
91826           };
91827
91828           function timeout(f, t) {
91829             timeouts.push(window.setTimeout(f, t));
91830           }
91831
91832           function eventCancel(d3_event) {
91833             d3_event.stopPropagation();
91834             d3_event.preventDefault();
91835           }
91836
91837           function revealPlayground(center, text, options) {
91838             var padding = 180 * Math.pow(2, context.map().zoom() - 19.5);
91839             var box = pad(center, padding, context);
91840             reveal(box, text, options);
91841           }
91842
91843           function addArea() {
91844             context.enter(modeBrowse(context));
91845             context.history().reset('initial');
91846             _areaID = null;
91847             var msec = transitionTime(playground, context.map().center());
91848
91849             if (msec) {
91850               reveal(null, null, {
91851                 duration: 0
91852               });
91853             }
91854
91855             context.map().centerZoomEase(playground, 19, msec);
91856             timeout(function () {
91857               var tooltip = reveal('button.add-area', helpHtml('intro.areas.add_playground'));
91858               tooltip.selectAll('.popover-inner').insert('svg', 'span').attr('class', 'tooltip-illustration').append('use').attr('xlink:href', '#iD-graphic-areas');
91859               context.on('enter.intro', function (mode) {
91860                 if (mode.id !== 'add-area') return;
91861                 continueTo(startPlayground);
91862               });
91863             }, msec + 100);
91864
91865             function continueTo(nextStep) {
91866               context.on('enter.intro', null);
91867               nextStep();
91868             }
91869           }
91870
91871           function startPlayground() {
91872             if (context.mode().id !== 'add-area') {
91873               return chapter.restart();
91874             }
91875
91876             _areaID = null;
91877             context.map().zoomEase(19.5, 500);
91878             timeout(function () {
91879               var textId = context.lastPointerType() === 'mouse' ? 'starting_node_click' : 'starting_node_tap';
91880               var startDrawString = helpHtml('intro.areas.start_playground') + helpHtml('intro.areas.' + textId);
91881               revealPlayground(playground, startDrawString, {
91882                 duration: 250
91883               });
91884               timeout(function () {
91885                 context.map().on('move.intro drawn.intro', function () {
91886                   revealPlayground(playground, startDrawString, {
91887                     duration: 0
91888                   });
91889                 });
91890                 context.on('enter.intro', function (mode) {
91891                   if (mode.id !== 'draw-area') return chapter.restart();
91892                   continueTo(continuePlayground);
91893                 });
91894               }, 250); // after reveal
91895             }, 550); // after easing
91896
91897             function continueTo(nextStep) {
91898               context.map().on('move.intro drawn.intro', null);
91899               context.on('enter.intro', null);
91900               nextStep();
91901             }
91902           }
91903
91904           function continuePlayground() {
91905             if (context.mode().id !== 'draw-area') {
91906               return chapter.restart();
91907             }
91908
91909             _areaID = null;
91910             revealPlayground(playground, helpHtml('intro.areas.continue_playground'), {
91911               duration: 250
91912             });
91913             timeout(function () {
91914               context.map().on('move.intro drawn.intro', function () {
91915                 revealPlayground(playground, helpHtml('intro.areas.continue_playground'), {
91916                   duration: 0
91917                 });
91918               });
91919             }, 250); // after reveal
91920
91921             context.on('enter.intro', function (mode) {
91922               if (mode.id === 'draw-area') {
91923                 var entity = context.hasEntity(context.selectedIDs()[0]);
91924
91925                 if (entity && entity.nodes.length >= 6) {
91926                   return continueTo(finishPlayground);
91927                 } else {
91928                   return;
91929                 }
91930               } else if (mode.id === 'select') {
91931                 _areaID = context.selectedIDs()[0];
91932                 return continueTo(searchPresets);
91933               } else {
91934                 return chapter.restart();
91935               }
91936             });
91937
91938             function continueTo(nextStep) {
91939               context.map().on('move.intro drawn.intro', null);
91940               context.on('enter.intro', null);
91941               nextStep();
91942             }
91943           }
91944
91945           function finishPlayground() {
91946             if (context.mode().id !== 'draw-area') {
91947               return chapter.restart();
91948             }
91949
91950             _areaID = null;
91951             var finishString = helpHtml('intro.areas.finish_area_' + (context.lastPointerType() === 'mouse' ? 'click' : 'tap')) + helpHtml('intro.areas.finish_playground');
91952             revealPlayground(playground, finishString, {
91953               duration: 250
91954             });
91955             timeout(function () {
91956               context.map().on('move.intro drawn.intro', function () {
91957                 revealPlayground(playground, finishString, {
91958                   duration: 0
91959                 });
91960               });
91961             }, 250); // after reveal
91962
91963             context.on('enter.intro', function (mode) {
91964               if (mode.id === 'draw-area') {
91965                 return;
91966               } else if (mode.id === 'select') {
91967                 _areaID = context.selectedIDs()[0];
91968                 return continueTo(searchPresets);
91969               } else {
91970                 return chapter.restart();
91971               }
91972             });
91973
91974             function continueTo(nextStep) {
91975               context.map().on('move.intro drawn.intro', null);
91976               context.on('enter.intro', null);
91977               nextStep();
91978             }
91979           }
91980
91981           function searchPresets() {
91982             if (!_areaID || !context.hasEntity(_areaID)) {
91983               return addArea();
91984             }
91985
91986             var ids = context.selectedIDs();
91987
91988             if (context.mode().id !== 'select' || !ids.length || ids[0] !== _areaID) {
91989               context.enter(modeSelect(context, [_areaID]));
91990             } // disallow scrolling
91991
91992
91993             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
91994             timeout(function () {
91995               // reset pane, in case user somehow happened to change it..
91996               context.container().select('.inspector-wrap .panewrap').style('right', '-100%');
91997               context.container().select('.preset-search-input').on('keydown.intro', null).on('keyup.intro', checkPresetSearch);
91998               reveal('.preset-search-input', helpHtml('intro.areas.search_playground', {
91999                 preset: playgroundPreset.name()
92000               }));
92001             }, 400); // after preset list pane visible..
92002
92003             context.on('enter.intro', function (mode) {
92004               if (!_areaID || !context.hasEntity(_areaID)) {
92005                 return continueTo(addArea);
92006               }
92007
92008               var ids = context.selectedIDs();
92009
92010               if (mode.id !== 'select' || !ids.length || ids[0] !== _areaID) {
92011                 // keep the user's area selected..
92012                 context.enter(modeSelect(context, [_areaID])); // reset pane, in case user somehow happened to change it..
92013
92014                 context.container().select('.inspector-wrap .panewrap').style('right', '-100%'); // disallow scrolling
92015
92016                 context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
92017                 context.container().select('.preset-search-input').on('keydown.intro', null).on('keyup.intro', checkPresetSearch);
92018                 reveal('.preset-search-input', helpHtml('intro.areas.search_playground', {
92019                   preset: playgroundPreset.name()
92020                 }));
92021                 context.history().on('change.intro', null);
92022               }
92023             });
92024
92025             function checkPresetSearch() {
92026               var first = context.container().select('.preset-list-item:first-child');
92027
92028               if (first.classed('preset-leisure-playground')) {
92029                 reveal(first.select('.preset-list-button').node(), helpHtml('intro.areas.choose_playground', {
92030                   preset: playgroundPreset.name()
92031                 }), {
92032                   duration: 300
92033                 });
92034                 context.container().select('.preset-search-input').on('keydown.intro', eventCancel, true).on('keyup.intro', null);
92035                 context.history().on('change.intro', function () {
92036                   continueTo(clickAddField);
92037                 });
92038               }
92039             }
92040
92041             function continueTo(nextStep) {
92042               context.container().select('.inspector-wrap').on('wheel.intro', null);
92043               context.on('enter.intro', null);
92044               context.history().on('change.intro', null);
92045               context.container().select('.preset-search-input').on('keydown.intro keyup.intro', null);
92046               nextStep();
92047             }
92048           }
92049
92050           function clickAddField() {
92051             if (!_areaID || !context.hasEntity(_areaID)) {
92052               return addArea();
92053             }
92054
92055             var ids = context.selectedIDs();
92056
92057             if (context.mode().id !== 'select' || !ids.length || ids[0] !== _areaID) {
92058               return searchPresets();
92059             }
92060
92061             if (!context.container().select('.form-field-description').empty()) {
92062               return continueTo(describePlayground);
92063             } // disallow scrolling
92064
92065
92066             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
92067             timeout(function () {
92068               // reset pane, in case user somehow happened to change it..
92069               context.container().select('.inspector-wrap .panewrap').style('right', '0%'); // It's possible for the user to add a description in a previous step..
92070               // If they did this already, just continue to next step.
92071
92072               var entity = context.entity(_areaID);
92073
92074               if (entity.tags.description) {
92075                 return continueTo(play);
92076               } // scroll "Add field" into view
92077
92078
92079               var box = context.container().select('.more-fields').node().getBoundingClientRect();
92080
92081               if (box.top > 300) {
92082                 var pane = context.container().select('.entity-editor-pane .inspector-body');
92083                 var start = pane.node().scrollTop;
92084                 var end = start + (box.top - 300);
92085                 pane.transition().duration(250).tween('scroll.inspector', function () {
92086                   var node = this;
92087                   var i = d3_interpolateNumber(start, end);
92088                   return function (t) {
92089                     node.scrollTop = i(t);
92090                   };
92091                 });
92092               }
92093
92094               timeout(function () {
92095                 reveal('.more-fields .combobox-input', helpHtml('intro.areas.add_field', {
92096                   name: {
92097                     html: nameField.label()
92098                   },
92099                   description: {
92100                     html: descriptionField.label()
92101                   }
92102                 }), {
92103                   duration: 300
92104                 });
92105                 context.container().select('.more-fields .combobox-input').on('click.intro', function () {
92106                   // Watch for the combobox to appear...
92107                   var watcher;
92108                   watcher = window.setInterval(function () {
92109                     if (!context.container().select('div.combobox').empty()) {
92110                       window.clearInterval(watcher);
92111                       continueTo(chooseDescriptionField);
92112                     }
92113                   }, 300);
92114                 });
92115               }, 300); // after "Add Field" visible
92116             }, 400); // after editor pane visible
92117
92118             context.on('exit.intro', function () {
92119               return continueTo(searchPresets);
92120             });
92121
92122             function continueTo(nextStep) {
92123               context.container().select('.inspector-wrap').on('wheel.intro', null);
92124               context.container().select('.more-fields .combobox-input').on('click.intro', null);
92125               context.on('exit.intro', null);
92126               nextStep();
92127             }
92128           }
92129
92130           function chooseDescriptionField() {
92131             if (!_areaID || !context.hasEntity(_areaID)) {
92132               return addArea();
92133             }
92134
92135             var ids = context.selectedIDs();
92136
92137             if (context.mode().id !== 'select' || !ids.length || ids[0] !== _areaID) {
92138               return searchPresets();
92139             }
92140
92141             if (!context.container().select('.form-field-description').empty()) {
92142               return continueTo(describePlayground);
92143             } // Make sure combobox is ready..
92144
92145
92146             if (context.container().select('div.combobox').empty()) {
92147               return continueTo(clickAddField);
92148             } // Watch for the combobox to go away..
92149
92150
92151             var watcher;
92152             watcher = window.setInterval(function () {
92153               if (context.container().select('div.combobox').empty()) {
92154                 window.clearInterval(watcher);
92155                 timeout(function () {
92156                   if (context.container().select('.form-field-description').empty()) {
92157                     continueTo(retryChooseDescription);
92158                   } else {
92159                     continueTo(describePlayground);
92160                   }
92161                 }, 300); // after description field added.
92162               }
92163             }, 300);
92164             reveal('div.combobox', helpHtml('intro.areas.choose_field', {
92165               field: {
92166                 html: descriptionField.label()
92167               }
92168             }), {
92169               duration: 300
92170             });
92171             context.on('exit.intro', function () {
92172               return continueTo(searchPresets);
92173             });
92174
92175             function continueTo(nextStep) {
92176               if (watcher) window.clearInterval(watcher);
92177               context.on('exit.intro', null);
92178               nextStep();
92179             }
92180           }
92181
92182           function describePlayground() {
92183             if (!_areaID || !context.hasEntity(_areaID)) {
92184               return addArea();
92185             }
92186
92187             var ids = context.selectedIDs();
92188
92189             if (context.mode().id !== 'select' || !ids.length || ids[0] !== _areaID) {
92190               return searchPresets();
92191             } // reset pane, in case user happened to change it..
92192
92193
92194             context.container().select('.inspector-wrap .panewrap').style('right', '0%');
92195
92196             if (context.container().select('.form-field-description').empty()) {
92197               return continueTo(retryChooseDescription);
92198             }
92199
92200             context.on('exit.intro', function () {
92201               continueTo(play);
92202             });
92203             reveal('.entity-editor-pane', helpHtml('intro.areas.describe_playground', {
92204               button: {
92205                 html: icon('#iD-icon-close', 'inline')
92206               }
92207             }), {
92208               duration: 300
92209             });
92210
92211             function continueTo(nextStep) {
92212               context.on('exit.intro', null);
92213               nextStep();
92214             }
92215           }
92216
92217           function retryChooseDescription() {
92218             if (!_areaID || !context.hasEntity(_areaID)) {
92219               return addArea();
92220             }
92221
92222             var ids = context.selectedIDs();
92223
92224             if (context.mode().id !== 'select' || !ids.length || ids[0] !== _areaID) {
92225               return searchPresets();
92226             } // reset pane, in case user happened to change it..
92227
92228
92229             context.container().select('.inspector-wrap .panewrap').style('right', '0%');
92230             reveal('.entity-editor-pane', helpHtml('intro.areas.retry_add_field', {
92231               field: {
92232                 html: descriptionField.label()
92233               }
92234             }), {
92235               buttonText: _t.html('intro.ok'),
92236               buttonCallback: function buttonCallback() {
92237                 continueTo(clickAddField);
92238               }
92239             });
92240             context.on('exit.intro', function () {
92241               return continueTo(searchPresets);
92242             });
92243
92244             function continueTo(nextStep) {
92245               context.on('exit.intro', null);
92246               nextStep();
92247             }
92248           }
92249
92250           function play() {
92251             dispatch.call('done');
92252             reveal('.ideditor', helpHtml('intro.areas.play', {
92253               next: _t('intro.lines.title')
92254             }), {
92255               tooltipBox: '.intro-nav-wrap .chapter-line',
92256               buttonText: _t.html('intro.ok'),
92257               buttonCallback: function buttonCallback() {
92258                 reveal('.ideditor');
92259               }
92260             });
92261           }
92262
92263           chapter.enter = function () {
92264             addArea();
92265           };
92266
92267           chapter.exit = function () {
92268             timeouts.forEach(window.clearTimeout);
92269             context.on('enter.intro exit.intro', null);
92270             context.map().on('move.intro drawn.intro', null);
92271             context.history().on('change.intro', null);
92272             context.container().select('.inspector-wrap').on('wheel.intro', null);
92273             context.container().select('.preset-search-input').on('keydown.intro keyup.intro', null);
92274             context.container().select('.more-fields .combobox-input').on('click.intro', null);
92275           };
92276
92277           chapter.restart = function () {
92278             chapter.exit();
92279             chapter.enter();
92280           };
92281
92282           return utilRebind(chapter, dispatch, 'on');
92283         }
92284
92285         function uiIntroLine(context, reveal) {
92286           var dispatch = dispatch$8('done');
92287           var timeouts = [];
92288           var _tulipRoadID = null;
92289           var flowerRoadID = 'w646';
92290           var tulipRoadStart = [-85.6297754121684, 41.95805253325314];
92291           var tulipRoadMidpoint = [-85.62975395449628, 41.95787501510204];
92292           var tulipRoadIntersection = [-85.62974496187628, 41.95742515554585];
92293           var roadCategory = _mainPresetIndex.item('category-road_minor');
92294           var residentialPreset = _mainPresetIndex.item('highway/residential');
92295           var woodRoadID = 'w525';
92296           var woodRoadEndID = 'n2862';
92297           var woodRoadAddNode = [-85.62390110349587, 41.95397111462291];
92298           var woodRoadDragEndpoint = [-85.623867390213, 41.95466987786487];
92299           var woodRoadDragMidpoint = [-85.62386254803509, 41.95430395953872];
92300           var washingtonStreetID = 'w522';
92301           var twelfthAvenueID = 'w1';
92302           var eleventhAvenueEndID = 'n3550';
92303           var twelfthAvenueEndID = 'n5';
92304           var _washingtonSegmentID = null;
92305           var eleventhAvenueEnd = context.entity(eleventhAvenueEndID).loc;
92306           var twelfthAvenueEnd = context.entity(twelfthAvenueEndID).loc;
92307           var deleteLinesLoc = [-85.6219395542764, 41.95228033922477];
92308           var twelfthAvenue = [-85.62219310052491, 41.952505413152956];
92309           var chapter = {
92310             title: 'intro.lines.title'
92311           };
92312
92313           function timeout(f, t) {
92314             timeouts.push(window.setTimeout(f, t));
92315           }
92316
92317           function eventCancel(d3_event) {
92318             d3_event.stopPropagation();
92319             d3_event.preventDefault();
92320           }
92321
92322           function addLine() {
92323             context.enter(modeBrowse(context));
92324             context.history().reset('initial');
92325             var msec = transitionTime(tulipRoadStart, context.map().center());
92326
92327             if (msec) {
92328               reveal(null, null, {
92329                 duration: 0
92330               });
92331             }
92332
92333             context.map().centerZoomEase(tulipRoadStart, 18.5, msec);
92334             timeout(function () {
92335               var tooltip = reveal('button.add-line', helpHtml('intro.lines.add_line'));
92336               tooltip.selectAll('.popover-inner').insert('svg', 'span').attr('class', 'tooltip-illustration').append('use').attr('xlink:href', '#iD-graphic-lines');
92337               context.on('enter.intro', function (mode) {
92338                 if (mode.id !== 'add-line') return;
92339                 continueTo(startLine);
92340               });
92341             }, msec + 100);
92342
92343             function continueTo(nextStep) {
92344               context.on('enter.intro', null);
92345               nextStep();
92346             }
92347           }
92348
92349           function startLine() {
92350             if (context.mode().id !== 'add-line') return chapter.restart();
92351             _tulipRoadID = null;
92352             var padding = 70 * Math.pow(2, context.map().zoom() - 18);
92353             var box = pad(tulipRoadStart, padding, context);
92354             box.height = box.height + 100;
92355             var textId = context.lastPointerType() === 'mouse' ? 'start_line' : 'start_line_tap';
92356             var startLineString = helpHtml('intro.lines.missing_road') + '{br}' + helpHtml('intro.lines.line_draw_info') + helpHtml('intro.lines.' + textId);
92357             reveal(box, startLineString);
92358             context.map().on('move.intro drawn.intro', function () {
92359               padding = 70 * Math.pow(2, context.map().zoom() - 18);
92360               box = pad(tulipRoadStart, padding, context);
92361               box.height = box.height + 100;
92362               reveal(box, startLineString, {
92363                 duration: 0
92364               });
92365             });
92366             context.on('enter.intro', function (mode) {
92367               if (mode.id !== 'draw-line') return chapter.restart();
92368               continueTo(drawLine);
92369             });
92370
92371             function continueTo(nextStep) {
92372               context.map().on('move.intro drawn.intro', null);
92373               context.on('enter.intro', null);
92374               nextStep();
92375             }
92376           }
92377
92378           function drawLine() {
92379             if (context.mode().id !== 'draw-line') return chapter.restart();
92380             _tulipRoadID = context.mode().selectedIDs()[0];
92381             context.map().centerEase(tulipRoadMidpoint, 500);
92382             timeout(function () {
92383               var padding = 200 * Math.pow(2, context.map().zoom() - 18.5);
92384               var box = pad(tulipRoadMidpoint, padding, context);
92385               box.height = box.height * 2;
92386               reveal(box, helpHtml('intro.lines.intersect', {
92387                 name: _t('intro.graph.name.flower-street')
92388               }));
92389               context.map().on('move.intro drawn.intro', function () {
92390                 padding = 200 * Math.pow(2, context.map().zoom() - 18.5);
92391                 box = pad(tulipRoadMidpoint, padding, context);
92392                 box.height = box.height * 2;
92393                 reveal(box, helpHtml('intro.lines.intersect', {
92394                   name: _t('intro.graph.name.flower-street')
92395                 }), {
92396                   duration: 0
92397                 });
92398               });
92399             }, 550); // after easing..
92400
92401             context.history().on('change.intro', function () {
92402               if (isLineConnected()) {
92403                 continueTo(continueLine);
92404               }
92405             });
92406             context.on('enter.intro', function (mode) {
92407               if (mode.id === 'draw-line') {
92408                 return;
92409               } else if (mode.id === 'select') {
92410                 continueTo(retryIntersect);
92411                 return;
92412               } else {
92413                 return chapter.restart();
92414               }
92415             });
92416
92417             function continueTo(nextStep) {
92418               context.map().on('move.intro drawn.intro', null);
92419               context.history().on('change.intro', null);
92420               context.on('enter.intro', null);
92421               nextStep();
92422             }
92423           }
92424
92425           function isLineConnected() {
92426             var entity = _tulipRoadID && context.hasEntity(_tulipRoadID);
92427
92428             if (!entity) return false;
92429             var drawNodes = context.graph().childNodes(entity);
92430             return drawNodes.some(function (node) {
92431               return context.graph().parentWays(node).some(function (parent) {
92432                 return parent.id === flowerRoadID;
92433               });
92434             });
92435           }
92436
92437           function retryIntersect() {
92438             select(window).on('pointerdown.intro mousedown.intro', eventCancel, true);
92439             var box = pad(tulipRoadIntersection, 80, context);
92440             reveal(box, helpHtml('intro.lines.retry_intersect', {
92441               name: _t('intro.graph.name.flower-street')
92442             }));
92443             timeout(chapter.restart, 3000);
92444           }
92445
92446           function continueLine() {
92447             if (context.mode().id !== 'draw-line') return chapter.restart();
92448
92449             var entity = _tulipRoadID && context.hasEntity(_tulipRoadID);
92450
92451             if (!entity) return chapter.restart();
92452             context.map().centerEase(tulipRoadIntersection, 500);
92453             var continueLineText = helpHtml('intro.lines.continue_line') + '{br}' + helpHtml('intro.lines.finish_line_' + (context.lastPointerType() === 'mouse' ? 'click' : 'tap')) + helpHtml('intro.lines.finish_road');
92454             reveal('.surface', continueLineText);
92455             context.on('enter.intro', function (mode) {
92456               if (mode.id === 'draw-line') {
92457                 return;
92458               } else if (mode.id === 'select') {
92459                 return continueTo(chooseCategoryRoad);
92460               } else {
92461                 return chapter.restart();
92462               }
92463             });
92464
92465             function continueTo(nextStep) {
92466               context.on('enter.intro', null);
92467               nextStep();
92468             }
92469           }
92470
92471           function chooseCategoryRoad() {
92472             if (context.mode().id !== 'select') return chapter.restart();
92473             context.on('exit.intro', function () {
92474               return chapter.restart();
92475             });
92476             var button = context.container().select('.preset-category-road_minor .preset-list-button');
92477             if (button.empty()) return chapter.restart(); // disallow scrolling
92478
92479             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
92480             timeout(function () {
92481               // reset pane, in case user somehow happened to change it..
92482               context.container().select('.inspector-wrap .panewrap').style('right', '-100%');
92483               reveal(button.node(), helpHtml('intro.lines.choose_category_road', {
92484                 category: roadCategory.name()
92485               }));
92486               button.on('click.intro', function () {
92487                 continueTo(choosePresetResidential);
92488               });
92489             }, 400); // after editor pane visible
92490
92491             function continueTo(nextStep) {
92492               context.container().select('.inspector-wrap').on('wheel.intro', null);
92493               context.container().select('.preset-list-button').on('click.intro', null);
92494               context.on('exit.intro', null);
92495               nextStep();
92496             }
92497           }
92498
92499           function choosePresetResidential() {
92500             if (context.mode().id !== 'select') return chapter.restart();
92501             context.on('exit.intro', function () {
92502               return chapter.restart();
92503             });
92504             var subgrid = context.container().select('.preset-category-road_minor .subgrid');
92505             if (subgrid.empty()) return chapter.restart();
92506             subgrid.selectAll(':not(.preset-highway-residential) .preset-list-button').on('click.intro', function () {
92507               continueTo(retryPresetResidential);
92508             });
92509             subgrid.selectAll('.preset-highway-residential .preset-list-button').on('click.intro', function () {
92510               continueTo(nameRoad);
92511             });
92512             timeout(function () {
92513               reveal(subgrid.node(), helpHtml('intro.lines.choose_preset_residential', {
92514                 preset: residentialPreset.name()
92515               }), {
92516                 tooltipBox: '.preset-highway-residential .preset-list-button',
92517                 duration: 300
92518               });
92519             }, 300);
92520
92521             function continueTo(nextStep) {
92522               context.container().select('.preset-list-button').on('click.intro', null);
92523               context.on('exit.intro', null);
92524               nextStep();
92525             }
92526           } // selected wrong road type
92527
92528
92529           function retryPresetResidential() {
92530             if (context.mode().id !== 'select') return chapter.restart();
92531             context.on('exit.intro', function () {
92532               return chapter.restart();
92533             }); // disallow scrolling
92534
92535             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
92536             timeout(function () {
92537               var button = context.container().select('.entity-editor-pane .preset-list-button');
92538               reveal(button.node(), helpHtml('intro.lines.retry_preset_residential', {
92539                 preset: residentialPreset.name()
92540               }));
92541               button.on('click.intro', function () {
92542                 continueTo(chooseCategoryRoad);
92543               });
92544             }, 500);
92545
92546             function continueTo(nextStep) {
92547               context.container().select('.inspector-wrap').on('wheel.intro', null);
92548               context.container().select('.preset-list-button').on('click.intro', null);
92549               context.on('exit.intro', null);
92550               nextStep();
92551             }
92552           }
92553
92554           function nameRoad() {
92555             context.on('exit.intro', function () {
92556               continueTo(didNameRoad);
92557             });
92558             timeout(function () {
92559               reveal('.entity-editor-pane', helpHtml('intro.lines.name_road', {
92560                 button: {
92561                   html: icon('#iD-icon-close', 'inline')
92562                 }
92563               }), {
92564                 tooltipClass: 'intro-lines-name_road'
92565               });
92566             }, 500);
92567
92568             function continueTo(nextStep) {
92569               context.on('exit.intro', null);
92570               nextStep();
92571             }
92572           }
92573
92574           function didNameRoad() {
92575             context.history().checkpoint('doneAddLine');
92576             timeout(function () {
92577               reveal('.surface', helpHtml('intro.lines.did_name_road'), {
92578                 buttonText: _t.html('intro.ok'),
92579                 buttonCallback: function buttonCallback() {
92580                   continueTo(updateLine);
92581                 }
92582               });
92583             }, 500);
92584
92585             function continueTo(nextStep) {
92586               nextStep();
92587             }
92588           }
92589
92590           function updateLine() {
92591             context.history().reset('doneAddLine');
92592
92593             if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92594               return chapter.restart();
92595             }
92596
92597             var msec = transitionTime(woodRoadDragMidpoint, context.map().center());
92598
92599             if (msec) {
92600               reveal(null, null, {
92601                 duration: 0
92602               });
92603             }
92604
92605             context.map().centerZoomEase(woodRoadDragMidpoint, 19, msec);
92606             timeout(function () {
92607               var padding = 250 * Math.pow(2, context.map().zoom() - 19);
92608               var box = pad(woodRoadDragMidpoint, padding, context);
92609
92610               var advance = function advance() {
92611                 continueTo(addNode);
92612               };
92613
92614               reveal(box, helpHtml('intro.lines.update_line'), {
92615                 buttonText: _t.html('intro.ok'),
92616                 buttonCallback: advance
92617               });
92618               context.map().on('move.intro drawn.intro', function () {
92619                 var padding = 250 * Math.pow(2, context.map().zoom() - 19);
92620                 var box = pad(woodRoadDragMidpoint, padding, context);
92621                 reveal(box, helpHtml('intro.lines.update_line'), {
92622                   duration: 0,
92623                   buttonText: _t.html('intro.ok'),
92624                   buttonCallback: advance
92625                 });
92626               });
92627             }, msec + 100);
92628
92629             function continueTo(nextStep) {
92630               context.map().on('move.intro drawn.intro', null);
92631               nextStep();
92632             }
92633           }
92634
92635           function addNode() {
92636             context.history().reset('doneAddLine');
92637
92638             if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92639               return chapter.restart();
92640             }
92641
92642             var padding = 40 * Math.pow(2, context.map().zoom() - 19);
92643             var box = pad(woodRoadAddNode, padding, context);
92644             var addNodeString = helpHtml('intro.lines.add_node' + (context.lastPointerType() === 'mouse' ? '' : '_touch'));
92645             reveal(box, addNodeString);
92646             context.map().on('move.intro drawn.intro', function () {
92647               var padding = 40 * Math.pow(2, context.map().zoom() - 19);
92648               var box = pad(woodRoadAddNode, padding, context);
92649               reveal(box, addNodeString, {
92650                 duration: 0
92651               });
92652             });
92653             context.history().on('change.intro', function (changed) {
92654               if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92655                 return continueTo(updateLine);
92656               }
92657
92658               if (changed.created().length === 1) {
92659                 timeout(function () {
92660                   continueTo(startDragEndpoint);
92661                 }, 500);
92662               }
92663             });
92664             context.on('enter.intro', function (mode) {
92665               if (mode.id !== 'select') {
92666                 continueTo(updateLine);
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 startDragEndpoint() {
92679             if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92680               return continueTo(updateLine);
92681             }
92682
92683             var padding = 100 * Math.pow(2, context.map().zoom() - 19);
92684             var box = pad(woodRoadDragEndpoint, padding, context);
92685             var startDragString = helpHtml('intro.lines.start_drag_endpoint' + (context.lastPointerType() === 'mouse' ? '' : '_touch')) + helpHtml('intro.lines.drag_to_intersection');
92686             reveal(box, startDragString);
92687             context.map().on('move.intro drawn.intro', function () {
92688               if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92689                 return continueTo(updateLine);
92690               }
92691
92692               var padding = 100 * Math.pow(2, context.map().zoom() - 19);
92693               var box = pad(woodRoadDragEndpoint, padding, context);
92694               reveal(box, startDragString, {
92695                 duration: 0
92696               });
92697               var entity = context.entity(woodRoadEndID);
92698
92699               if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) <= 4) {
92700                 continueTo(finishDragEndpoint);
92701               }
92702             });
92703
92704             function continueTo(nextStep) {
92705               context.map().on('move.intro drawn.intro', null);
92706               nextStep();
92707             }
92708           }
92709
92710           function finishDragEndpoint() {
92711             if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92712               return continueTo(updateLine);
92713             }
92714
92715             var padding = 100 * Math.pow(2, context.map().zoom() - 19);
92716             var box = pad(woodRoadDragEndpoint, padding, context);
92717             var finishDragString = helpHtml('intro.lines.spot_looks_good') + helpHtml('intro.lines.finish_drag_endpoint' + (context.lastPointerType() === 'mouse' ? '' : '_touch'));
92718             reveal(box, finishDragString);
92719             context.map().on('move.intro drawn.intro', function () {
92720               if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92721                 return continueTo(updateLine);
92722               }
92723
92724               var padding = 100 * Math.pow(2, context.map().zoom() - 19);
92725               var box = pad(woodRoadDragEndpoint, padding, context);
92726               reveal(box, finishDragString, {
92727                 duration: 0
92728               });
92729               var entity = context.entity(woodRoadEndID);
92730
92731               if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) > 4) {
92732                 continueTo(startDragEndpoint);
92733               }
92734             });
92735             context.on('enter.intro', function () {
92736               continueTo(startDragMidpoint);
92737             });
92738
92739             function continueTo(nextStep) {
92740               context.map().on('move.intro drawn.intro', null);
92741               context.on('enter.intro', null);
92742               nextStep();
92743             }
92744           }
92745
92746           function startDragMidpoint() {
92747             if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92748               return continueTo(updateLine);
92749             }
92750
92751             if (context.selectedIDs().indexOf(woodRoadID) === -1) {
92752               context.enter(modeSelect(context, [woodRoadID]));
92753             }
92754
92755             var padding = 80 * Math.pow(2, context.map().zoom() - 19);
92756             var box = pad(woodRoadDragMidpoint, padding, context);
92757             reveal(box, helpHtml('intro.lines.start_drag_midpoint'));
92758             context.map().on('move.intro drawn.intro', function () {
92759               if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92760                 return continueTo(updateLine);
92761               }
92762
92763               var padding = 80 * Math.pow(2, context.map().zoom() - 19);
92764               var box = pad(woodRoadDragMidpoint, padding, context);
92765               reveal(box, helpHtml('intro.lines.start_drag_midpoint'), {
92766                 duration: 0
92767               });
92768             });
92769             context.history().on('change.intro', function (changed) {
92770               if (changed.created().length === 1) {
92771                 continueTo(continueDragMidpoint);
92772               }
92773             });
92774             context.on('enter.intro', function (mode) {
92775               if (mode.id !== 'select') {
92776                 // keep Wood Road selected so midpoint triangles are drawn..
92777                 context.enter(modeSelect(context, [woodRoadID]));
92778               }
92779             });
92780
92781             function continueTo(nextStep) {
92782               context.map().on('move.intro drawn.intro', null);
92783               context.history().on('change.intro', null);
92784               context.on('enter.intro', null);
92785               nextStep();
92786             }
92787           }
92788
92789           function continueDragMidpoint() {
92790             if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92791               return continueTo(updateLine);
92792             }
92793
92794             var padding = 100 * Math.pow(2, context.map().zoom() - 19);
92795             var box = pad(woodRoadDragEndpoint, padding, context);
92796             box.height += 400;
92797
92798             var advance = function advance() {
92799               context.history().checkpoint('doneUpdateLine');
92800               continueTo(deleteLines);
92801             };
92802
92803             reveal(box, helpHtml('intro.lines.continue_drag_midpoint'), {
92804               buttonText: _t.html('intro.ok'),
92805               buttonCallback: advance
92806             });
92807             context.map().on('move.intro drawn.intro', function () {
92808               if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92809                 return continueTo(updateLine);
92810               }
92811
92812               var padding = 100 * Math.pow(2, context.map().zoom() - 19);
92813               var box = pad(woodRoadDragEndpoint, padding, context);
92814               box.height += 400;
92815               reveal(box, helpHtml('intro.lines.continue_drag_midpoint'), {
92816                 duration: 0,
92817                 buttonText: _t.html('intro.ok'),
92818                 buttonCallback: advance
92819               });
92820             });
92821
92822             function continueTo(nextStep) {
92823               context.map().on('move.intro drawn.intro', null);
92824               nextStep();
92825             }
92826           }
92827
92828           function deleteLines() {
92829             context.history().reset('doneUpdateLine');
92830             context.enter(modeBrowse(context));
92831
92832             if (!context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
92833               return chapter.restart();
92834             }
92835
92836             var msec = transitionTime(deleteLinesLoc, context.map().center());
92837
92838             if (msec) {
92839               reveal(null, null, {
92840                 duration: 0
92841               });
92842             }
92843
92844             context.map().centerZoomEase(deleteLinesLoc, 18, msec);
92845             timeout(function () {
92846               var padding = 200 * Math.pow(2, context.map().zoom() - 18);
92847               var box = pad(deleteLinesLoc, padding, context);
92848               box.top -= 200;
92849               box.height += 400;
92850
92851               var advance = function advance() {
92852                 continueTo(rightClickIntersection);
92853               };
92854
92855               reveal(box, helpHtml('intro.lines.delete_lines', {
92856                 street: _t('intro.graph.name.12th-avenue')
92857               }), {
92858                 buttonText: _t.html('intro.ok'),
92859                 buttonCallback: advance
92860               });
92861               context.map().on('move.intro drawn.intro', function () {
92862                 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
92863                 var box = pad(deleteLinesLoc, padding, context);
92864                 box.top -= 200;
92865                 box.height += 400;
92866                 reveal(box, helpHtml('intro.lines.delete_lines', {
92867                   street: _t('intro.graph.name.12th-avenue')
92868                 }), {
92869                   duration: 0,
92870                   buttonText: _t.html('intro.ok'),
92871                   buttonCallback: advance
92872                 });
92873               });
92874               context.history().on('change.intro', function () {
92875                 timeout(function () {
92876                   continueTo(deleteLines);
92877                 }, 500); // after any transition (e.g. if user deleted intersection)
92878               });
92879             }, msec + 100);
92880
92881             function continueTo(nextStep) {
92882               context.map().on('move.intro drawn.intro', null);
92883               context.history().on('change.intro', null);
92884               nextStep();
92885             }
92886           }
92887
92888           function rightClickIntersection() {
92889             context.history().reset('doneUpdateLine');
92890             context.enter(modeBrowse(context));
92891             context.map().centerZoomEase(eleventhAvenueEnd, 18, 500);
92892             var rightClickString = helpHtml('intro.lines.split_street', {
92893               street1: _t('intro.graph.name.11th-avenue'),
92894               street2: _t('intro.graph.name.washington-street')
92895             }) + helpHtml('intro.lines.' + (context.lastPointerType() === 'mouse' ? 'rightclick_intersection' : 'edit_menu_intersection_touch'));
92896             timeout(function () {
92897               var padding = 60 * Math.pow(2, context.map().zoom() - 18);
92898               var box = pad(eleventhAvenueEnd, padding, context);
92899               reveal(box, rightClickString);
92900               context.map().on('move.intro drawn.intro', function () {
92901                 var padding = 60 * Math.pow(2, context.map().zoom() - 18);
92902                 var box = pad(eleventhAvenueEnd, padding, context);
92903                 reveal(box, rightClickString, {
92904                   duration: 0
92905                 });
92906               });
92907               context.on('enter.intro', function (mode) {
92908                 if (mode.id !== 'select') return;
92909                 var ids = context.selectedIDs();
92910                 if (ids.length !== 1 || ids[0] !== eleventhAvenueEndID) return;
92911                 timeout(function () {
92912                   var node = selectMenuItem(context, 'split').node();
92913                   if (!node) return;
92914                   continueTo(splitIntersection);
92915                 }, 50); // after menu visible
92916               });
92917               context.history().on('change.intro', function () {
92918                 timeout(function () {
92919                   continueTo(deleteLines);
92920                 }, 300); // after any transition (e.g. if user deleted intersection)
92921               });
92922             }, 600);
92923
92924             function continueTo(nextStep) {
92925               context.map().on('move.intro drawn.intro', null);
92926               context.on('enter.intro', null);
92927               context.history().on('change.intro', null);
92928               nextStep();
92929             }
92930           }
92931
92932           function splitIntersection() {
92933             if (!context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
92934               return continueTo(deleteLines);
92935             }
92936
92937             var node = selectMenuItem(context, 'split').node();
92938
92939             if (!node) {
92940               return continueTo(rightClickIntersection);
92941             }
92942
92943             var wasChanged = false;
92944             _washingtonSegmentID = null;
92945             reveal('.edit-menu', helpHtml('intro.lines.split_intersection', {
92946               street: _t('intro.graph.name.washington-street')
92947             }), {
92948               padding: 50
92949             });
92950             context.map().on('move.intro drawn.intro', function () {
92951               var node = selectMenuItem(context, 'split').node();
92952
92953               if (!wasChanged && !node) {
92954                 return continueTo(rightClickIntersection);
92955               }
92956
92957               reveal('.edit-menu', helpHtml('intro.lines.split_intersection', {
92958                 street: _t('intro.graph.name.washington-street')
92959               }), {
92960                 duration: 0,
92961                 padding: 50
92962               });
92963             });
92964             context.history().on('change.intro', function (changed) {
92965               wasChanged = true;
92966               timeout(function () {
92967                 if (context.history().undoAnnotation() === _t('operations.split.annotation.line', {
92968                   n: 1
92969                 })) {
92970                   _washingtonSegmentID = changed.created()[0].id;
92971                   continueTo(didSplit);
92972                 } else {
92973                   _washingtonSegmentID = null;
92974                   continueTo(retrySplit);
92975                 }
92976               }, 300); // after any transition (e.g. if user deleted intersection)
92977             });
92978
92979             function continueTo(nextStep) {
92980               context.map().on('move.intro drawn.intro', null);
92981               context.history().on('change.intro', null);
92982               nextStep();
92983             }
92984           }
92985
92986           function retrySplit() {
92987             context.enter(modeBrowse(context));
92988             context.map().centerZoomEase(eleventhAvenueEnd, 18, 500);
92989
92990             var advance = function advance() {
92991               continueTo(rightClickIntersection);
92992             };
92993
92994             var padding = 60 * Math.pow(2, context.map().zoom() - 18);
92995             var box = pad(eleventhAvenueEnd, padding, context);
92996             reveal(box, helpHtml('intro.lines.retry_split'), {
92997               buttonText: _t.html('intro.ok'),
92998               buttonCallback: advance
92999             });
93000             context.map().on('move.intro drawn.intro', function () {
93001               var padding = 60 * Math.pow(2, context.map().zoom() - 18);
93002               var box = pad(eleventhAvenueEnd, padding, context);
93003               reveal(box, helpHtml('intro.lines.retry_split'), {
93004                 duration: 0,
93005                 buttonText: _t.html('intro.ok'),
93006                 buttonCallback: advance
93007               });
93008             });
93009
93010             function continueTo(nextStep) {
93011               context.map().on('move.intro drawn.intro', null);
93012               nextStep();
93013             }
93014           }
93015
93016           function didSplit() {
93017             if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93018               return continueTo(rightClickIntersection);
93019             }
93020
93021             var ids = context.selectedIDs();
93022             var string = 'intro.lines.did_split_' + (ids.length > 1 ? 'multi' : 'single');
93023             var street = _t('intro.graph.name.washington-street');
93024             var padding = 200 * Math.pow(2, context.map().zoom() - 18);
93025             var box = pad(twelfthAvenue, padding, context);
93026             box.width = box.width / 2;
93027             reveal(box, helpHtml(string, {
93028               street1: street,
93029               street2: street
93030             }), {
93031               duration: 500
93032             });
93033             timeout(function () {
93034               context.map().centerZoomEase(twelfthAvenue, 18, 500);
93035               context.map().on('move.intro drawn.intro', function () {
93036                 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
93037                 var box = pad(twelfthAvenue, padding, context);
93038                 box.width = box.width / 2;
93039                 reveal(box, helpHtml(string, {
93040                   street1: street,
93041                   street2: street
93042                 }), {
93043                   duration: 0
93044                 });
93045               });
93046             }, 600); // after initial reveal and curtain cut
93047
93048             context.on('enter.intro', function () {
93049               var ids = context.selectedIDs();
93050
93051               if (ids.length === 1 && ids[0] === _washingtonSegmentID) {
93052                 continueTo(multiSelect);
93053               }
93054             });
93055             context.history().on('change.intro', function () {
93056               if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93057                 return continueTo(rightClickIntersection);
93058               }
93059             });
93060
93061             function continueTo(nextStep) {
93062               context.map().on('move.intro drawn.intro', null);
93063               context.on('enter.intro', null);
93064               context.history().on('change.intro', null);
93065               nextStep();
93066             }
93067           }
93068
93069           function multiSelect() {
93070             if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93071               return continueTo(rightClickIntersection);
93072             }
93073
93074             var ids = context.selectedIDs();
93075             var hasWashington = ids.indexOf(_washingtonSegmentID) !== -1;
93076             var hasTwelfth = ids.indexOf(twelfthAvenueID) !== -1;
93077
93078             if (hasWashington && hasTwelfth) {
93079               return continueTo(multiRightClick);
93080             } else if (!hasWashington && !hasTwelfth) {
93081               return continueTo(didSplit);
93082             }
93083
93084             context.map().centerZoomEase(twelfthAvenue, 18, 500);
93085             timeout(function () {
93086               var selected, other, padding, box;
93087
93088               if (hasWashington) {
93089                 selected = _t('intro.graph.name.washington-street');
93090                 other = _t('intro.graph.name.12th-avenue');
93091                 padding = 60 * Math.pow(2, context.map().zoom() - 18);
93092                 box = pad(twelfthAvenueEnd, padding, context);
93093                 box.width *= 3;
93094               } else {
93095                 selected = _t('intro.graph.name.12th-avenue');
93096                 other = _t('intro.graph.name.washington-street');
93097                 padding = 200 * Math.pow(2, context.map().zoom() - 18);
93098                 box = pad(twelfthAvenue, padding, context);
93099                 box.width /= 2;
93100               }
93101
93102               reveal(box, helpHtml('intro.lines.multi_select', {
93103                 selected: selected,
93104                 other1: other
93105               }) + ' ' + helpHtml('intro.lines.add_to_selection_' + (context.lastPointerType() === 'mouse' ? 'click' : 'touch'), {
93106                 selected: selected,
93107                 other2: other
93108               }));
93109               context.map().on('move.intro drawn.intro', function () {
93110                 if (hasWashington) {
93111                   selected = _t('intro.graph.name.washington-street');
93112                   other = _t('intro.graph.name.12th-avenue');
93113                   padding = 60 * Math.pow(2, context.map().zoom() - 18);
93114                   box = pad(twelfthAvenueEnd, padding, context);
93115                   box.width *= 3;
93116                 } else {
93117                   selected = _t('intro.graph.name.12th-avenue');
93118                   other = _t('intro.graph.name.washington-street');
93119                   padding = 200 * Math.pow(2, context.map().zoom() - 18);
93120                   box = pad(twelfthAvenue, padding, context);
93121                   box.width /= 2;
93122                 }
93123
93124                 reveal(box, helpHtml('intro.lines.multi_select', {
93125                   selected: selected,
93126                   other1: other
93127                 }) + ' ' + helpHtml('intro.lines.add_to_selection_' + (context.lastPointerType() === 'mouse' ? 'click' : 'touch'), {
93128                   selected: selected,
93129                   other2: other
93130                 }), {
93131                   duration: 0
93132                 });
93133               });
93134               context.on('enter.intro', function () {
93135                 continueTo(multiSelect);
93136               });
93137               context.history().on('change.intro', function () {
93138                 if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93139                   return continueTo(rightClickIntersection);
93140                 }
93141               });
93142             }, 600);
93143
93144             function continueTo(nextStep) {
93145               context.map().on('move.intro drawn.intro', null);
93146               context.on('enter.intro', null);
93147               context.history().on('change.intro', null);
93148               nextStep();
93149             }
93150           }
93151
93152           function multiRightClick() {
93153             if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93154               return continueTo(rightClickIntersection);
93155             }
93156
93157             var padding = 200 * Math.pow(2, context.map().zoom() - 18);
93158             var box = pad(twelfthAvenue, padding, context);
93159             var rightClickString = helpHtml('intro.lines.multi_select_success') + helpHtml('intro.lines.multi_' + (context.lastPointerType() === 'mouse' ? 'rightclick' : 'edit_menu_touch'));
93160             reveal(box, rightClickString);
93161             context.map().on('move.intro drawn.intro', function () {
93162               var padding = 200 * Math.pow(2, context.map().zoom() - 18);
93163               var box = pad(twelfthAvenue, padding, context);
93164               reveal(box, rightClickString, {
93165                 duration: 0
93166               });
93167             });
93168             context.ui().editMenu().on('toggled.intro', function (open) {
93169               if (!open) return;
93170               timeout(function () {
93171                 var ids = context.selectedIDs();
93172
93173                 if (ids.length === 2 && ids.indexOf(twelfthAvenueID) !== -1 && ids.indexOf(_washingtonSegmentID) !== -1) {
93174                   var node = selectMenuItem(context, 'delete').node();
93175                   if (!node) return;
93176                   continueTo(multiDelete);
93177                 } else if (ids.length === 1 && ids.indexOf(_washingtonSegmentID) !== -1) {
93178                   return continueTo(multiSelect);
93179                 } else {
93180                   return continueTo(didSplit);
93181                 }
93182               }, 300); // after edit menu visible
93183             });
93184             context.history().on('change.intro', function () {
93185               if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93186                 return continueTo(rightClickIntersection);
93187               }
93188             });
93189
93190             function continueTo(nextStep) {
93191               context.map().on('move.intro drawn.intro', null);
93192               context.ui().editMenu().on('toggled.intro', null);
93193               context.history().on('change.intro', null);
93194               nextStep();
93195             }
93196           }
93197
93198           function multiDelete() {
93199             if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93200               return continueTo(rightClickIntersection);
93201             }
93202
93203             var node = selectMenuItem(context, 'delete').node();
93204             if (!node) return continueTo(multiRightClick);
93205             reveal('.edit-menu', helpHtml('intro.lines.multi_delete'), {
93206               padding: 50
93207             });
93208             context.map().on('move.intro drawn.intro', function () {
93209               reveal('.edit-menu', helpHtml('intro.lines.multi_delete'), {
93210                 duration: 0,
93211                 padding: 50
93212               });
93213             });
93214             context.on('exit.intro', function () {
93215               if (context.hasEntity(_washingtonSegmentID) || context.hasEntity(twelfthAvenueID)) {
93216                 return continueTo(multiSelect); // left select mode but roads still exist
93217               }
93218             });
93219             context.history().on('change.intro', function () {
93220               if (context.hasEntity(_washingtonSegmentID) || context.hasEntity(twelfthAvenueID)) {
93221                 continueTo(retryDelete); // changed something but roads still exist
93222               } else {
93223                 continueTo(play);
93224               }
93225             });
93226
93227             function continueTo(nextStep) {
93228               context.map().on('move.intro drawn.intro', null);
93229               context.on('exit.intro', null);
93230               context.history().on('change.intro', null);
93231               nextStep();
93232             }
93233           }
93234
93235           function retryDelete() {
93236             context.enter(modeBrowse(context));
93237             var padding = 200 * Math.pow(2, context.map().zoom() - 18);
93238             var box = pad(twelfthAvenue, padding, context);
93239             reveal(box, helpHtml('intro.lines.retry_delete'), {
93240               buttonText: _t.html('intro.ok'),
93241               buttonCallback: function buttonCallback() {
93242                 continueTo(multiSelect);
93243               }
93244             });
93245
93246             function continueTo(nextStep) {
93247               nextStep();
93248             }
93249           }
93250
93251           function play() {
93252             dispatch.call('done');
93253             reveal('.ideditor', helpHtml('intro.lines.play', {
93254               next: _t('intro.buildings.title')
93255             }), {
93256               tooltipBox: '.intro-nav-wrap .chapter-building',
93257               buttonText: _t.html('intro.ok'),
93258               buttonCallback: function buttonCallback() {
93259                 reveal('.ideditor');
93260               }
93261             });
93262           }
93263
93264           chapter.enter = function () {
93265             addLine();
93266           };
93267
93268           chapter.exit = function () {
93269             timeouts.forEach(window.clearTimeout);
93270             select(window).on('pointerdown.intro mousedown.intro', null, true);
93271             context.on('enter.intro exit.intro', null);
93272             context.map().on('move.intro drawn.intro', null);
93273             context.history().on('change.intro', null);
93274             context.container().select('.inspector-wrap').on('wheel.intro', null);
93275             context.container().select('.preset-list-button').on('click.intro', null);
93276           };
93277
93278           chapter.restart = function () {
93279             chapter.exit();
93280             chapter.enter();
93281           };
93282
93283           return utilRebind(chapter, dispatch, 'on');
93284         }
93285
93286         function uiIntroBuilding(context, reveal) {
93287           var dispatch = dispatch$8('done');
93288           var house = [-85.62815, 41.95638];
93289           var tank = [-85.62732, 41.95347];
93290           var buildingCatetory = _mainPresetIndex.item('category-building');
93291           var housePreset = _mainPresetIndex.item('building/house');
93292           var tankPreset = _mainPresetIndex.item('man_made/storage_tank');
93293           var timeouts = [];
93294           var _houseID = null;
93295           var _tankID = null;
93296           var chapter = {
93297             title: 'intro.buildings.title'
93298           };
93299
93300           function timeout(f, t) {
93301             timeouts.push(window.setTimeout(f, t));
93302           }
93303
93304           function eventCancel(d3_event) {
93305             d3_event.stopPropagation();
93306             d3_event.preventDefault();
93307           }
93308
93309           function revealHouse(center, text, options) {
93310             var padding = 160 * Math.pow(2, context.map().zoom() - 20);
93311             var box = pad(center, padding, context);
93312             reveal(box, text, options);
93313           }
93314
93315           function revealTank(center, text, options) {
93316             var padding = 190 * Math.pow(2, context.map().zoom() - 19.5);
93317             var box = pad(center, padding, context);
93318             reveal(box, text, options);
93319           }
93320
93321           function addHouse() {
93322             context.enter(modeBrowse(context));
93323             context.history().reset('initial');
93324             _houseID = null;
93325             var msec = transitionTime(house, context.map().center());
93326
93327             if (msec) {
93328               reveal(null, null, {
93329                 duration: 0
93330               });
93331             }
93332
93333             context.map().centerZoomEase(house, 19, msec);
93334             timeout(function () {
93335               var tooltip = reveal('button.add-area', helpHtml('intro.buildings.add_building'));
93336               tooltip.selectAll('.popover-inner').insert('svg', 'span').attr('class', 'tooltip-illustration').append('use').attr('xlink:href', '#iD-graphic-buildings');
93337               context.on('enter.intro', function (mode) {
93338                 if (mode.id !== 'add-area') return;
93339                 continueTo(startHouse);
93340               });
93341             }, msec + 100);
93342
93343             function continueTo(nextStep) {
93344               context.on('enter.intro', null);
93345               nextStep();
93346             }
93347           }
93348
93349           function startHouse() {
93350             if (context.mode().id !== 'add-area') {
93351               return continueTo(addHouse);
93352             }
93353
93354             _houseID = null;
93355             context.map().zoomEase(20, 500);
93356             timeout(function () {
93357               var startString = helpHtml('intro.buildings.start_building') + helpHtml('intro.buildings.building_corner_' + (context.lastPointerType() === 'mouse' ? 'click' : 'tap'));
93358               revealHouse(house, startString);
93359               context.map().on('move.intro drawn.intro', function () {
93360                 revealHouse(house, startString, {
93361                   duration: 0
93362                 });
93363               });
93364               context.on('enter.intro', function (mode) {
93365                 if (mode.id !== 'draw-area') return chapter.restart();
93366                 continueTo(continueHouse);
93367               });
93368             }, 550); // after easing
93369
93370             function continueTo(nextStep) {
93371               context.map().on('move.intro drawn.intro', null);
93372               context.on('enter.intro', null);
93373               nextStep();
93374             }
93375           }
93376
93377           function continueHouse() {
93378             if (context.mode().id !== 'draw-area') {
93379               return continueTo(addHouse);
93380             }
93381
93382             _houseID = null;
93383             var continueString = helpHtml('intro.buildings.continue_building') + '{br}' + helpHtml('intro.areas.finish_area_' + (context.lastPointerType() === 'mouse' ? 'click' : 'tap')) + helpHtml('intro.buildings.finish_building');
93384             revealHouse(house, continueString);
93385             context.map().on('move.intro drawn.intro', function () {
93386               revealHouse(house, continueString, {
93387                 duration: 0
93388               });
93389             });
93390             context.on('enter.intro', function (mode) {
93391               if (mode.id === 'draw-area') {
93392                 return;
93393               } else if (mode.id === 'select') {
93394                 var graph = context.graph();
93395                 var way = context.entity(context.selectedIDs()[0]);
93396                 var nodes = graph.childNodes(way);
93397                 var points = utilArrayUniq(nodes).map(function (n) {
93398                   return context.projection(n.loc);
93399                 });
93400
93401                 if (isMostlySquare(points)) {
93402                   _houseID = way.id;
93403                   return continueTo(chooseCategoryBuilding);
93404                 } else {
93405                   return continueTo(retryHouse);
93406                 }
93407               } else {
93408                 return chapter.restart();
93409               }
93410             });
93411
93412             function continueTo(nextStep) {
93413               context.map().on('move.intro drawn.intro', null);
93414               context.on('enter.intro', null);
93415               nextStep();
93416             }
93417           }
93418
93419           function retryHouse() {
93420             var onClick = function onClick() {
93421               continueTo(addHouse);
93422             };
93423
93424             revealHouse(house, helpHtml('intro.buildings.retry_building'), {
93425               buttonText: _t.html('intro.ok'),
93426               buttonCallback: onClick
93427             });
93428             context.map().on('move.intro drawn.intro', function () {
93429               revealHouse(house, helpHtml('intro.buildings.retry_building'), {
93430                 duration: 0,
93431                 buttonText: _t.html('intro.ok'),
93432                 buttonCallback: onClick
93433               });
93434             });
93435
93436             function continueTo(nextStep) {
93437               context.map().on('move.intro drawn.intro', null);
93438               nextStep();
93439             }
93440           }
93441
93442           function chooseCategoryBuilding() {
93443             if (!_houseID || !context.hasEntity(_houseID)) {
93444               return addHouse();
93445             }
93446
93447             var ids = context.selectedIDs();
93448
93449             if (context.mode().id !== 'select' || !ids.length || ids[0] !== _houseID) {
93450               context.enter(modeSelect(context, [_houseID]));
93451             } // disallow scrolling
93452
93453
93454             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
93455             timeout(function () {
93456               // reset pane, in case user somehow happened to change it..
93457               context.container().select('.inspector-wrap .panewrap').style('right', '-100%');
93458               var button = context.container().select('.preset-category-building .preset-list-button');
93459               reveal(button.node(), helpHtml('intro.buildings.choose_category_building', {
93460                 category: buildingCatetory.name()
93461               }));
93462               button.on('click.intro', function () {
93463                 button.on('click.intro', null);
93464                 continueTo(choosePresetHouse);
93465               });
93466             }, 400); // after preset list pane visible..
93467
93468             context.on('enter.intro', function (mode) {
93469               if (!_houseID || !context.hasEntity(_houseID)) {
93470                 return continueTo(addHouse);
93471               }
93472
93473               var ids = context.selectedIDs();
93474
93475               if (mode.id !== 'select' || !ids.length || ids[0] !== _houseID) {
93476                 return continueTo(chooseCategoryBuilding);
93477               }
93478             });
93479
93480             function continueTo(nextStep) {
93481               context.container().select('.inspector-wrap').on('wheel.intro', null);
93482               context.container().select('.preset-list-button').on('click.intro', null);
93483               context.on('enter.intro', null);
93484               nextStep();
93485             }
93486           }
93487
93488           function choosePresetHouse() {
93489             if (!_houseID || !context.hasEntity(_houseID)) {
93490               return addHouse();
93491             }
93492
93493             var ids = context.selectedIDs();
93494
93495             if (context.mode().id !== 'select' || !ids.length || ids[0] !== _houseID) {
93496               context.enter(modeSelect(context, [_houseID]));
93497             } // disallow scrolling
93498
93499
93500             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
93501             timeout(function () {
93502               // reset pane, in case user somehow happened to change it..
93503               context.container().select('.inspector-wrap .panewrap').style('right', '-100%');
93504               var button = context.container().select('.preset-building-house .preset-list-button');
93505               reveal(button.node(), helpHtml('intro.buildings.choose_preset_house', {
93506                 preset: housePreset.name()
93507               }), {
93508                 duration: 300
93509               });
93510               button.on('click.intro', function () {
93511                 button.on('click.intro', null);
93512                 continueTo(closeEditorHouse);
93513               });
93514             }, 400); // after preset list pane visible..
93515
93516             context.on('enter.intro', function (mode) {
93517               if (!_houseID || !context.hasEntity(_houseID)) {
93518                 return continueTo(addHouse);
93519               }
93520
93521               var ids = context.selectedIDs();
93522
93523               if (mode.id !== 'select' || !ids.length || ids[0] !== _houseID) {
93524                 return continueTo(chooseCategoryBuilding);
93525               }
93526             });
93527
93528             function continueTo(nextStep) {
93529               context.container().select('.inspector-wrap').on('wheel.intro', null);
93530               context.container().select('.preset-list-button').on('click.intro', null);
93531               context.on('enter.intro', null);
93532               nextStep();
93533             }
93534           }
93535
93536           function closeEditorHouse() {
93537             if (!_houseID || !context.hasEntity(_houseID)) {
93538               return addHouse();
93539             }
93540
93541             var ids = context.selectedIDs();
93542
93543             if (context.mode().id !== 'select' || !ids.length || ids[0] !== _houseID) {
93544               context.enter(modeSelect(context, [_houseID]));
93545             }
93546
93547             context.history().checkpoint('hasHouse');
93548             context.on('exit.intro', function () {
93549               continueTo(rightClickHouse);
93550             });
93551             timeout(function () {
93552               reveal('.entity-editor-pane', helpHtml('intro.buildings.close', {
93553                 button: {
93554                   html: icon('#iD-icon-close', 'inline')
93555                 }
93556               }));
93557             }, 500);
93558
93559             function continueTo(nextStep) {
93560               context.on('exit.intro', null);
93561               nextStep();
93562             }
93563           }
93564
93565           function rightClickHouse() {
93566             if (!_houseID) return chapter.restart();
93567             context.enter(modeBrowse(context));
93568             context.history().reset('hasHouse');
93569             var zoom = context.map().zoom();
93570
93571             if (zoom < 20) {
93572               zoom = 20;
93573             }
93574
93575             context.map().centerZoomEase(house, zoom, 500);
93576             context.on('enter.intro', function (mode) {
93577               if (mode.id !== 'select') return;
93578               var ids = context.selectedIDs();
93579               if (ids.length !== 1 || ids[0] !== _houseID) return;
93580               timeout(function () {
93581                 var node = selectMenuItem(context, 'orthogonalize').node();
93582                 if (!node) return;
93583                 continueTo(clickSquare);
93584               }, 50); // after menu visible
93585             });
93586             context.map().on('move.intro drawn.intro', function () {
93587               var rightclickString = helpHtml('intro.buildings.' + (context.lastPointerType() === 'mouse' ? 'rightclick_building' : 'edit_menu_building_touch'));
93588               revealHouse(house, rightclickString, {
93589                 duration: 0
93590               });
93591             });
93592             context.history().on('change.intro', function () {
93593               continueTo(rightClickHouse);
93594             });
93595
93596             function continueTo(nextStep) {
93597               context.on('enter.intro', null);
93598               context.map().on('move.intro drawn.intro', null);
93599               context.history().on('change.intro', null);
93600               nextStep();
93601             }
93602           }
93603
93604           function clickSquare() {
93605             if (!_houseID) return chapter.restart();
93606             var entity = context.hasEntity(_houseID);
93607             if (!entity) return continueTo(rightClickHouse);
93608             var node = selectMenuItem(context, 'orthogonalize').node();
93609
93610             if (!node) {
93611               return continueTo(rightClickHouse);
93612             }
93613
93614             var wasChanged = false;
93615             reveal('.edit-menu', helpHtml('intro.buildings.square_building'), {
93616               padding: 50
93617             });
93618             context.on('enter.intro', function (mode) {
93619               if (mode.id === 'browse') {
93620                 continueTo(rightClickHouse);
93621               } else if (mode.id === 'move' || mode.id === 'rotate') {
93622                 continueTo(retryClickSquare);
93623               }
93624             });
93625             context.map().on('move.intro', function () {
93626               var node = selectMenuItem(context, 'orthogonalize').node();
93627
93628               if (!wasChanged && !node) {
93629                 return continueTo(rightClickHouse);
93630               }
93631
93632               reveal('.edit-menu', helpHtml('intro.buildings.square_building'), {
93633                 duration: 0,
93634                 padding: 50
93635               });
93636             });
93637             context.history().on('change.intro', function () {
93638               wasChanged = true;
93639               context.history().on('change.intro', null); // Something changed.  Wait for transition to complete and check undo annotation.
93640
93641               timeout(function () {
93642                 if (context.history().undoAnnotation() === _t('operations.orthogonalize.annotation.feature', {
93643                   n: 1
93644                 })) {
93645                   continueTo(doneSquare);
93646                 } else {
93647                   continueTo(retryClickSquare);
93648                 }
93649               }, 500); // after transitioned actions
93650             });
93651
93652             function continueTo(nextStep) {
93653               context.on('enter.intro', null);
93654               context.map().on('move.intro', null);
93655               context.history().on('change.intro', null);
93656               nextStep();
93657             }
93658           }
93659
93660           function retryClickSquare() {
93661             context.enter(modeBrowse(context));
93662             revealHouse(house, helpHtml('intro.buildings.retry_square'), {
93663               buttonText: _t.html('intro.ok'),
93664               buttonCallback: function buttonCallback() {
93665                 continueTo(rightClickHouse);
93666               }
93667             });
93668
93669             function continueTo(nextStep) {
93670               nextStep();
93671             }
93672           }
93673
93674           function doneSquare() {
93675             context.history().checkpoint('doneSquare');
93676             revealHouse(house, helpHtml('intro.buildings.done_square'), {
93677               buttonText: _t.html('intro.ok'),
93678               buttonCallback: function buttonCallback() {
93679                 continueTo(addTank);
93680               }
93681             });
93682
93683             function continueTo(nextStep) {
93684               nextStep();
93685             }
93686           }
93687
93688           function addTank() {
93689             context.enter(modeBrowse(context));
93690             context.history().reset('doneSquare');
93691             _tankID = null;
93692             var msec = transitionTime(tank, context.map().center());
93693
93694             if (msec) {
93695               reveal(null, null, {
93696                 duration: 0
93697               });
93698             }
93699
93700             context.map().centerZoomEase(tank, 19.5, msec);
93701             timeout(function () {
93702               reveal('button.add-area', helpHtml('intro.buildings.add_tank'));
93703               context.on('enter.intro', function (mode) {
93704                 if (mode.id !== 'add-area') return;
93705                 continueTo(startTank);
93706               });
93707             }, msec + 100);
93708
93709             function continueTo(nextStep) {
93710               context.on('enter.intro', null);
93711               nextStep();
93712             }
93713           }
93714
93715           function startTank() {
93716             if (context.mode().id !== 'add-area') {
93717               return continueTo(addTank);
93718             }
93719
93720             _tankID = null;
93721             timeout(function () {
93722               var startString = helpHtml('intro.buildings.start_tank') + helpHtml('intro.buildings.tank_edge_' + (context.lastPointerType() === 'mouse' ? 'click' : 'tap'));
93723               revealTank(tank, startString);
93724               context.map().on('move.intro drawn.intro', function () {
93725                 revealTank(tank, startString, {
93726                   duration: 0
93727                 });
93728               });
93729               context.on('enter.intro', function (mode) {
93730                 if (mode.id !== 'draw-area') return chapter.restart();
93731                 continueTo(continueTank);
93732               });
93733             }, 550); // after easing
93734
93735             function continueTo(nextStep) {
93736               context.map().on('move.intro drawn.intro', null);
93737               context.on('enter.intro', null);
93738               nextStep();
93739             }
93740           }
93741
93742           function continueTank() {
93743             if (context.mode().id !== 'draw-area') {
93744               return continueTo(addTank);
93745             }
93746
93747             _tankID = null;
93748             var continueString = helpHtml('intro.buildings.continue_tank') + '{br}' + helpHtml('intro.areas.finish_area_' + (context.lastPointerType() === 'mouse' ? 'click' : 'tap')) + helpHtml('intro.buildings.finish_tank');
93749             revealTank(tank, continueString);
93750             context.map().on('move.intro drawn.intro', function () {
93751               revealTank(tank, continueString, {
93752                 duration: 0
93753               });
93754             });
93755             context.on('enter.intro', function (mode) {
93756               if (mode.id === 'draw-area') {
93757                 return;
93758               } else if (mode.id === 'select') {
93759                 _tankID = context.selectedIDs()[0];
93760                 return continueTo(searchPresetTank);
93761               } else {
93762                 return continueTo(addTank);
93763               }
93764             });
93765
93766             function continueTo(nextStep) {
93767               context.map().on('move.intro drawn.intro', null);
93768               context.on('enter.intro', null);
93769               nextStep();
93770             }
93771           }
93772
93773           function searchPresetTank() {
93774             if (!_tankID || !context.hasEntity(_tankID)) {
93775               return addTank();
93776             }
93777
93778             var ids = context.selectedIDs();
93779
93780             if (context.mode().id !== 'select' || !ids.length || ids[0] !== _tankID) {
93781               context.enter(modeSelect(context, [_tankID]));
93782             } // disallow scrolling
93783
93784
93785             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
93786             timeout(function () {
93787               // reset pane, in case user somehow happened to change it..
93788               context.container().select('.inspector-wrap .panewrap').style('right', '-100%');
93789               context.container().select('.preset-search-input').on('keydown.intro', null).on('keyup.intro', checkPresetSearch);
93790               reveal('.preset-search-input', helpHtml('intro.buildings.search_tank', {
93791                 preset: tankPreset.name()
93792               }));
93793             }, 400); // after preset list pane visible..
93794
93795             context.on('enter.intro', function (mode) {
93796               if (!_tankID || !context.hasEntity(_tankID)) {
93797                 return continueTo(addTank);
93798               }
93799
93800               var ids = context.selectedIDs();
93801
93802               if (mode.id !== 'select' || !ids.length || ids[0] !== _tankID) {
93803                 // keep the user's area selected..
93804                 context.enter(modeSelect(context, [_tankID])); // reset pane, in case user somehow happened to change it..
93805
93806                 context.container().select('.inspector-wrap .panewrap').style('right', '-100%'); // disallow scrolling
93807
93808                 context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
93809                 context.container().select('.preset-search-input').on('keydown.intro', null).on('keyup.intro', checkPresetSearch);
93810                 reveal('.preset-search-input', helpHtml('intro.buildings.search_tank', {
93811                   preset: tankPreset.name()
93812                 }));
93813                 context.history().on('change.intro', null);
93814               }
93815             });
93816
93817             function checkPresetSearch() {
93818               var first = context.container().select('.preset-list-item:first-child');
93819
93820               if (first.classed('preset-man_made-storage_tank')) {
93821                 reveal(first.select('.preset-list-button').node(), helpHtml('intro.buildings.choose_tank', {
93822                   preset: tankPreset.name()
93823                 }), {
93824                   duration: 300
93825                 });
93826                 context.container().select('.preset-search-input').on('keydown.intro', eventCancel, true).on('keyup.intro', null);
93827                 context.history().on('change.intro', function () {
93828                   continueTo(closeEditorTank);
93829                 });
93830               }
93831             }
93832
93833             function continueTo(nextStep) {
93834               context.container().select('.inspector-wrap').on('wheel.intro', null);
93835               context.on('enter.intro', null);
93836               context.history().on('change.intro', null);
93837               context.container().select('.preset-search-input').on('keydown.intro keyup.intro', null);
93838               nextStep();
93839             }
93840           }
93841
93842           function closeEditorTank() {
93843             if (!_tankID || !context.hasEntity(_tankID)) {
93844               return addTank();
93845             }
93846
93847             var ids = context.selectedIDs();
93848
93849             if (context.mode().id !== 'select' || !ids.length || ids[0] !== _tankID) {
93850               context.enter(modeSelect(context, [_tankID]));
93851             }
93852
93853             context.history().checkpoint('hasTank');
93854             context.on('exit.intro', function () {
93855               continueTo(rightClickTank);
93856             });
93857             timeout(function () {
93858               reveal('.entity-editor-pane', helpHtml('intro.buildings.close', {
93859                 button: {
93860                   html: icon('#iD-icon-close', 'inline')
93861                 }
93862               }));
93863             }, 500);
93864
93865             function continueTo(nextStep) {
93866               context.on('exit.intro', null);
93867               nextStep();
93868             }
93869           }
93870
93871           function rightClickTank() {
93872             if (!_tankID) return continueTo(addTank);
93873             context.enter(modeBrowse(context));
93874             context.history().reset('hasTank');
93875             context.map().centerEase(tank, 500);
93876             timeout(function () {
93877               context.on('enter.intro', function (mode) {
93878                 if (mode.id !== 'select') return;
93879                 var ids = context.selectedIDs();
93880                 if (ids.length !== 1 || ids[0] !== _tankID) return;
93881                 timeout(function () {
93882                   var node = selectMenuItem(context, 'circularize').node();
93883                   if (!node) return;
93884                   continueTo(clickCircle);
93885                 }, 50); // after menu visible
93886               });
93887               var rightclickString = helpHtml('intro.buildings.' + (context.lastPointerType() === 'mouse' ? 'rightclick_tank' : 'edit_menu_tank_touch'));
93888               revealTank(tank, rightclickString);
93889               context.map().on('move.intro drawn.intro', function () {
93890                 revealTank(tank, rightclickString, {
93891                   duration: 0
93892                 });
93893               });
93894               context.history().on('change.intro', function () {
93895                 continueTo(rightClickTank);
93896               });
93897             }, 600);
93898
93899             function continueTo(nextStep) {
93900               context.on('enter.intro', null);
93901               context.map().on('move.intro drawn.intro', null);
93902               context.history().on('change.intro', null);
93903               nextStep();
93904             }
93905           }
93906
93907           function clickCircle() {
93908             if (!_tankID) return chapter.restart();
93909             var entity = context.hasEntity(_tankID);
93910             if (!entity) return continueTo(rightClickTank);
93911             var node = selectMenuItem(context, 'circularize').node();
93912
93913             if (!node) {
93914               return continueTo(rightClickTank);
93915             }
93916
93917             var wasChanged = false;
93918             reveal('.edit-menu', helpHtml('intro.buildings.circle_tank'), {
93919               padding: 50
93920             });
93921             context.on('enter.intro', function (mode) {
93922               if (mode.id === 'browse') {
93923                 continueTo(rightClickTank);
93924               } else if (mode.id === 'move' || mode.id === 'rotate') {
93925                 continueTo(retryClickCircle);
93926               }
93927             });
93928             context.map().on('move.intro', function () {
93929               var node = selectMenuItem(context, 'circularize').node();
93930
93931               if (!wasChanged && !node) {
93932                 return continueTo(rightClickTank);
93933               }
93934
93935               reveal('.edit-menu', helpHtml('intro.buildings.circle_tank'), {
93936                 duration: 0,
93937                 padding: 50
93938               });
93939             });
93940             context.history().on('change.intro', function () {
93941               wasChanged = true;
93942               context.history().on('change.intro', null); // Something changed.  Wait for transition to complete and check undo annotation.
93943
93944               timeout(function () {
93945                 if (context.history().undoAnnotation() === _t('operations.circularize.annotation.feature', {
93946                   n: 1
93947                 })) {
93948                   continueTo(play);
93949                 } else {
93950                   continueTo(retryClickCircle);
93951                 }
93952               }, 500); // after transitioned actions
93953             });
93954
93955             function continueTo(nextStep) {
93956               context.on('enter.intro', null);
93957               context.map().on('move.intro', null);
93958               context.history().on('change.intro', null);
93959               nextStep();
93960             }
93961           }
93962
93963           function retryClickCircle() {
93964             context.enter(modeBrowse(context));
93965             revealTank(tank, helpHtml('intro.buildings.retry_circle'), {
93966               buttonText: _t.html('intro.ok'),
93967               buttonCallback: function buttonCallback() {
93968                 continueTo(rightClickTank);
93969               }
93970             });
93971
93972             function continueTo(nextStep) {
93973               nextStep();
93974             }
93975           }
93976
93977           function play() {
93978             dispatch.call('done');
93979             reveal('.ideditor', helpHtml('intro.buildings.play', {
93980               next: _t('intro.startediting.title')
93981             }), {
93982               tooltipBox: '.intro-nav-wrap .chapter-startEditing',
93983               buttonText: _t.html('intro.ok'),
93984               buttonCallback: function buttonCallback() {
93985                 reveal('.ideditor');
93986               }
93987             });
93988           }
93989
93990           chapter.enter = function () {
93991             addHouse();
93992           };
93993
93994           chapter.exit = function () {
93995             timeouts.forEach(window.clearTimeout);
93996             context.on('enter.intro exit.intro', null);
93997             context.map().on('move.intro drawn.intro', null);
93998             context.history().on('change.intro', null);
93999             context.container().select('.inspector-wrap').on('wheel.intro', null);
94000             context.container().select('.preset-search-input').on('keydown.intro keyup.intro', null);
94001             context.container().select('.more-fields .combobox-input').on('click.intro', null);
94002           };
94003
94004           chapter.restart = function () {
94005             chapter.exit();
94006             chapter.enter();
94007           };
94008
94009           return utilRebind(chapter, dispatch, 'on');
94010         }
94011
94012         function uiIntroStartEditing(context, reveal) {
94013           var dispatch = dispatch$8('done', 'startEditing');
94014           var modalSelection = select(null);
94015           var chapter = {
94016             title: 'intro.startediting.title'
94017           };
94018
94019           function showHelp() {
94020             reveal('.map-control.help-control', helpHtml('intro.startediting.help'), {
94021               buttonText: _t.html('intro.ok'),
94022               buttonCallback: function buttonCallback() {
94023                 shortcuts();
94024               }
94025             });
94026           }
94027
94028           function shortcuts() {
94029             reveal('.map-control.help-control', helpHtml('intro.startediting.shortcuts'), {
94030               buttonText: _t.html('intro.ok'),
94031               buttonCallback: function buttonCallback() {
94032                 showSave();
94033               }
94034             });
94035           }
94036
94037           function showSave() {
94038             context.container().selectAll('.shaded').remove(); // in case user opened keyboard shortcuts
94039
94040             reveal('.top-toolbar button.save', helpHtml('intro.startediting.save'), {
94041               buttonText: _t.html('intro.ok'),
94042               buttonCallback: function buttonCallback() {
94043                 showStart();
94044               }
94045             });
94046           }
94047
94048           function showStart() {
94049             context.container().selectAll('.shaded').remove(); // in case user opened keyboard shortcuts
94050
94051             modalSelection = uiModal(context.container());
94052             modalSelection.select('.modal').attr('class', 'modal-splash modal');
94053             modalSelection.selectAll('.close').remove();
94054             var startbutton = modalSelection.select('.content').attr('class', 'fillL').append('button').attr('class', 'modal-section huge-modal-button').on('click', function () {
94055               modalSelection.remove();
94056             });
94057             startbutton.append('svg').attr('class', 'illustration').append('use').attr('xlink:href', '#iD-logo-walkthrough');
94058             startbutton.append('h2').call(_t.append('intro.startediting.start'));
94059             dispatch.call('startEditing');
94060           }
94061
94062           chapter.enter = function () {
94063             showHelp();
94064           };
94065
94066           chapter.exit = function () {
94067             modalSelection.remove();
94068             context.container().selectAll('.shaded').remove(); // in case user opened keyboard shortcuts
94069           };
94070
94071           return utilRebind(chapter, dispatch, 'on');
94072         }
94073
94074         var chapterUi = {
94075           welcome: uiIntroWelcome,
94076           navigation: uiIntroNavigation,
94077           point: uiIntroPoint,
94078           area: uiIntroArea,
94079           line: uiIntroLine,
94080           building: uiIntroBuilding,
94081           startEditing: uiIntroStartEditing
94082         };
94083         var chapterFlow = ['welcome', 'navigation', 'point', 'area', 'line', 'building', 'startEditing'];
94084         function uiIntro(context) {
94085           var INTRO_IMAGERY = 'EsriWorldImageryClarity';
94086           var _introGraph = {};
94087
94088           var _currChapter;
94089
94090           function intro(selection) {
94091             _mainFileFetcher.get('intro_graph').then(function (dataIntroGraph) {
94092               // create entities for intro graph and localize names
94093               for (var id in dataIntroGraph) {
94094                 if (!_introGraph[id]) {
94095                   _introGraph[id] = osmEntity(localize(dataIntroGraph[id]));
94096                 }
94097               }
94098
94099               selection.call(startIntro);
94100             })["catch"](function () {
94101               /* ignore */
94102             });
94103           }
94104
94105           function startIntro(selection) {
94106             context.enter(modeBrowse(context)); // Save current map state
94107
94108             var osm = context.connection();
94109             var history = context.history().toJSON();
94110             var hash = window.location.hash;
94111             var center = context.map().center();
94112             var zoom = context.map().zoom();
94113             var background = context.background().baseLayerSource();
94114             var overlays = context.background().overlayLayerSources();
94115             var opacity = context.container().selectAll('.main-map .layer-background').style('opacity');
94116             var caches = osm && osm.caches();
94117             var baseEntities = context.history().graph().base().entities; // Show sidebar and disable the sidebar resizing button
94118             // (this needs to be before `context.inIntro(true)`)
94119
94120             context.ui().sidebar.expand();
94121             context.container().selectAll('button.sidebar-toggle').classed('disabled', true); // Block saving
94122
94123             context.inIntro(true); // Load semi-real data used in intro
94124
94125             if (osm) {
94126               osm.toggle(false).reset();
94127             }
94128
94129             context.history().reset();
94130             context.history().merge(Object.values(coreGraph().load(_introGraph).entities));
94131             context.history().checkpoint('initial'); // Setup imagery
94132
94133             var imagery = context.background().findSource(INTRO_IMAGERY);
94134
94135             if (imagery) {
94136               context.background().baseLayerSource(imagery);
94137             } else {
94138               context.background().bing();
94139             }
94140
94141             overlays.forEach(function (d) {
94142               return context.background().toggleOverlayLayer(d);
94143             }); // Setup data layers (only OSM)
94144
94145             var layers = context.layers();
94146             layers.all().forEach(function (item) {
94147               // if the layer has the function `enabled`
94148               if (typeof item.layer.enabled === 'function') {
94149                 item.layer.enabled(item.id === 'osm');
94150               }
94151             });
94152             context.container().selectAll('.main-map .layer-background').style('opacity', 1);
94153             var curtain = uiCurtain(context.container().node());
94154             selection.call(curtain); // Store that the user started the walkthrough..
94155
94156             corePreferences('walkthrough_started', 'yes'); // Restore previous walkthrough progress..
94157
94158             var storedProgress = corePreferences('walkthrough_progress') || '';
94159             var progress = storedProgress.split(';').filter(Boolean);
94160             var chapters = chapterFlow.map(function (chapter, i) {
94161               var s = chapterUi[chapter](context, curtain.reveal).on('done', function () {
94162                 buttons.filter(function (d) {
94163                   return d.title === s.title;
94164                 }).classed('finished', true);
94165
94166                 if (i < chapterFlow.length - 1) {
94167                   var next = chapterFlow[i + 1];
94168                   context.container().select("button.chapter-".concat(next)).classed('next', true);
94169                 } // Store walkthrough progress..
94170
94171
94172                 progress.push(chapter);
94173                 corePreferences('walkthrough_progress', utilArrayUniq(progress).join(';'));
94174               });
94175               return s;
94176             });
94177             chapters[chapters.length - 1].on('startEditing', function () {
94178               // Store walkthrough progress..
94179               progress.push('startEditing');
94180               corePreferences('walkthrough_progress', utilArrayUniq(progress).join(';')); // Store if walkthrough is completed..
94181
94182               var incomplete = utilArrayDifference(chapterFlow, progress);
94183
94184               if (!incomplete.length) {
94185                 corePreferences('walkthrough_completed', 'yes');
94186               }
94187
94188               curtain.remove();
94189               navwrap.remove();
94190               context.container().selectAll('.main-map .layer-background').style('opacity', opacity);
94191               context.container().selectAll('button.sidebar-toggle').classed('disabled', false);
94192
94193               if (osm) {
94194                 osm.toggle(true).reset().caches(caches);
94195               }
94196
94197               context.history().reset().merge(Object.values(baseEntities));
94198               context.background().baseLayerSource(background);
94199               overlays.forEach(function (d) {
94200                 return context.background().toggleOverlayLayer(d);
94201               });
94202
94203               if (history) {
94204                 context.history().fromJSON(history, false);
94205               }
94206
94207               context.map().centerZoom(center, zoom);
94208               window.location.replace(hash);
94209               context.inIntro(false);
94210             });
94211             var navwrap = selection.append('div').attr('class', 'intro-nav-wrap fillD');
94212             navwrap.append('svg').attr('class', 'intro-nav-wrap-logo').append('use').attr('xlink:href', '#iD-logo-walkthrough');
94213             var buttonwrap = navwrap.append('div').attr('class', 'joined').selectAll('button.chapter');
94214             var buttons = buttonwrap.data(chapters).enter().append('button').attr('class', function (d, i) {
94215               return "chapter chapter-".concat(chapterFlow[i]);
94216             }).on('click', enterChapter);
94217             buttons.append('span').html(function (d) {
94218               return _t.html(d.title);
94219             });
94220             buttons.append('span').attr('class', 'status').call(svgIcon(_mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-backward' : '#iD-icon-forward', 'inline'));
94221             enterChapter(null, chapters[0]);
94222
94223             function enterChapter(d3_event, newChapter) {
94224               if (_currChapter) {
94225                 _currChapter.exit();
94226               }
94227
94228               context.enter(modeBrowse(context));
94229               _currChapter = newChapter;
94230
94231               _currChapter.enter();
94232
94233               buttons.classed('next', false).classed('active', function (d) {
94234                 return d.title === _currChapter.title;
94235               });
94236             }
94237           }
94238
94239           return intro;
94240         }
94241
94242         function uiIssuesInfo(context) {
94243           var warningsItem = {
94244             id: 'warnings',
94245             count: 0,
94246             iconID: 'iD-icon-alert',
94247             descriptionID: 'issues.warnings_and_errors'
94248           };
94249           var resolvedItem = {
94250             id: 'resolved',
94251             count: 0,
94252             iconID: 'iD-icon-apply',
94253             descriptionID: 'issues.user_resolved_issues'
94254           };
94255
94256           function update(selection) {
94257             var shownItems = [];
94258             var liveIssues = context.validator().getIssues({
94259               what: corePreferences('validate-what') || 'edited',
94260               where: corePreferences('validate-where') || 'all'
94261             });
94262
94263             if (liveIssues.length) {
94264               warningsItem.count = liveIssues.length;
94265               shownItems.push(warningsItem);
94266             }
94267
94268             if (corePreferences('validate-what') === 'all') {
94269               var resolvedIssues = context.validator().getResolvedIssues();
94270
94271               if (resolvedIssues.length) {
94272                 resolvedItem.count = resolvedIssues.length;
94273                 shownItems.push(resolvedItem);
94274               }
94275             }
94276
94277             var chips = selection.selectAll('.chip').data(shownItems, function (d) {
94278               return d.id;
94279             });
94280             chips.exit().remove();
94281             var enter = chips.enter().append('a').attr('class', function (d) {
94282               return 'chip ' + d.id + '-count';
94283             }).attr('href', '#').each(function (d) {
94284               var chipSelection = select(this);
94285               var tooltipBehavior = uiTooltip().placement('top').title(_t.html(d.descriptionID));
94286               chipSelection.call(tooltipBehavior).on('click', function (d3_event) {
94287                 d3_event.preventDefault();
94288                 tooltipBehavior.hide(select(this)); // open the Issues pane
94289
94290                 context.ui().togglePanes(context.container().select('.map-panes .issues-pane'));
94291               });
94292               chipSelection.call(svgIcon('#' + d.iconID));
94293             });
94294             enter.append('span').attr('class', 'count');
94295             enter.merge(chips).selectAll('span.count').text(function (d) {
94296               return d.count.toString();
94297             });
94298           }
94299
94300           return function (selection) {
94301             update(selection);
94302             context.validator().on('validated.infobox', function () {
94303               update(selection);
94304             });
94305           };
94306         }
94307
94308         function uiMapInMap(context) {
94309           function mapInMap(selection) {
94310             var backgroundLayer = rendererTileLayer(context);
94311             var overlayLayers = {};
94312             var projection = geoRawMercator();
94313             var dataLayer = svgData(projection, context).showLabels(false);
94314             var debugLayer = svgDebug(projection, context);
94315             var zoom = d3_zoom().scaleExtent([geoZoomToScale(0.5), geoZoomToScale(24)]).on('start', zoomStarted).on('zoom', zoomed).on('end', zoomEnded);
94316             var wrap = select(null);
94317             var tiles = select(null);
94318             var viewport = select(null);
94319             var _isTransformed = false;
94320             var _isHidden = true;
94321             var _skipEvents = false;
94322             var _gesture = null;
94323             var _zDiff = 6; // by default, minimap renders at (main zoom - 6)
94324
94325             var _dMini; // dimensions of minimap
94326
94327
94328             var _cMini; // center pixel of minimap
94329
94330
94331             var _tStart; // transform at start of gesture
94332
94333
94334             var _tCurr; // transform at most recent event
94335
94336
94337             var _timeoutID;
94338
94339             function zoomStarted() {
94340               if (_skipEvents) return;
94341               _tStart = _tCurr = projection.transform();
94342               _gesture = null;
94343             }
94344
94345             function zoomed(d3_event) {
94346               if (_skipEvents) return;
94347               var x = d3_event.transform.x;
94348               var y = d3_event.transform.y;
94349               var k = d3_event.transform.k;
94350               var isZooming = k !== _tStart.k;
94351               var isPanning = x !== _tStart.x || y !== _tStart.y;
94352
94353               if (!isZooming && !isPanning) {
94354                 return; // no change
94355               } // lock in either zooming or panning, don't allow both in minimap.
94356
94357
94358               if (!_gesture) {
94359                 _gesture = isZooming ? 'zoom' : 'pan';
94360               }
94361
94362               var tMini = projection.transform();
94363               var tX, tY, scale;
94364
94365               if (_gesture === 'zoom') {
94366                 scale = k / tMini.k;
94367                 tX = (_cMini[0] / scale - _cMini[0]) * scale;
94368                 tY = (_cMini[1] / scale - _cMini[1]) * scale;
94369               } else {
94370                 k = tMini.k;
94371                 scale = 1;
94372                 tX = x - tMini.x;
94373                 tY = y - tMini.y;
94374               }
94375
94376               utilSetTransform(tiles, tX, tY, scale);
94377               utilSetTransform(viewport, 0, 0, scale);
94378               _isTransformed = true;
94379               _tCurr = identity$2.translate(x, y).scale(k);
94380               var zMain = geoScaleToZoom(context.projection.scale());
94381               var zMini = geoScaleToZoom(k);
94382               _zDiff = zMain - zMini;
94383               queueRedraw();
94384             }
94385
94386             function zoomEnded() {
94387               if (_skipEvents) return;
94388               if (_gesture !== 'pan') return;
94389               updateProjection();
94390               _gesture = null;
94391               context.map().center(projection.invert(_cMini)); // recenter main map..
94392             }
94393
94394             function updateProjection() {
94395               var loc = context.map().center();
94396               var tMain = context.projection.transform();
94397               var zMain = geoScaleToZoom(tMain.k);
94398               var zMini = Math.max(zMain - _zDiff, 0.5);
94399               var kMini = geoZoomToScale(zMini);
94400               projection.translate([tMain.x, tMain.y]).scale(kMini);
94401               var point = projection(loc);
94402               var mouse = _gesture === 'pan' ? geoVecSubtract([_tCurr.x, _tCurr.y], [_tStart.x, _tStart.y]) : [0, 0];
94403               var xMini = _cMini[0] - point[0] + tMain.x + mouse[0];
94404               var yMini = _cMini[1] - point[1] + tMain.y + mouse[1];
94405               projection.translate([xMini, yMini]).clipExtent([[0, 0], _dMini]);
94406               _tCurr = projection.transform();
94407
94408               if (_isTransformed) {
94409                 utilSetTransform(tiles, 0, 0);
94410                 utilSetTransform(viewport, 0, 0);
94411                 _isTransformed = false;
94412               }
94413
94414               zoom.scaleExtent([geoZoomToScale(0.5), geoZoomToScale(zMain - 3)]);
94415               _skipEvents = true;
94416               wrap.call(zoom.transform, _tCurr);
94417               _skipEvents = false;
94418             }
94419
94420             function redraw() {
94421               clearTimeout(_timeoutID);
94422               if (_isHidden) return;
94423               updateProjection();
94424               var zMini = geoScaleToZoom(projection.scale()); // setup tile container
94425
94426               tiles = wrap.selectAll('.map-in-map-tiles').data([0]);
94427               tiles = tiles.enter().append('div').attr('class', 'map-in-map-tiles').merge(tiles); // redraw background
94428
94429               backgroundLayer.source(context.background().baseLayerSource()).projection(projection).dimensions(_dMini);
94430               var background = tiles.selectAll('.map-in-map-background').data([0]);
94431               background.enter().append('div').attr('class', 'map-in-map-background').merge(background).call(backgroundLayer); // redraw overlay
94432
94433               var overlaySources = context.background().overlayLayerSources();
94434               var activeOverlayLayers = [];
94435
94436               for (var i = 0; i < overlaySources.length; i++) {
94437                 if (overlaySources[i].validZoom(zMini)) {
94438                   if (!overlayLayers[i]) overlayLayers[i] = rendererTileLayer(context);
94439                   activeOverlayLayers.push(overlayLayers[i].source(overlaySources[i]).projection(projection).dimensions(_dMini));
94440                 }
94441               }
94442
94443               var overlay = tiles.selectAll('.map-in-map-overlay').data([0]);
94444               overlay = overlay.enter().append('div').attr('class', 'map-in-map-overlay').merge(overlay);
94445               var overlays = overlay.selectAll('div').data(activeOverlayLayers, function (d) {
94446                 return d.source().name();
94447               });
94448               overlays.exit().remove();
94449               overlays = overlays.enter().append('div').merge(overlays).each(function (layer) {
94450                 select(this).call(layer);
94451               });
94452               var dataLayers = tiles.selectAll('.map-in-map-data').data([0]);
94453               dataLayers.exit().remove();
94454               dataLayers = dataLayers.enter().append('svg').attr('class', 'map-in-map-data').merge(dataLayers).call(dataLayer).call(debugLayer); // redraw viewport bounding box
94455
94456               if (_gesture !== 'pan') {
94457                 var getPath = d3_geoPath(projection);
94458                 var bbox = {
94459                   type: 'Polygon',
94460                   coordinates: [context.map().extent().polygon()]
94461                 };
94462                 viewport = wrap.selectAll('.map-in-map-viewport').data([0]);
94463                 viewport = viewport.enter().append('svg').attr('class', 'map-in-map-viewport').merge(viewport);
94464                 var path = viewport.selectAll('.map-in-map-bbox').data([bbox]);
94465                 path.enter().append('path').attr('class', 'map-in-map-bbox').merge(path).attr('d', getPath).classed('thick', function (d) {
94466                   return getPath.area(d) < 30;
94467                 });
94468               }
94469             }
94470
94471             function queueRedraw() {
94472               clearTimeout(_timeoutID);
94473               _timeoutID = setTimeout(function () {
94474                 redraw();
94475               }, 750);
94476             }
94477
94478             function toggle(d3_event) {
94479               if (d3_event) d3_event.preventDefault();
94480               _isHidden = !_isHidden;
94481               context.container().select('.minimap-toggle-item').classed('active', !_isHidden).select('input').property('checked', !_isHidden);
94482
94483               if (_isHidden) {
94484                 wrap.style('display', 'block').style('opacity', '1').transition().duration(200).style('opacity', '0').on('end', function () {
94485                   selection.selectAll('.map-in-map').style('display', 'none');
94486                 });
94487               } else {
94488                 wrap.style('display', 'block').style('opacity', '0').transition().duration(200).style('opacity', '1').on('end', function () {
94489                   redraw();
94490                 });
94491               }
94492             }
94493
94494             uiMapInMap.toggle = toggle;
94495             wrap = selection.selectAll('.map-in-map').data([0]);
94496             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..
94497
94498             _dMini = [200, 150]; //utilGetDimensions(wrap);
94499
94500             _cMini = geoVecScale(_dMini, 0.5);
94501             context.map().on('drawn.map-in-map', function (drawn) {
94502               if (drawn.full === true) {
94503                 redraw();
94504               }
94505             });
94506             redraw();
94507             context.keybinding().on(_t('background.minimap.key'), toggle);
94508           }
94509
94510           return mapInMap;
94511         }
94512
94513         function uiNotice(context) {
94514           return function (selection) {
94515             var div = selection.append('div').attr('class', 'notice');
94516             var button = div.append('button').attr('class', 'zoom-to notice fillD').on('click', function () {
94517               context.map().zoomEase(context.minEditableZoom());
94518             }).on('wheel', function (d3_event) {
94519               // let wheel events pass through #4482
94520               var e2 = new WheelEvent(d3_event.type, d3_event);
94521               context.surface().node().dispatchEvent(e2);
94522             });
94523             button.call(svgIcon('#iD-icon-plus', 'pre-text')).append('span').attr('class', 'label').call(_t.append('zoom_in_edit'));
94524
94525             function disableTooHigh() {
94526               var canEdit = context.map().zoom() >= context.minEditableZoom();
94527               div.style('display', canEdit ? 'none' : 'block');
94528             }
94529
94530             context.map().on('move.notice', debounce(disableTooHigh, 500));
94531             disableTooHigh();
94532           };
94533         }
94534
94535         function uiPhotoviewer(context) {
94536           var dispatch = dispatch$8('resize');
94537
94538           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
94539
94540           function photoviewer(selection) {
94541             selection.append('button').attr('class', 'thumb-hide').attr('title', _t('icons.close')).on('click', function () {
94542               if (services.streetside) {
94543                 services.streetside.hideViewer(context);
94544               }
94545
94546               if (services.mapillary) {
94547                 services.mapillary.hideViewer(context);
94548               }
94549
94550               if (services.kartaview) {
94551                 services.kartaview.hideViewer(context);
94552               }
94553             }).append('div').call(svgIcon('#iD-icon-close'));
94554
94555             function preventDefault(d3_event) {
94556               d3_event.preventDefault();
94557             }
94558
94559             selection.append('button').attr('class', 'resize-handle-xy').on('touchstart touchdown touchend', preventDefault).on(_pointerPrefix + 'down', buildResizeListener(selection, 'resize', dispatch, {
94560               resizeOnX: true,
94561               resizeOnY: true
94562             }));
94563             selection.append('button').attr('class', 'resize-handle-x').on('touchstart touchdown touchend', preventDefault).on(_pointerPrefix + 'down', buildResizeListener(selection, 'resize', dispatch, {
94564               resizeOnX: true
94565             }));
94566             selection.append('button').attr('class', 'resize-handle-y').on('touchstart touchdown touchend', preventDefault).on(_pointerPrefix + 'down', buildResizeListener(selection, 'resize', dispatch, {
94567               resizeOnY: true
94568             }));
94569
94570             function buildResizeListener(target, eventName, dispatch, options) {
94571               var resizeOnX = !!options.resizeOnX;
94572               var resizeOnY = !!options.resizeOnY;
94573               var minHeight = options.minHeight || 240;
94574               var minWidth = options.minWidth || 320;
94575               var pointerId;
94576               var startX;
94577               var startY;
94578               var startWidth;
94579               var startHeight;
94580
94581               function startResize(d3_event) {
94582                 if (pointerId !== (d3_event.pointerId || 'mouse')) return;
94583                 d3_event.preventDefault();
94584                 d3_event.stopPropagation();
94585                 var mapSize = context.map().dimensions();
94586
94587                 if (resizeOnX) {
94588                   var maxWidth = mapSize[0];
94589                   var newWidth = clamp(startWidth + d3_event.clientX - startX, minWidth, maxWidth);
94590                   target.style('width', newWidth + 'px');
94591                 }
94592
94593                 if (resizeOnY) {
94594                   var maxHeight = mapSize[1] - 90; // preserve space at top/bottom of map
94595
94596                   var newHeight = clamp(startHeight + startY - d3_event.clientY, minHeight, maxHeight);
94597                   target.style('height', newHeight + 'px');
94598                 }
94599
94600                 dispatch.call(eventName, target, utilGetDimensions(target, true));
94601               }
94602
94603               function clamp(num, min, max) {
94604                 return Math.max(min, Math.min(num, max));
94605               }
94606
94607               function stopResize(d3_event) {
94608                 if (pointerId !== (d3_event.pointerId || 'mouse')) return;
94609                 d3_event.preventDefault();
94610                 d3_event.stopPropagation(); // remove all the listeners we added
94611
94612                 select(window).on('.' + eventName, null);
94613               }
94614
94615               return function initResize(d3_event) {
94616                 d3_event.preventDefault();
94617                 d3_event.stopPropagation();
94618                 pointerId = d3_event.pointerId || 'mouse';
94619                 startX = d3_event.clientX;
94620                 startY = d3_event.clientY;
94621                 var targetRect = target.node().getBoundingClientRect();
94622                 startWidth = targetRect.width;
94623                 startHeight = targetRect.height;
94624                 select(window).on(_pointerPrefix + 'move.' + eventName, startResize, false).on(_pointerPrefix + 'up.' + eventName, stopResize, false);
94625
94626                 if (_pointerPrefix === 'pointer') {
94627                   select(window).on('pointercancel.' + eventName, stopResize, false);
94628                 }
94629               };
94630             }
94631           }
94632
94633           photoviewer.onMapResize = function () {
94634             var photoviewer = context.container().select('.photoviewer');
94635             var content = context.container().select('.main-content');
94636             var mapDimensions = utilGetDimensions(content, true); // shrink photo viewer if it is too big
94637             // (-90 preserves space at top and bottom of map used by menus)
94638
94639             var photoDimensions = utilGetDimensions(photoviewer, true);
94640
94641             if (photoDimensions[0] > mapDimensions[0] || photoDimensions[1] > mapDimensions[1] - 90) {
94642               var setPhotoDimensions = [Math.min(photoDimensions[0], mapDimensions[0]), Math.min(photoDimensions[1], mapDimensions[1] - 90)];
94643               photoviewer.style('width', setPhotoDimensions[0] + 'px').style('height', setPhotoDimensions[1] + 'px');
94644               dispatch.call('resize', photoviewer, setPhotoDimensions);
94645             }
94646           };
94647
94648           return utilRebind(photoviewer, dispatch, 'on');
94649         }
94650
94651         function uiRestore(context) {
94652           return function (selection) {
94653             if (!context.history().hasRestorableChanges()) return;
94654             var modalSelection = uiModal(selection, true);
94655             modalSelection.select('.modal').attr('class', 'modal fillL');
94656             var introModal = modalSelection.select('.content');
94657             introModal.append('div').attr('class', 'modal-section').append('h3').call(_t.append('restore.heading'));
94658             introModal.append('div').attr('class', 'modal-section').append('p').call(_t.append('restore.description'));
94659             var buttonWrap = introModal.append('div').attr('class', 'modal-actions');
94660             var restore = buttonWrap.append('button').attr('class', 'restore').on('click', function () {
94661               context.history().restore();
94662               modalSelection.remove();
94663             });
94664             restore.append('svg').attr('class', 'logo logo-restore').append('use').attr('xlink:href', '#iD-logo-restore');
94665             restore.append('div').call(_t.append('restore.restore'));
94666             var reset = buttonWrap.append('button').attr('class', 'reset').on('click', function () {
94667               context.history().clearSaved();
94668               modalSelection.remove();
94669             });
94670             reset.append('svg').attr('class', 'logo logo-reset').append('use').attr('xlink:href', '#iD-logo-reset');
94671             reset.append('div').call(_t.append('restore.reset'));
94672             restore.node().focus();
94673           };
94674         }
94675
94676         function uiScale(context) {
94677           var projection = context.projection,
94678               isImperial = !_mainLocalizer.usesMetric(),
94679               maxLength = 180,
94680               tickHeight = 8;
94681
94682           function scaleDefs(loc1, loc2) {
94683             var lat = (loc2[1] + loc1[1]) / 2,
94684                 conversion = isImperial ? 3.28084 : 1,
94685                 dist = geoLonToMeters(loc2[0] - loc1[0], lat) * conversion,
94686                 scale = {
94687               dist: 0,
94688               px: 0,
94689               text: ''
94690             },
94691                 buckets,
94692                 i,
94693                 val,
94694                 dLon;
94695
94696             if (isImperial) {
94697               buckets = [5280000, 528000, 52800, 5280, 500, 50, 5, 1];
94698             } else {
94699               buckets = [5000000, 500000, 50000, 5000, 500, 50, 5, 1];
94700             } // determine a user-friendly endpoint for the scale
94701
94702
94703             for (i = 0; i < buckets.length; i++) {
94704               val = buckets[i];
94705
94706               if (dist >= val) {
94707                 scale.dist = Math.floor(dist / val) * val;
94708                 break;
94709               } else {
94710                 scale.dist = +dist.toFixed(2);
94711               }
94712             }
94713
94714             dLon = geoMetersToLon(scale.dist / conversion, lat);
94715             scale.px = Math.round(projection([loc1[0] + dLon, loc1[1]])[0]);
94716             scale.text = displayLength(scale.dist / conversion, isImperial);
94717             return scale;
94718           }
94719
94720           function update(selection) {
94721             // choose loc1, loc2 along bottom of viewport (near where the scale will be drawn)
94722             var dims = context.map().dimensions(),
94723                 loc1 = projection.invert([0, dims[1]]),
94724                 loc2 = projection.invert([maxLength, dims[1]]),
94725                 scale = scaleDefs(loc1, loc2);
94726             selection.select('.scale-path').attr('d', 'M0.5,0.5v' + tickHeight + 'h' + scale.px + 'v-' + tickHeight);
94727             selection.select('.scale-text').style(_mainLocalizer.textDirection() === 'ltr' ? 'left' : 'right', scale.px + 16 + 'px').text(scale.text);
94728           }
94729
94730           return function (selection) {
94731             function switchUnits() {
94732               isImperial = !isImperial;
94733               selection.call(update);
94734             }
94735
94736             var scalegroup = selection.append('svg').attr('class', 'scale').on('click', switchUnits).append('g').attr('transform', 'translate(10,11)');
94737             scalegroup.append('path').attr('class', 'scale-path');
94738             selection.append('div').attr('class', 'scale-text');
94739             selection.call(update);
94740             context.map().on('move.scale', function () {
94741               update(selection);
94742             });
94743           };
94744         }
94745
94746         function uiShortcuts(context) {
94747           var detected = utilDetect();
94748           var _activeTab = 0;
94749
94750           var _modalSelection;
94751
94752           var _selection = select(null);
94753
94754           var _dataShortcuts;
94755
94756           function shortcutsModal(_modalSelection) {
94757             _modalSelection.select('.modal').classed('modal-shortcuts', true);
94758
94759             var content = _modalSelection.select('.content');
94760
94761             content.append('div').attr('class', 'modal-section header').append('h2').call(_t.append('shortcuts.title'));
94762             _mainFileFetcher.get('shortcuts').then(function (data) {
94763               _dataShortcuts = data;
94764               content.call(render);
94765             })["catch"](function () {
94766               /* ignore */
94767             });
94768           }
94769
94770           function render(selection) {
94771             if (!_dataShortcuts) return;
94772             var wrapper = selection.selectAll('.wrapper').data([0]);
94773             var wrapperEnter = wrapper.enter().append('div').attr('class', 'wrapper modal-section');
94774             var tabsBar = wrapperEnter.append('div').attr('class', 'tabs-bar');
94775             var shortcutsList = wrapperEnter.append('div').attr('class', 'shortcuts-list');
94776             wrapper = wrapper.merge(wrapperEnter);
94777             var tabs = tabsBar.selectAll('.tab').data(_dataShortcuts);
94778             var tabsEnter = tabs.enter().append('a').attr('class', 'tab').attr('href', '#').on('click', function (d3_event, d) {
94779               d3_event.preventDefault();
94780
94781               var i = _dataShortcuts.indexOf(d);
94782
94783               _activeTab = i;
94784               render(selection);
94785             });
94786             tabsEnter.append('span').html(function (d) {
94787               return _t.html(d.text);
94788             }); // Update
94789
94790             wrapper.selectAll('.tab').classed('active', function (d, i) {
94791               return i === _activeTab;
94792             });
94793             var shortcuts = shortcutsList.selectAll('.shortcut-tab').data(_dataShortcuts);
94794             var shortcutsEnter = shortcuts.enter().append('div').attr('class', function (d) {
94795               return 'shortcut-tab shortcut-tab-' + d.tab;
94796             });
94797             var columnsEnter = shortcutsEnter.selectAll('.shortcut-column').data(function (d) {
94798               return d.columns;
94799             }).enter().append('table').attr('class', 'shortcut-column');
94800             var rowsEnter = columnsEnter.selectAll('.shortcut-row').data(function (d) {
94801               return d.rows;
94802             }).enter().append('tr').attr('class', 'shortcut-row');
94803             var sectionRows = rowsEnter.filter(function (d) {
94804               return !d.shortcuts;
94805             });
94806             sectionRows.append('td');
94807             sectionRows.append('td').attr('class', 'shortcut-section').append('h3').html(function (d) {
94808               return _t.html(d.text);
94809             });
94810             var shortcutRows = rowsEnter.filter(function (d) {
94811               return d.shortcuts;
94812             });
94813             var shortcutKeys = shortcutRows.append('td').attr('class', 'shortcut-keys');
94814             var modifierKeys = shortcutKeys.filter(function (d) {
94815               return d.modifiers;
94816             });
94817             modifierKeys.selectAll('kbd.modifier').data(function (d) {
94818               if (detected.os === 'win' && d.text === 'shortcuts.editing.commands.redo') {
94819                 return ['⌘'];
94820               } else if (detected.os !== 'mac' && d.text === 'shortcuts.browsing.display_options.fullscreen') {
94821                 return [];
94822               } else {
94823                 return d.modifiers;
94824               }
94825             }).enter().each(function () {
94826               var selection = select(this);
94827               selection.append('kbd').attr('class', 'modifier').text(function (d) {
94828                 return uiCmd.display(d);
94829               });
94830               selection.append('span').text('+');
94831             });
94832             shortcutKeys.selectAll('kbd.shortcut').data(function (d) {
94833               var arr = d.shortcuts;
94834
94835               if (detected.os === 'win' && d.text === 'shortcuts.editing.commands.redo') {
94836                 arr = ['Y'];
94837               } else if (detected.os !== 'mac' && d.text === 'shortcuts.browsing.display_options.fullscreen') {
94838                 arr = ['F11'];
94839               } // replace translations
94840
94841
94842               arr = arr.map(function (s) {
94843                 return uiCmd.display(s.indexOf('.') !== -1 ? _t(s) : s);
94844               });
94845               return utilArrayUniq(arr).map(function (s) {
94846                 return {
94847                   shortcut: s,
94848                   separator: d.separator,
94849                   suffix: d.suffix
94850                 };
94851               });
94852             }).enter().each(function (d, i, nodes) {
94853               var selection = select(this);
94854               var click = d.shortcut.toLowerCase().match(/(.*).click/);
94855
94856               if (click && click[1]) {
94857                 // replace "left_click", "right_click" with mouse icon
94858                 selection.call(svgIcon('#iD-walkthrough-mouse-' + click[1], 'operation'));
94859               } else if (d.shortcut.toLowerCase() === 'long-press') {
94860                 selection.call(svgIcon('#iD-walkthrough-longpress', 'longpress operation'));
94861               } else if (d.shortcut.toLowerCase() === 'tap') {
94862                 selection.call(svgIcon('#iD-walkthrough-tap', 'tap operation'));
94863               } else {
94864                 selection.append('kbd').attr('class', 'shortcut').text(function (d) {
94865                   return d.shortcut;
94866                 });
94867               }
94868
94869               if (i < nodes.length - 1) {
94870                 selection.append('span').html(d.separator || "\xA0" + _t.html('shortcuts.or') + "\xA0");
94871               } else if (i === nodes.length - 1 && d.suffix) {
94872                 selection.append('span').text(d.suffix);
94873               }
94874             });
94875             shortcutKeys.filter(function (d) {
94876               return d.gesture;
94877             }).each(function () {
94878               var selection = select(this);
94879               selection.append('span').text('+');
94880               selection.append('span').attr('class', 'gesture').html(function (d) {
94881                 return _t.html(d.gesture);
94882               });
94883             });
94884             shortcutRows.append('td').attr('class', 'shortcut-desc').html(function (d) {
94885               return d.text ? _t.html(d.text) : "\xA0";
94886             }); // Update
94887
94888             wrapper.selectAll('.shortcut-tab').style('display', function (d, i) {
94889               return i === _activeTab ? 'flex' : 'none';
94890             });
94891           }
94892
94893           return function (selection, show) {
94894             _selection = selection;
94895
94896             if (show) {
94897               _modalSelection = uiModal(selection);
94898
94899               _modalSelection.call(shortcutsModal);
94900             } else {
94901               context.keybinding().on([_t('shortcuts.toggle.key'), '?'], function () {
94902                 if (context.container().selectAll('.modal-shortcuts').size()) {
94903                   // already showing
94904                   if (_modalSelection) {
94905                     _modalSelection.close();
94906
94907                     _modalSelection = null;
94908                   }
94909                 } else {
94910                   _modalSelection = uiModal(_selection);
94911
94912                   _modalSelection.call(shortcutsModal);
94913                 }
94914               });
94915             }
94916           };
94917         }
94918
94919         function uiDataHeader() {
94920           var _datum;
94921
94922           function dataHeader(selection) {
94923             var header = selection.selectAll('.data-header').data(_datum ? [_datum] : [], function (d) {
94924               return d.__featurehash__;
94925             });
94926             header.exit().remove();
94927             var headerEnter = header.enter().append('div').attr('class', 'data-header');
94928             var iconEnter = headerEnter.append('div').attr('class', 'data-header-icon');
94929             iconEnter.append('div').attr('class', 'preset-icon-28').call(svgIcon('#iD-icon-data', 'note-fill'));
94930             headerEnter.append('div').attr('class', 'data-header-label').call(_t.append('map_data.layers.custom.title'));
94931           }
94932
94933           dataHeader.datum = function (val) {
94934             if (!arguments.length) return _datum;
94935             _datum = val;
94936             return this;
94937           };
94938
94939           return dataHeader;
94940         }
94941
94942         // It is keyed on the `value` of the entry. Data should be an array of objects like:
94943         //   [{
94944         //       value:   'string value',  // required
94945         //       display: 'label html'     // optional
94946         //       title:   'hover text'     // optional
94947         //       terms:   ['search terms'] // optional
94948         //   }, ...]
94949
94950         var _comboHideTimerID;
94951
94952         function uiCombobox(context, klass) {
94953           var dispatch = dispatch$8('accept', 'cancel');
94954           var container = context.container();
94955           var _suggestions = [];
94956           var _data = [];
94957           var _fetched = {};
94958           var _selected = null;
94959           var _canAutocomplete = true;
94960           var _caseSensitive = false;
94961           var _cancelFetch = false;
94962           var _minItems = 2;
94963           var _tDown = 0;
94964
94965           var _mouseEnterHandler, _mouseLeaveHandler;
94966
94967           var _fetcher = function _fetcher(val, cb) {
94968             cb(_data.filter(function (d) {
94969               var terms = d.terms || [];
94970               terms.push(d.value);
94971               return terms.some(function (term) {
94972                 return term.toString().toLowerCase().indexOf(val.toLowerCase()) !== -1;
94973               });
94974             }));
94975           };
94976
94977           var combobox = function combobox(input, attachTo) {
94978             if (!input || input.empty()) return;
94979             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 () {
94980               var parent = this.parentNode;
94981               var sibling = this.nextSibling;
94982               select(parent).selectAll('.combobox-caret').filter(function (d) {
94983                 return d === input.node();
94984               }).data([input.node()]).enter().insert('div', function () {
94985                 return sibling;
94986               }).attr('class', 'combobox-caret').on('mousedown.combo-caret', function (d3_event) {
94987                 d3_event.preventDefault(); // don't steal focus from input
94988
94989                 input.node().focus(); // focus the input as if it was clicked
94990
94991                 mousedown(d3_event);
94992               }).on('mouseup.combo-caret', function (d3_event) {
94993                 d3_event.preventDefault(); // don't steal focus from input
94994
94995                 mouseup(d3_event);
94996               });
94997             });
94998
94999             function mousedown(d3_event) {
95000               if (d3_event.button !== 0) return; // left click only
95001
95002               if (input.classed('disabled')) return;
95003               _tDown = +new Date(); // clear selection
95004
95005               var start = input.property('selectionStart');
95006               var end = input.property('selectionEnd');
95007
95008               if (start !== end) {
95009                 var val = utilGetSetValue(input);
95010                 input.node().setSelectionRange(val.length, val.length);
95011                 return;
95012               }
95013
95014               input.on('mouseup.combo-input', mouseup);
95015             }
95016
95017             function mouseup(d3_event) {
95018               input.on('mouseup.combo-input', null);
95019               if (d3_event.button !== 0) return; // left click only
95020
95021               if (input.classed('disabled')) return;
95022               if (input.node() !== document.activeElement) return; // exit if this input is not focused
95023
95024               var start = input.property('selectionStart');
95025               var end = input.property('selectionEnd');
95026               if (start !== end) return; // exit if user is selecting
95027               // not showing or showing for a different field - try to show it.
95028
95029               var combo = container.selectAll('.combobox');
95030
95031               if (combo.empty() || combo.datum() !== input.node()) {
95032                 var tOrig = _tDown;
95033                 window.setTimeout(function () {
95034                   if (tOrig !== _tDown) return; // exit if user double clicked
95035
95036                   fetchComboData('', function () {
95037                     show();
95038                     render();
95039                   });
95040                 }, 250);
95041               } else {
95042                 hide();
95043               }
95044             }
95045
95046             function focus() {
95047               fetchComboData(''); // prefetch values (may warm taginfo cache)
95048             }
95049
95050             function blur() {
95051               _comboHideTimerID = window.setTimeout(hide, 75);
95052             }
95053
95054             function show() {
95055               hide(); // remove any existing
95056
95057               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) {
95058                 // prevent moving focus out of the input field
95059                 d3_event.preventDefault();
95060               });
95061               container.on('scroll.combo-scroll', render, true);
95062             }
95063
95064             function hide() {
95065               if (_comboHideTimerID) {
95066                 window.clearTimeout(_comboHideTimerID);
95067                 _comboHideTimerID = undefined;
95068               }
95069
95070               container.selectAll('.combobox').remove();
95071               container.on('scroll.combo-scroll', null);
95072             }
95073
95074             function keydown(d3_event) {
95075               var shown = !container.selectAll('.combobox').empty();
95076               var tagName = input.node() ? input.node().tagName.toLowerCase() : '';
95077
95078               switch (d3_event.keyCode) {
95079                 case 8: // ⌫ Backspace
95080
95081                 case 46:
95082                   // ⌦ Delete
95083                   d3_event.stopPropagation();
95084                   _selected = null;
95085                   render();
95086                   input.on('input.combo-input', function () {
95087                     var start = input.property('selectionStart');
95088                     input.node().setSelectionRange(start, start);
95089                     input.on('input.combo-input', change);
95090                   });
95091                   break;
95092
95093                 case 9:
95094                   // ⇥ Tab
95095                   accept();
95096                   break;
95097
95098                 case 13:
95099                   // ↩ Return
95100                   d3_event.preventDefault();
95101                   d3_event.stopPropagation();
95102                   break;
95103
95104                 case 38:
95105                   // ↑ Up arrow
95106                   if (tagName === 'textarea' && !shown) return;
95107                   d3_event.preventDefault();
95108
95109                   if (tagName === 'input' && !shown) {
95110                     show();
95111                   }
95112
95113                   nav(-1);
95114                   break;
95115
95116                 case 40:
95117                   // ↓ Down arrow
95118                   if (tagName === 'textarea' && !shown) return;
95119                   d3_event.preventDefault();
95120
95121                   if (tagName === 'input' && !shown) {
95122                     show();
95123                   }
95124
95125                   nav(+1);
95126                   break;
95127               }
95128             }
95129
95130             function keyup(d3_event) {
95131               switch (d3_event.keyCode) {
95132                 case 27:
95133                   // ⎋ Escape
95134                   cancel();
95135                   break;
95136
95137                 case 13:
95138                   // ↩ Return
95139                   accept();
95140                   break;
95141               }
95142             } // Called whenever the input value is changed (e.g. on typing)
95143
95144
95145             function change() {
95146               fetchComboData(value(), function () {
95147                 _selected = null;
95148                 var val = input.property('value');
95149
95150                 if (_suggestions.length) {
95151                   if (input.property('selectionEnd') === val.length) {
95152                     _selected = tryAutocomplete();
95153                   }
95154
95155                   if (!_selected) {
95156                     _selected = val;
95157                   }
95158                 }
95159
95160                 if (val.length) {
95161                   var combo = container.selectAll('.combobox');
95162
95163                   if (combo.empty()) {
95164                     show();
95165                   }
95166                 } else {
95167                   hide();
95168                 }
95169
95170                 render();
95171               });
95172             } // Called when the user presses up/down arrows to navigate the list
95173
95174
95175             function nav(dir) {
95176               if (_suggestions.length) {
95177                 // try to determine previously selected index..
95178                 var index = -1;
95179
95180                 for (var i = 0; i < _suggestions.length; i++) {
95181                   if (_selected && _suggestions[i].value === _selected) {
95182                     index = i;
95183                     break;
95184                   }
95185                 } // pick new _selected
95186
95187
95188                 index = Math.max(Math.min(index + dir, _suggestions.length - 1), 0);
95189                 _selected = _suggestions[index].value;
95190                 input.property('value', _selected);
95191               }
95192
95193               render();
95194               ensureVisible();
95195             }
95196
95197             function ensureVisible() {
95198               var combo = container.selectAll('.combobox');
95199               if (combo.empty()) return;
95200               var containerRect = container.node().getBoundingClientRect();
95201               var comboRect = combo.node().getBoundingClientRect();
95202
95203               if (comboRect.bottom > containerRect.bottom) {
95204                 var node = attachTo ? attachTo.node() : input.node();
95205                 node.scrollIntoView({
95206                   behavior: 'instant',
95207                   block: 'center'
95208                 });
95209                 render();
95210               } // https://stackoverflow.com/questions/11039885/scrollintoview-causing-the-whole-page-to-move
95211
95212
95213               var selected = combo.selectAll('.combobox-option.selected').node();
95214
95215               if (selected) {
95216                 selected.scrollIntoView({
95217                   behavior: 'smooth',
95218                   block: 'nearest'
95219                 });
95220               }
95221             }
95222
95223             function value() {
95224               var value = input.property('value');
95225               var start = input.property('selectionStart');
95226               var end = input.property('selectionEnd');
95227
95228               if (start && end) {
95229                 value = value.substring(0, start);
95230               }
95231
95232               return value;
95233             }
95234
95235             function fetchComboData(v, cb) {
95236               _cancelFetch = false;
95237
95238               _fetcher.call(input, v, function (results) {
95239                 // already chose a value, don't overwrite or autocomplete it
95240                 if (_cancelFetch) return;
95241                 _suggestions = results;
95242                 results.forEach(function (d) {
95243                   _fetched[d.value] = d;
95244                 });
95245
95246                 if (cb) {
95247                   cb();
95248                 }
95249               });
95250             }
95251
95252             function tryAutocomplete() {
95253               if (!_canAutocomplete) return;
95254               var val = _caseSensitive ? value() : value().toLowerCase();
95255               if (!val) return; // Don't autocomplete if user is typing a number - #4935
95256
95257               if (!isNaN(parseFloat(val)) && isFinite(val)) return;
95258               var bestIndex = -1;
95259
95260               for (var i = 0; i < _suggestions.length; i++) {
95261                 var suggestion = _suggestions[i].value;
95262                 var compare = _caseSensitive ? suggestion : suggestion.toLowerCase(); // if search string matches suggestion exactly, pick it..
95263
95264                 if (compare === val) {
95265                   bestIndex = i;
95266                   break; // otherwise lock in the first result that starts with the search string..
95267                 } else if (bestIndex === -1 && compare.indexOf(val) === 0) {
95268                   bestIndex = i;
95269                 }
95270               }
95271
95272               if (bestIndex !== -1) {
95273                 var bestVal = _suggestions[bestIndex].value;
95274                 input.property('value', bestVal);
95275                 input.node().setSelectionRange(val.length, bestVal.length);
95276                 return bestVal;
95277               }
95278             }
95279
95280             function render() {
95281               if (_suggestions.length < _minItems || document.activeElement !== input.node()) {
95282                 hide();
95283                 return;
95284               }
95285
95286               var shown = !container.selectAll('.combobox').empty();
95287               if (!shown) return;
95288               var combo = container.selectAll('.combobox');
95289               var options = combo.selectAll('.combobox-option').data(_suggestions, function (d) {
95290                 return d.value;
95291               });
95292               options.exit().remove(); // enter/update
95293
95294               options.enter().append('a').attr('class', function (d) {
95295                 return 'combobox-option ' + (d.klass || '');
95296               }).attr('title', function (d) {
95297                 return d.title;
95298               }).html(function (d) {
95299                 return d.display || d.value;
95300               }).on('mouseenter', _mouseEnterHandler).on('mouseleave', _mouseLeaveHandler).merge(options).classed('selected', function (d) {
95301                 return d.value === _selected;
95302               }).on('click.combo-option', accept).order();
95303               var node = attachTo ? attachTo.node() : input.node();
95304               var containerRect = container.node().getBoundingClientRect();
95305               var rect = node.getBoundingClientRect();
95306               combo.style('left', rect.left + 5 - containerRect.left + 'px').style('width', rect.width - 10 + 'px').style('top', rect.height + rect.top - containerRect.top + 'px');
95307             } // Dispatches an 'accept' event
95308             // Then hides the combobox.
95309
95310
95311             function accept(d3_event, d) {
95312               _cancelFetch = true;
95313               var thiz = input.node();
95314
95315               if (d) {
95316                 // user clicked on a suggestion
95317                 utilGetSetValue(input, d.value); // replace field contents
95318
95319                 utilTriggerEvent(input, 'change');
95320               } // clear (and keep) selection
95321
95322
95323               var val = utilGetSetValue(input);
95324               thiz.setSelectionRange(val.length, val.length);
95325               d = _fetched[val];
95326               dispatch.call('accept', thiz, d, val);
95327               hide();
95328             } // Dispatches an 'cancel' event
95329             // Then hides the combobox.
95330
95331
95332             function cancel() {
95333               _cancelFetch = true;
95334               var thiz = input.node(); // clear (and remove) selection, and replace field contents
95335
95336               var val = utilGetSetValue(input);
95337               var start = input.property('selectionStart');
95338               var end = input.property('selectionEnd');
95339               val = val.slice(0, start) + val.slice(end);
95340               utilGetSetValue(input, val);
95341               thiz.setSelectionRange(val.length, val.length);
95342               dispatch.call('cancel', thiz);
95343               hide();
95344             }
95345           };
95346
95347           combobox.canAutocomplete = function (val) {
95348             if (!arguments.length) return _canAutocomplete;
95349             _canAutocomplete = val;
95350             return combobox;
95351           };
95352
95353           combobox.caseSensitive = function (val) {
95354             if (!arguments.length) return _caseSensitive;
95355             _caseSensitive = val;
95356             return combobox;
95357           };
95358
95359           combobox.data = function (val) {
95360             if (!arguments.length) return _data;
95361             _data = val;
95362             return combobox;
95363           };
95364
95365           combobox.fetcher = function (val) {
95366             if (!arguments.length) return _fetcher;
95367             _fetcher = val;
95368             return combobox;
95369           };
95370
95371           combobox.minItems = function (val) {
95372             if (!arguments.length) return _minItems;
95373             _minItems = val;
95374             return combobox;
95375           };
95376
95377           combobox.itemsMouseEnter = function (val) {
95378             if (!arguments.length) return _mouseEnterHandler;
95379             _mouseEnterHandler = val;
95380             return combobox;
95381           };
95382
95383           combobox.itemsMouseLeave = function (val) {
95384             if (!arguments.length) return _mouseLeaveHandler;
95385             _mouseLeaveHandler = val;
95386             return combobox;
95387           };
95388
95389           return utilRebind(combobox, dispatch, 'on');
95390         }
95391
95392         uiCombobox.off = function (input, context) {
95393           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);
95394           context.container().on('scroll.combo-scroll', null);
95395         };
95396
95397         function uiDisclosure(context, key, expandedDefault) {
95398           var dispatch = dispatch$8('toggled');
95399
95400           var _expanded;
95401
95402           var _label = utilFunctor('');
95403
95404           var _updatePreference = true;
95405
95406           var _content = function _content() {};
95407
95408           var disclosure = function disclosure(selection) {
95409             if (_expanded === undefined || _expanded === null) {
95410               // loading _expanded here allows it to be reset by calling `disclosure.expanded(null)`
95411               var preference = corePreferences('disclosure.' + key + '.expanded');
95412               _expanded = preference === null ? !!expandedDefault : preference === 'true';
95413             }
95414
95415             var hideToggle = selection.selectAll('.hide-toggle-' + key).data([0]); // enter
95416
95417             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'));
95418             hideToggleEnter.append('span').attr('class', 'hide-toggle-text'); // update
95419
95420             hideToggle = hideToggleEnter.merge(hideToggle);
95421             hideToggle.on('click', toggle).attr('title', _t("icons.".concat(_expanded ? 'collapse' : 'expand'))).attr('aria-expanded', _expanded).classed('expanded', _expanded);
95422             hideToggle.selectAll('.hide-toggle-text').html(_label());
95423             hideToggle.selectAll('.hide-toggle-icon').attr('xlink:href', _expanded ? '#iD-icon-down' : _mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-backward' : '#iD-icon-forward');
95424             var wrap = selection.selectAll('.disclosure-wrap').data([0]); // enter/update
95425
95426             wrap = wrap.enter().append('div').attr('class', 'disclosure-wrap disclosure-wrap-' + key).merge(wrap).classed('hide', !_expanded);
95427
95428             if (_expanded) {
95429               wrap.call(_content);
95430             }
95431
95432             function toggle(d3_event) {
95433               d3_event.preventDefault();
95434               _expanded = !_expanded;
95435
95436               if (_updatePreference) {
95437                 corePreferences('disclosure.' + key + '.expanded', _expanded);
95438               }
95439
95440               hideToggle.classed('expanded', _expanded).attr('aria-expanded', _expanded).attr('title', _t("icons.".concat(_expanded ? 'collapse' : 'expand')));
95441               hideToggle.selectAll('.hide-toggle-icon').attr('xlink:href', _expanded ? '#iD-icon-down' : _mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-backward' : '#iD-icon-forward');
95442               wrap.call(uiToggle(_expanded));
95443
95444               if (_expanded) {
95445                 wrap.call(_content);
95446               }
95447
95448               dispatch.call('toggled', this, _expanded);
95449             }
95450           };
95451
95452           disclosure.label = function (val) {
95453             if (!arguments.length) return _label;
95454             _label = utilFunctor(val);
95455             return disclosure;
95456           };
95457
95458           disclosure.expanded = function (val) {
95459             if (!arguments.length) return _expanded;
95460             _expanded = val;
95461             return disclosure;
95462           };
95463
95464           disclosure.updatePreference = function (val) {
95465             if (!arguments.length) return _updatePreference;
95466             _updatePreference = val;
95467             return disclosure;
95468           };
95469
95470           disclosure.content = function (val) {
95471             if (!arguments.length) return _content;
95472             _content = val;
95473             return disclosure;
95474           };
95475
95476           return utilRebind(disclosure, dispatch, 'on');
95477         }
95478
95479         // Can be labeled and collapsible.
95480
95481         function uiSection(id, context) {
95482           var _classes = utilFunctor('');
95483
95484           var _shouldDisplay;
95485
95486           var _content;
95487
95488           var _disclosure;
95489
95490           var _label;
95491
95492           var _expandedByDefault = utilFunctor(true);
95493
95494           var _disclosureContent;
95495
95496           var _disclosureExpanded;
95497
95498           var _containerSelection = select(null);
95499
95500           var section = {
95501             id: id
95502           };
95503
95504           section.classes = function (val) {
95505             if (!arguments.length) return _classes;
95506             _classes = utilFunctor(val);
95507             return section;
95508           };
95509
95510           section.label = function (val) {
95511             if (!arguments.length) return _label;
95512             _label = utilFunctor(val);
95513             return section;
95514           };
95515
95516           section.expandedByDefault = function (val) {
95517             if (!arguments.length) return _expandedByDefault;
95518             _expandedByDefault = utilFunctor(val);
95519             return section;
95520           };
95521
95522           section.shouldDisplay = function (val) {
95523             if (!arguments.length) return _shouldDisplay;
95524             _shouldDisplay = utilFunctor(val);
95525             return section;
95526           };
95527
95528           section.content = function (val) {
95529             if (!arguments.length) return _content;
95530             _content = val;
95531             return section;
95532           };
95533
95534           section.disclosureContent = function (val) {
95535             if (!arguments.length) return _disclosureContent;
95536             _disclosureContent = val;
95537             return section;
95538           };
95539
95540           section.disclosureExpanded = function (val) {
95541             if (!arguments.length) return _disclosureExpanded;
95542             _disclosureExpanded = val;
95543             return section;
95544           }; // may be called multiple times
95545
95546
95547           section.render = function (selection) {
95548             _containerSelection = selection.selectAll('.section-' + id).data([0]);
95549
95550             var sectionEnter = _containerSelection.enter().append('div').attr('class', 'section section-' + id + ' ' + (_classes && _classes() || ''));
95551
95552             _containerSelection = sectionEnter.merge(_containerSelection);
95553
95554             _containerSelection.call(renderContent);
95555           };
95556
95557           section.reRender = function () {
95558             _containerSelection.call(renderContent);
95559           };
95560
95561           section.selection = function () {
95562             return _containerSelection;
95563           };
95564
95565           section.disclosure = function () {
95566             return _disclosure;
95567           }; // may be called multiple times
95568
95569
95570           function renderContent(selection) {
95571             if (_shouldDisplay) {
95572               var shouldDisplay = _shouldDisplay();
95573
95574               selection.classed('hide', !shouldDisplay);
95575
95576               if (!shouldDisplay) {
95577                 selection.html('');
95578                 return;
95579               }
95580             }
95581
95582             if (_disclosureContent) {
95583               if (!_disclosure) {
95584                 _disclosure = uiDisclosure(context, id.replace(/-/g, '_'), _expandedByDefault()).label(_label || '')
95585                 /*.on('toggled', function(expanded) {
95586                     if (expanded) { selection.node().parentNode.scrollTop += 200; }
95587                 })*/
95588                 .content(_disclosureContent);
95589               }
95590
95591               if (_disclosureExpanded !== undefined) {
95592                 _disclosure.expanded(_disclosureExpanded);
95593
95594                 _disclosureExpanded = undefined;
95595               }
95596
95597               selection.call(_disclosure);
95598               return;
95599             }
95600
95601             if (_content) {
95602               selection.call(_content);
95603             }
95604           }
95605
95606           return section;
95607         }
95608
95609         // {
95610         //   key: 'string',     // required
95611         //   value: 'string'    // optional
95612         // }
95613         //   -or-
95614         // {
95615         //   qid: 'string'      // brand wikidata  (e.g. 'Q37158')
95616         // }
95617         //
95618
95619         function uiTagReference(what) {
95620           var wikibase = what.qid ? services.wikidata : services.osmWikibase;
95621           var tagReference = {};
95622
95623           var _button = select(null);
95624
95625           var _body = select(null);
95626
95627           var _loaded;
95628
95629           var _showing;
95630
95631           function load() {
95632             if (!wikibase) return;
95633
95634             _button.classed('tag-reference-loading', true);
95635
95636             wikibase.getDocs(what, gotDocs);
95637           }
95638
95639           function gotDocs(err, docs) {
95640             _body.html('');
95641
95642             if (!docs || !docs.title) {
95643               _body.append('p').attr('class', 'tag-reference-description').call(_t.append('inspector.no_documentation_key'));
95644
95645               done();
95646               return;
95647             }
95648
95649             if (docs.imageURL) {
95650               _body.append('img').attr('class', 'tag-reference-wiki-image').attr('alt', docs.description).attr('src', docs.imageURL).on('load', function () {
95651                 done();
95652               }).on('error', function () {
95653                 select(this).remove();
95654                 done();
95655               });
95656             } else {
95657               done();
95658             }
95659
95660             var tagReferenceDescription = _body.append('p').attr('class', 'tag-reference-description').append('span');
95661
95662             if (docs.description) {
95663               tagReferenceDescription = tagReferenceDescription.attr('class', 'localized-text').attr('lang', docs.descriptionLocaleCode || 'und').text(docs.description);
95664             } else {
95665               tagReferenceDescription = tagReferenceDescription.call(_t.append('inspector.no_documentation_key'));
95666             }
95667
95668             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'));
95669
95670             if (docs.wiki) {
95671               _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));
95672             } // Add link to info about "good changeset comments" - #2923
95673
95674
95675             if (what.key === 'comment') {
95676               _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'));
95677             }
95678           }
95679
95680           function done() {
95681             _loaded = true;
95682
95683             _button.classed('tag-reference-loading', false);
95684
95685             _body.classed('expanded', true).transition().duration(200).style('max-height', '200px').style('opacity', '1');
95686
95687             _showing = true;
95688
95689             _button.selectAll('svg.icon use').each(function () {
95690               var iconUse = select(this);
95691
95692               if (iconUse.attr('href') === '#iD-icon-info') {
95693                 iconUse.attr('href', '#iD-icon-info-filled');
95694               }
95695             });
95696           }
95697
95698           function hide() {
95699             _body.transition().duration(200).style('max-height', '0px').style('opacity', '0').on('end', function () {
95700               _body.classed('expanded', false);
95701             });
95702
95703             _showing = false;
95704
95705             _button.selectAll('svg.icon use').each(function () {
95706               var iconUse = select(this);
95707
95708               if (iconUse.attr('href') === '#iD-icon-info-filled') {
95709                 iconUse.attr('href', '#iD-icon-info');
95710               }
95711             });
95712           }
95713
95714           tagReference.button = function (selection, klass, iconName) {
95715             _button = selection.selectAll('.tag-reference-button').data([0]);
95716             _button = _button.enter().append('button').attr('class', 'tag-reference-button ' + (klass || '')).attr('title', _t('icons.information')).call(svgIcon('#iD-icon-' + (iconName || 'inspect'))).merge(_button);
95717
95718             _button.on('click', function (d3_event) {
95719               d3_event.stopPropagation();
95720               d3_event.preventDefault();
95721               this.blur(); // avoid keeping focus on the button - #4641
95722
95723               if (_showing) {
95724                 hide();
95725               } else if (_loaded) {
95726                 done();
95727               } else {
95728                 load();
95729               }
95730             });
95731           };
95732
95733           tagReference.body = function (selection) {
95734             var itemID = what.qid || what.key + '-' + (what.value || '');
95735             _body = selection.selectAll('.tag-reference-body').data([itemID], function (d) {
95736               return d;
95737             });
95738
95739             _body.exit().remove();
95740
95741             _body = _body.enter().append('div').attr('class', 'tag-reference-body').style('max-height', '0').style('opacity', '0').merge(_body);
95742
95743             if (_showing === false) {
95744               hide();
95745             }
95746           };
95747
95748           tagReference.showing = function (val) {
95749             if (!arguments.length) return _showing;
95750             _showing = val;
95751             return tagReference;
95752           };
95753
95754           return tagReference;
95755         }
95756
95757         // It borrows some code from uiHelp
95758
95759         function uiFieldHelp(context, fieldName) {
95760           var fieldHelp = {};
95761
95762           var _inspector = select(null);
95763
95764           var _wrap = select(null);
95765
95766           var _body = select(null);
95767
95768           var fieldHelpKeys = {
95769             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']]]
95770           };
95771           var fieldHelpHeadings = {};
95772           var replacements = {
95773             distField: {
95774               html: _t.html('restriction.controls.distance')
95775             },
95776             viaField: {
95777               html: _t.html('restriction.controls.via')
95778             },
95779             fromShadow: {
95780               html: icon('#iD-turn-shadow', 'inline shadow from')
95781             },
95782             allowShadow: {
95783               html: icon('#iD-turn-shadow', 'inline shadow allow')
95784             },
95785             restrictShadow: {
95786               html: icon('#iD-turn-shadow', 'inline shadow restrict')
95787             },
95788             onlyShadow: {
95789               html: icon('#iD-turn-shadow', 'inline shadow only')
95790             },
95791             allowTurn: {
95792               html: icon('#iD-turn-yes', 'inline turn')
95793             },
95794             restrictTurn: {
95795               html: icon('#iD-turn-no', 'inline turn')
95796             },
95797             onlyTurn: {
95798               html: icon('#iD-turn-only', 'inline turn')
95799             }
95800           }; // For each section, squash all the texts into a single markdown document
95801
95802           var docs = fieldHelpKeys[fieldName].map(function (key) {
95803             var helpkey = 'help.field.' + fieldName + '.' + key[0];
95804             var text = key[1].reduce(function (all, part) {
95805               var subkey = helpkey + '.' + part;
95806               var depth = fieldHelpHeadings[subkey]; // is this subkey a heading?
95807
95808               var hhh = depth ? Array(depth + 1).join('#') + ' ' : ''; // if so, prepend with some ##'s
95809
95810               return all + hhh + _t.html(subkey, replacements) + '\n\n';
95811             }, '');
95812             return {
95813               key: helpkey,
95814               title: _t.html(helpkey + '.title'),
95815               html: marked_1(text.trim())
95816             };
95817           });
95818
95819           function show() {
95820             updatePosition();
95821
95822             _body.classed('hide', false).style('opacity', '0').transition().duration(200).style('opacity', '1');
95823           }
95824
95825           function hide() {
95826             _body.classed('hide', true).transition().duration(200).style('opacity', '0').on('end', function () {
95827               _body.classed('hide', true);
95828             });
95829           }
95830
95831           function clickHelp(index) {
95832             var d = docs[index];
95833             var tkeys = fieldHelpKeys[fieldName][index][1];
95834
95835             _body.selectAll('.field-help-nav-item').classed('active', function (d, i) {
95836               return i === index;
95837             });
95838
95839             var content = _body.selectAll('.field-help-content').html(d.html); // class the paragraphs so we can find and style them
95840
95841
95842             content.selectAll('p').attr('class', function (d, i) {
95843               return tkeys[i];
95844             }); // insert special content for certain help sections
95845
95846             if (d.key === 'help.field.restrictions.inspecting') {
95847               content.insert('img', 'p.from_shadow').attr('class', 'field-help-image cf').attr('src', context.imagePath('tr_inspect.gif'));
95848             } else if (d.key === 'help.field.restrictions.modifying') {
95849               content.insert('img', 'p.allow_turn').attr('class', 'field-help-image cf').attr('src', context.imagePath('tr_modify.gif'));
95850             }
95851           }
95852
95853           fieldHelp.button = function (selection) {
95854             if (_body.empty()) return;
95855             var button = selection.selectAll('.field-help-button').data([0]); // enter/update
95856
95857             button.enter().append('button').attr('class', 'field-help-button').call(svgIcon('#iD-icon-help')).merge(button).on('click', function (d3_event) {
95858               d3_event.stopPropagation();
95859               d3_event.preventDefault();
95860
95861               if (_body.classed('hide')) {
95862                 show();
95863               } else {
95864                 hide();
95865               }
95866             });
95867           };
95868
95869           function updatePosition() {
95870             var wrap = _wrap.node();
95871
95872             var inspector = _inspector.node();
95873
95874             var wRect = wrap.getBoundingClientRect();
95875             var iRect = inspector.getBoundingClientRect();
95876
95877             _body.style('top', wRect.top + inspector.scrollTop - iRect.top + 'px');
95878           }
95879
95880           fieldHelp.body = function (selection) {
95881             // This control expects the field to have a form-field-input-wrap div
95882             _wrap = selection.selectAll('.form-field-input-wrap');
95883             if (_wrap.empty()) return; // absolute position relative to the inspector, so it "floats" above the fields
95884
95885             _inspector = context.container().select('.sidebar .entity-editor-pane .inspector-body');
95886             if (_inspector.empty()) return;
95887             _body = _inspector.selectAll('.field-help-body').data([0]);
95888
95889             var enter = _body.enter().append('div').attr('class', 'field-help-body hide'); // initially hidden
95890
95891
95892             var titleEnter = enter.append('div').attr('class', 'field-help-title cf');
95893             titleEnter.append('h2').attr('class', _mainLocalizer.textDirection() === 'rtl' ? 'fr' : 'fl').call(_t.append('help.field.' + fieldName + '.title'));
95894             titleEnter.append('button').attr('class', 'fr close').attr('title', _t('icons.close')).on('click', function (d3_event) {
95895               d3_event.stopPropagation();
95896               d3_event.preventDefault();
95897               hide();
95898             }).call(svgIcon('#iD-icon-close'));
95899             var navEnter = enter.append('div').attr('class', 'field-help-nav cf');
95900             var titles = docs.map(function (d) {
95901               return d.title;
95902             });
95903             navEnter.selectAll('.field-help-nav-item').data(titles).enter().append('div').attr('class', 'field-help-nav-item').html(function (d) {
95904               return d;
95905             }).on('click', function (d3_event, d) {
95906               d3_event.stopPropagation();
95907               d3_event.preventDefault();
95908               clickHelp(titles.indexOf(d));
95909             });
95910             enter.append('div').attr('class', 'field-help-content');
95911             _body = _body.merge(enter);
95912             clickHelp(0);
95913           };
95914
95915           return fieldHelp;
95916         }
95917
95918         function uiFieldCheck(field, context) {
95919           var dispatch = dispatch$8('change');
95920           var options = field.options;
95921           var values = [];
95922           var texts = [];
95923
95924           var _tags;
95925
95926           var input = select(null);
95927           var text = select(null);
95928           var label = select(null);
95929           var reverser = select(null);
95930
95931           var _impliedYes;
95932
95933           var _entityIDs = [];
95934
95935           var _value;
95936
95937           if (options) {
95938             for (var i in options) {
95939               var v = options[i];
95940               values.push(v === 'undefined' ? undefined : v);
95941               texts.push(field.t.html('options.' + v, {
95942                 'default': v
95943               }));
95944             }
95945           } else {
95946             values = [undefined, 'yes'];
95947             texts = [_t.html('inspector.unknown'), _t.html('inspector.check.yes')];
95948
95949             if (field.type !== 'defaultCheck') {
95950               values.push('no');
95951               texts.push(_t.html('inspector.check.no'));
95952             }
95953           } // Checks tags to see whether an undefined value is "Assumed to be Yes"
95954
95955
95956           function checkImpliedYes() {
95957             _impliedYes = field.id === 'oneway_yes'; // hack: pretend `oneway` field is a `oneway_yes` field
95958             // where implied oneway tag exists (e.g. `junction=roundabout`) #2220, #1841
95959
95960             if (field.id === 'oneway') {
95961               var entity = context.entity(_entityIDs[0]);
95962
95963               for (var key in entity.tags) {
95964                 if (key in osmOneWayTags && entity.tags[key] in osmOneWayTags[key]) {
95965                   _impliedYes = true;
95966                   texts[0] = _t.html('_tagging.presets.fields.oneway_yes.options.undefined');
95967                   break;
95968                 }
95969               }
95970             }
95971           }
95972
95973           function reverserHidden() {
95974             if (!context.container().select('div.inspector-hover').empty()) return true;
95975             return !(_value === 'yes' || _impliedYes && !_value);
95976           }
95977
95978           function reverserSetText(selection) {
95979             var entity = _entityIDs.length && context.hasEntity(_entityIDs[0]);
95980             if (reverserHidden() || !entity) return selection;
95981             var first = entity.first();
95982             var last = entity.isClosed() ? entity.nodes[entity.nodes.length - 2] : entity.last();
95983             var pseudoDirection = first < last;
95984             var icon = pseudoDirection ? '#iD-icon-forward' : '#iD-icon-backward';
95985             selection.selectAll('.reverser-span').html('').call(_t.append('inspector.check.reverser')).call(svgIcon(icon, 'inline'));
95986             return selection;
95987           }
95988
95989           var check = function check(selection) {
95990             checkImpliedYes();
95991             label = selection.selectAll('.form-field-input-wrap').data([0]);
95992             var enter = label.enter().append('label').attr('class', 'form-field-input-wrap form-field-input-check');
95993             enter.append('input').property('indeterminate', field.type !== 'defaultCheck').attr('type', 'checkbox').attr('id', field.domId);
95994             enter.append('span').html(texts[0]).attr('class', 'value');
95995
95996             if (field.type === 'onewayCheck') {
95997               enter.append('button').attr('class', 'reverser' + (reverserHidden() ? ' hide' : '')).append('span').attr('class', 'reverser-span');
95998             }
95999
96000             label = label.merge(enter);
96001             input = label.selectAll('input');
96002             text = label.selectAll('span.value');
96003             input.on('click', function (d3_event) {
96004               d3_event.stopPropagation();
96005               var t = {};
96006
96007               if (Array.isArray(_tags[field.key])) {
96008                 if (values.indexOf('yes') !== -1) {
96009                   t[field.key] = 'yes';
96010                 } else {
96011                   t[field.key] = values[0];
96012                 }
96013               } else {
96014                 t[field.key] = values[(values.indexOf(_value) + 1) % values.length];
96015               } // Don't cycle through `alternating` or `reversible` states - #4970
96016               // (They are supported as translated strings, but should not toggle with clicks)
96017
96018
96019               if (t[field.key] === 'reversible' || t[field.key] === 'alternating') {
96020                 t[field.key] = values[0];
96021               }
96022
96023               dispatch.call('change', this, t);
96024             });
96025
96026             if (field.type === 'onewayCheck') {
96027               reverser = label.selectAll('.reverser');
96028               reverser.call(reverserSetText).on('click', function (d3_event) {
96029                 d3_event.preventDefault();
96030                 d3_event.stopPropagation();
96031                 context.perform(function (graph) {
96032                   for (var i in _entityIDs) {
96033                     graph = actionReverse(_entityIDs[i])(graph);
96034                   }
96035
96036                   return graph;
96037                 }, _t('operations.reverse.annotation.line', {
96038                   n: 1
96039                 })); // must manually revalidate since no 'change' event was called
96040
96041                 context.validator().validate();
96042                 select(this).call(reverserSetText);
96043               });
96044             }
96045           };
96046
96047           check.entityIDs = function (val) {
96048             if (!arguments.length) return _entityIDs;
96049             _entityIDs = val;
96050             return check;
96051           };
96052
96053           check.tags = function (tags) {
96054             _tags = tags;
96055
96056             function isChecked(val) {
96057               return val !== 'no' && val !== '' && val !== undefined && val !== null;
96058             }
96059
96060             function textFor(val) {
96061               if (val === '') val = undefined;
96062               var index = values.indexOf(val);
96063               return index !== -1 ? texts[index] : '"' + val + '"';
96064             }
96065
96066             checkImpliedYes();
96067             var isMixed = Array.isArray(tags[field.key]);
96068             _value = !isMixed && tags[field.key] && tags[field.key].toLowerCase();
96069
96070             if (field.type === 'onewayCheck' && (_value === '1' || _value === '-1')) {
96071               _value = 'yes';
96072             }
96073
96074             input.property('indeterminate', isMixed || field.type !== 'defaultCheck' && !_value).property('checked', isChecked(_value));
96075             text.html(isMixed ? _t.html('inspector.multiple_values') : textFor(_value)).classed('mixed', isMixed);
96076             label.classed('set', !!_value);
96077
96078             if (field.type === 'onewayCheck') {
96079               reverser.classed('hide', reverserHidden()).call(reverserSetText);
96080             }
96081           };
96082
96083           check.focus = function () {
96084             input.node().focus();
96085           };
96086
96087           return utilRebind(check, dispatch, 'on');
96088         }
96089
96090         function uiFieldCombo(field, context) {
96091           var dispatch = dispatch$8('change');
96092
96093           var _isMulti = field.type === 'multiCombo' || field.type === 'manyCombo';
96094
96095           var _isNetwork = field.type === 'networkCombo';
96096
96097           var _isSemi = field.type === 'semiCombo';
96098
96099           var _optarray = field.options;
96100
96101           var _showTagInfoSuggestions = field.type !== 'manyCombo' && field.autoSuggestions !== false;
96102
96103           var _allowCustomValues = field.type !== 'manyCombo' && field.customValues !== false;
96104
96105           var _snake_case = field.snake_case || field.snake_case === undefined;
96106
96107           var _combobox = uiCombobox(context, 'combo-' + field.safeid).caseSensitive(field.caseSensitive).minItems(_isMulti || _isSemi ? 1 : 2);
96108
96109           var _container = select(null);
96110
96111           var _inputWrap = select(null);
96112
96113           var _input = select(null);
96114
96115           var _comboData = [];
96116           var _multiData = [];
96117           var _entityIDs = [];
96118
96119           var _tags;
96120
96121           var _countryCode;
96122
96123           var _staticPlaceholder; // initialize deprecated tags array
96124
96125
96126           var _dataDeprecated = [];
96127           _mainFileFetcher.get('deprecated').then(function (d) {
96128             _dataDeprecated = d;
96129           })["catch"](function () {
96130             /* ignore */
96131           }); // ensure multiCombo field.key ends with a ':'
96132
96133           if (_isMulti && field.key && /[^:]$/.test(field.key)) {
96134             field.key += ':';
96135           }
96136
96137           function snake(s) {
96138             return s.replace(/\s+/g, '_').toLowerCase();
96139           }
96140
96141           function clean(s) {
96142             return s.split(';').map(function (s) {
96143               return s.trim();
96144             }).join(';');
96145           } // returns the tag value for a display value
96146           // (for multiCombo, dval should be the key suffix, not the entire key)
96147
96148
96149           function tagValue(dval) {
96150             dval = clean(dval || '');
96151
96152             var found = _comboData.find(function (o) {
96153               return o.key && clean(o.value) === dval;
96154             });
96155
96156             if (found) return found.key;
96157
96158             if (field.type === 'typeCombo' && !dval) {
96159               return 'yes';
96160             }
96161
96162             return (_snake_case ? snake(dval) : dval) || undefined;
96163           } // returns the display value for a tag value
96164           // (for multiCombo, tval should be the key suffix, not the entire key)
96165
96166
96167           function displayValue(tval) {
96168             tval = tval || '';
96169
96170             if (field.hasTextForStringId('options.' + tval)) {
96171               return field.t('options.' + tval, {
96172                 "default": tval
96173               });
96174             }
96175
96176             if (field.type === 'typeCombo' && tval.toLowerCase() === 'yes') {
96177               return '';
96178             }
96179
96180             return tval;
96181           } // Compute the difference between arrays of objects by `value` property
96182           //
96183           // objectDifference([{value:1}, {value:2}, {value:3}], [{value:2}])
96184           // > [{value:1}, {value:3}]
96185           //
96186
96187
96188           function objectDifference(a, b) {
96189             return a.filter(function (d1) {
96190               return !b.some(function (d2) {
96191                 return !d2.isMixed && d1.value === d2.value;
96192               });
96193             });
96194           }
96195
96196           function initCombo(selection, attachTo) {
96197             if (!_allowCustomValues) {
96198               selection.attr('readonly', 'readonly');
96199             }
96200
96201             if (_showTagInfoSuggestions && services.taginfo) {
96202               selection.call(_combobox.fetcher(setTaginfoValues), attachTo);
96203               setTaginfoValues('', setPlaceholder);
96204             } else {
96205               selection.call(_combobox, attachTo);
96206               setStaticValues(setPlaceholder);
96207             }
96208           }
96209
96210           function setStaticValues(callback) {
96211             if (!_optarray) return;
96212             _comboData = _optarray.map(function (v) {
96213               return {
96214                 key: v,
96215                 value: field.t('options.' + v, {
96216                   "default": v
96217                 }),
96218                 title: v,
96219                 display: field.t.html('options.' + v, {
96220                   "default": v
96221                 }),
96222                 klass: field.hasTextForStringId('options.' + v) ? '' : 'raw-option'
96223               };
96224             });
96225
96226             _combobox.data(objectDifference(_comboData, _multiData));
96227
96228             if (callback) callback(_comboData);
96229           }
96230
96231           function setTaginfoValues(q, callback) {
96232             var fn = _isMulti ? 'multikeys' : 'values';
96233             var query = (_isMulti ? field.key : '') + q;
96234             var hasCountryPrefix = _isNetwork && _countryCode && _countryCode.indexOf(q.toLowerCase()) === 0;
96235
96236             if (hasCountryPrefix) {
96237               query = _countryCode + ':';
96238             }
96239
96240             var params = {
96241               debounce: q !== '',
96242               key: field.key,
96243               query: query
96244             };
96245
96246             if (_entityIDs.length) {
96247               params.geometry = context.graph().geometry(_entityIDs[0]);
96248             }
96249
96250             services.taginfo[fn](params, function (err, data) {
96251               if (err) return;
96252               data = data.filter(function (d) {
96253                 if (field.type === 'typeCombo' && d.value === 'yes') {
96254                   // don't show the fallback value
96255                   return false;
96256                 } // don't show values with very low usage
96257
96258
96259                 return !d.count || d.count > 10;
96260               });
96261               var deprecatedValues = osmEntity.deprecatedTagValuesByKey(_dataDeprecated)[field.key];
96262
96263               if (deprecatedValues) {
96264                 // don't suggest deprecated tag values
96265                 data = data.filter(function (d) {
96266                   return deprecatedValues.indexOf(d.value) === -1;
96267                 });
96268               }
96269
96270               if (hasCountryPrefix) {
96271                 data = data.filter(function (d) {
96272                   return d.value.toLowerCase().indexOf(_countryCode + ':') === 0;
96273                 });
96274               } // hide the caret if there are no suggestions
96275
96276
96277               _container.classed('empty-combobox', data.length === 0);
96278
96279               _comboData = data.map(function (d) {
96280                 var k = d.value;
96281                 if (_isMulti) k = k.replace(field.key, '');
96282                 var label = field.t('options.' + k, {
96283                   "default": k
96284                 });
96285                 return {
96286                   key: k,
96287                   value: label,
96288                   display: field.t.html('options.' + k, {
96289                     "default": k
96290                   }),
96291                   title: d.title || label,
96292                   klass: field.hasTextForStringId('options.' + k) ? '' : 'raw-option'
96293                 };
96294               });
96295               _comboData = objectDifference(_comboData, _multiData);
96296               if (callback) callback(_comboData);
96297             });
96298           }
96299
96300           function setPlaceholder(values) {
96301             if (_isMulti || _isSemi) {
96302               _staticPlaceholder = field.placeholder() || _t('inspector.add');
96303             } else {
96304               var vals = values.map(function (d) {
96305                 return d.value;
96306               }).filter(function (s) {
96307                 return s.length < 20;
96308               });
96309               var placeholders = vals.length > 1 ? vals : values.map(function (d) {
96310                 return d.key;
96311               });
96312               _staticPlaceholder = field.placeholder() || placeholders.slice(0, 3).join(', ');
96313             }
96314
96315             if (!/(…|\.\.\.)$/.test(_staticPlaceholder)) {
96316               _staticPlaceholder += '…';
96317             }
96318
96319             var ph;
96320
96321             if (!_isMulti && !_isSemi && _tags && Array.isArray(_tags[field.key])) {
96322               ph = _t('inspector.multiple_values');
96323             } else {
96324               ph = _staticPlaceholder;
96325             }
96326
96327             _container.selectAll('input').attr('placeholder', ph);
96328           }
96329
96330           function change() {
96331             var t = {};
96332             var val;
96333
96334             if (_isMulti || _isSemi) {
96335               val = tagValue(utilGetSetValue(_input).replace(/,/g, ';')) || '';
96336
96337               _container.classed('active', false);
96338
96339               utilGetSetValue(_input, '');
96340               var vals = val.split(';').filter(Boolean);
96341               if (!vals.length) return;
96342
96343               if (_isMulti) {
96344                 utilArrayUniq(vals).forEach(function (v) {
96345                   var key = (field.key || '') + v;
96346
96347                   if (_tags) {
96348                     // don't set a multicombo value to 'yes' if it already has a non-'no' value
96349                     // e.g. `language:de=main`
96350                     var old = _tags[key];
96351                     if (typeof old === 'string' && old.toLowerCase() !== 'no') return;
96352                   }
96353
96354                   key = context.cleanTagKey(key);
96355                   field.keys.push(key);
96356                   t[key] = 'yes';
96357                 });
96358               } else if (_isSemi) {
96359                 var arr = _multiData.map(function (d) {
96360                   return d.key;
96361                 });
96362
96363                 arr = arr.concat(vals);
96364                 t[field.key] = context.cleanTagValue(utilArrayUniq(arr).filter(Boolean).join(';'));
96365               }
96366
96367               window.setTimeout(function () {
96368                 _input.node().focus();
96369               }, 10);
96370             } else {
96371               var rawValue = utilGetSetValue(_input); // don't override multiple values with blank string
96372
96373               if (!rawValue && Array.isArray(_tags[field.key])) return;
96374               val = context.cleanTagValue(tagValue(rawValue));
96375               t[field.key] = val || undefined;
96376             }
96377
96378             dispatch.call('change', this, t);
96379           }
96380
96381           function removeMultikey(d3_event, d) {
96382             d3_event.preventDefault();
96383             d3_event.stopPropagation();
96384             var t = {};
96385
96386             if (_isMulti) {
96387               t[d.key] = undefined;
96388             } else if (_isSemi) {
96389               var arr = _multiData.map(function (md) {
96390                 return md.key === d.key ? null : md.key;
96391               }).filter(Boolean);
96392
96393               arr = utilArrayUniq(arr);
96394               t[field.key] = arr.length ? arr.join(';') : undefined;
96395             }
96396
96397             dispatch.call('change', this, t);
96398           }
96399
96400           function combo(selection) {
96401             _container = selection.selectAll('.form-field-input-wrap').data([0]);
96402             var type = _isMulti || _isSemi ? 'multicombo' : 'combo';
96403             _container = _container.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + type).merge(_container);
96404
96405             if (_isMulti || _isSemi) {
96406               _container = _container.selectAll('.chiplist').data([0]);
96407               var listClass = 'chiplist'; // Use a separate line for each value in the Destinations and Via fields
96408               // to mimic highway exit signs
96409
96410               if (field.key === 'destination' || field.key === 'via') {
96411                 listClass += ' full-line-chips';
96412               }
96413
96414               _container = _container.enter().append('ul').attr('class', listClass).on('click', function () {
96415                 window.setTimeout(function () {
96416                   _input.node().focus();
96417                 }, 10);
96418               }).merge(_container);
96419               _inputWrap = _container.selectAll('.input-wrap').data([0]);
96420               _inputWrap = _inputWrap.enter().append('li').attr('class', 'input-wrap').merge(_inputWrap);
96421               _input = _inputWrap.selectAll('input').data([0]);
96422             } else {
96423               _input = _container.selectAll('input').data([0]);
96424             }
96425
96426             _input = _input.enter().append('input').attr('type', 'text').attr('id', field.domId).call(utilNoAuto).call(initCombo, selection).merge(_input);
96427
96428             if (_isNetwork) {
96429               var extent = combinedEntityExtent();
96430               var countryCode = extent && iso1A2Code(extent.center());
96431               _countryCode = countryCode && countryCode.toLowerCase();
96432             }
96433
96434             _input.on('change', change).on('blur', change);
96435
96436             _input.on('keydown.field', function (d3_event) {
96437               switch (d3_event.keyCode) {
96438                 case 13:
96439                   // ↩ Return
96440                   _input.node().blur(); // blurring also enters the value
96441
96442
96443                   d3_event.stopPropagation();
96444                   break;
96445               }
96446             });
96447
96448             if (_isMulti || _isSemi) {
96449               _combobox.on('accept', function () {
96450                 _input.node().blur();
96451
96452                 _input.node().focus();
96453               });
96454
96455               _input.on('focus', function () {
96456                 _container.classed('active', true);
96457               });
96458             }
96459           }
96460
96461           combo.tags = function (tags) {
96462             _tags = tags;
96463
96464             if (_isMulti || _isSemi) {
96465               _multiData = [];
96466               var maxLength;
96467
96468               if (_isMulti) {
96469                 // Build _multiData array containing keys already set..
96470                 for (var k in tags) {
96471                   if (field.key && k.indexOf(field.key) !== 0) continue;
96472                   if (!field.key && field.keys.indexOf(k) === -1) continue;
96473                   var v = tags[k];
96474                   if (!v || typeof v === 'string' && v.toLowerCase() === 'no') continue;
96475                   var suffix = field.key ? k.substr(field.key.length) : k;
96476
96477                   _multiData.push({
96478                     key: k,
96479                     value: displayValue(suffix),
96480                     isMixed: Array.isArray(v)
96481                   });
96482                 }
96483
96484                 if (field.key) {
96485                   // Set keys for form-field modified (needed for undo and reset buttons)..
96486                   field.keys = _multiData.map(function (d) {
96487                     return d.key;
96488                   }); // limit the input length so it fits after prepending the key prefix
96489
96490                   maxLength = context.maxCharsForTagKey() - utilUnicodeCharsCount(field.key);
96491                 } else {
96492                   maxLength = context.maxCharsForTagKey();
96493                 }
96494               } else if (_isSemi) {
96495                 var allValues = [];
96496                 var commonValues;
96497
96498                 if (Array.isArray(tags[field.key])) {
96499                   tags[field.key].forEach(function (tagVal) {
96500                     var thisVals = utilArrayUniq((tagVal || '').split(';')).filter(Boolean);
96501                     allValues = allValues.concat(thisVals);
96502
96503                     if (!commonValues) {
96504                       commonValues = thisVals;
96505                     } else {
96506                       commonValues = commonValues.filter(function (value) {
96507                         return thisVals.includes(value);
96508                       });
96509                     }
96510                   });
96511                   allValues = utilArrayUniq(allValues).filter(Boolean);
96512                 } else {
96513                   allValues = utilArrayUniq((tags[field.key] || '').split(';')).filter(Boolean);
96514                   commonValues = allValues;
96515                 }
96516
96517                 _multiData = allValues.map(function (v) {
96518                   return {
96519                     key: v,
96520                     value: displayValue(v),
96521                     isMixed: !commonValues.includes(v)
96522                   };
96523                 });
96524                 var currLength = utilUnicodeCharsCount(commonValues.join(';')); // limit the input length to the remaining available characters
96525
96526                 maxLength = context.maxCharsForTagValue() - currLength;
96527
96528                 if (currLength > 0) {
96529                   // account for the separator if a new value will be appended to existing
96530                   maxLength -= 1;
96531                 }
96532               } // a negative maxlength doesn't make sense
96533
96534
96535               maxLength = Math.max(0, maxLength);
96536               var allowDragAndDrop = _isSemi // only semiCombo values are ordered
96537               && !Array.isArray(tags[field.key]); // Exclude existing multikeys from combo options..
96538
96539               var available = objectDifference(_comboData, _multiData);
96540
96541               _combobox.data(available); // Hide 'Add' button if this field uses fixed set of
96542               // options and they're all currently used,
96543               // or if the field is already at its character limit
96544
96545
96546               var hideAdd = !_allowCustomValues && !available.length || maxLength <= 0;
96547
96548               _container.selectAll('.chiplist .input-wrap').style('display', hideAdd ? 'none' : null); // Render chips
96549
96550
96551               var chips = _container.selectAll('.chip').data(_multiData);
96552
96553               chips.exit().remove();
96554               var enter = chips.enter().insert('li', '.input-wrap').attr('class', 'chip');
96555               enter.append('span');
96556               enter.append('a');
96557               chips = chips.merge(enter).order().classed('raw-value', function (d) {
96558                 var k = d.key;
96559                 if (_isMulti) k = k.replace(field.key, '');
96560                 return !field.hasTextForStringId('options.' + k);
96561               }).classed('draggable', allowDragAndDrop).classed('mixed', function (d) {
96562                 return d.isMixed;
96563               }).attr('title', function (d) {
96564                 return d.isMixed ? _t('inspector.unshared_value_tooltip') : null;
96565               });
96566
96567               if (allowDragAndDrop) {
96568                 registerDragAndDrop(chips);
96569               }
96570
96571               chips.select('span').text(function (d) {
96572                 return d.value;
96573               });
96574               chips.select('a').attr('href', '#').on('click', removeMultikey).attr('class', 'remove').text('×');
96575             } else {
96576               var isMixed = Array.isArray(tags[field.key]);
96577               var mixedValues = isMixed && tags[field.key].map(function (val) {
96578                 return displayValue(val);
96579               }).filter(Boolean);
96580               var showsValue = !isMixed && tags[field.key] && !(field.type === 'typeCombo' && tags[field.key] === 'yes');
96581               var isRawValue = showsValue && !field.hasTextForStringId('options.' + tags[field.key]);
96582               var isKnownValue = showsValue && !isRawValue;
96583               var isReadOnly = !_allowCustomValues || isKnownValue;
96584               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) {
96585                 if (isReadOnly && isKnownValue && (d3_event.keyCode === utilKeybinding.keyCodes['⌫'] || d3_event.keyCode === utilKeybinding.keyCodes['⌦'])) {
96586                   d3_event.preventDefault();
96587                   d3_event.stopPropagation();
96588                   var t = {};
96589                   t[field.key] = undefined;
96590                   dispatch.call('change', this, t);
96591                 }
96592               });
96593             }
96594           };
96595
96596           function registerDragAndDrop(selection) {
96597             // allow drag and drop re-ordering of chips
96598             var dragOrigin, targetIndex;
96599             selection.call(d3_drag().on('start', function (d3_event) {
96600               dragOrigin = {
96601                 x: d3_event.x,
96602                 y: d3_event.y
96603               };
96604               targetIndex = null;
96605             }).on('drag', function (d3_event) {
96606               var x = d3_event.x - dragOrigin.x,
96607                   y = d3_event.y - dragOrigin.y;
96608               if (!select(this).classed('dragging') && // don't display drag until dragging beyond a distance threshold
96609               Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)) <= 5) return;
96610               var index = selection.nodes().indexOf(this);
96611               select(this).classed('dragging', true);
96612               targetIndex = null;
96613               var targetIndexOffsetTop = null;
96614               var draggedTagWidth = select(this).node().offsetWidth;
96615
96616               if (field.key === 'destination' || field.key === 'via') {
96617                 // meaning tags are full width
96618                 _container.selectAll('.chip').style('transform', function (d2, index2) {
96619                   var node = select(this).node();
96620
96621                   if (index === index2) {
96622                     return 'translate(' + x + 'px, ' + y + 'px)'; // move the dragged tag up the order
96623                   } else if (index2 > index && d3_event.y > node.offsetTop) {
96624                     if (targetIndex === null || index2 > targetIndex) {
96625                       targetIndex = index2;
96626                     }
96627
96628                     return 'translateY(-100%)'; // move the dragged tag down the order
96629                   } else if (index2 < index && d3_event.y < node.offsetTop + node.offsetHeight) {
96630                     if (targetIndex === null || index2 < targetIndex) {
96631                       targetIndex = index2;
96632                     }
96633
96634                     return 'translateY(100%)';
96635                   }
96636
96637                   return null;
96638                 });
96639               } else {
96640                 _container.selectAll('.chip').each(function (d2, index2) {
96641                   var node = select(this).node(); // check the cursor is in the bounding box
96642
96643                   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) {
96644                     targetIndex = index2;
96645                     targetIndexOffsetTop = node.offsetTop;
96646                   }
96647                 }).style('transform', function (d2, index2) {
96648                   var node = select(this).node();
96649
96650                   if (index === index2) {
96651                     return 'translate(' + x + 'px, ' + y + 'px)';
96652                   } // only translate tags in the same row
96653
96654
96655                   if (node.offsetTop === targetIndexOffsetTop) {
96656                     if (index2 < index && index2 >= targetIndex) {
96657                       return 'translateX(' + draggedTagWidth + 'px)';
96658                     } else if (index2 > index && index2 <= targetIndex) {
96659                       return 'translateX(-' + draggedTagWidth + 'px)';
96660                     }
96661                   }
96662
96663                   return null;
96664                 });
96665               }
96666             }).on('end', function () {
96667               if (!select(this).classed('dragging')) {
96668                 return;
96669               }
96670
96671               var index = selection.nodes().indexOf(this);
96672               select(this).classed('dragging', false);
96673
96674               _container.selectAll('.chip').style('transform', null);
96675
96676               if (typeof targetIndex === 'number') {
96677                 var element = _multiData[index];
96678
96679                 _multiData.splice(index, 1);
96680
96681                 _multiData.splice(targetIndex, 0, element);
96682
96683                 var t = {};
96684
96685                 if (_multiData.length) {
96686                   t[field.key] = _multiData.map(function (element) {
96687                     return element.key;
96688                   }).join(';');
96689                 } else {
96690                   t[field.key] = undefined;
96691                 }
96692
96693                 dispatch.call('change', this, t);
96694               }
96695
96696               dragOrigin = undefined;
96697               targetIndex = undefined;
96698             }));
96699           }
96700
96701           combo.focus = function () {
96702             _input.node().focus();
96703           };
96704
96705           combo.entityIDs = function (val) {
96706             if (!arguments.length) return _entityIDs;
96707             _entityIDs = val;
96708             return combo;
96709           };
96710
96711           function combinedEntityExtent() {
96712             return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
96713           }
96714
96715           return utilRebind(combo, dispatch, 'on');
96716         }
96717
96718         // based on https://github.com/bestiejs/punycode.js/blob/master/punycode.js
96719         var global$2 = global$1m;
96720         var uncurryThis$1 = functionUncurryThis;
96721
96722         var maxInt = 2147483647; // aka. 0x7FFFFFFF or 2^31-1
96723         var base = 36;
96724         var tMin = 1;
96725         var tMax = 26;
96726         var skew = 38;
96727         var damp = 700;
96728         var initialBias = 72;
96729         var initialN = 128; // 0x80
96730         var delimiter = '-'; // '\x2D'
96731         var regexNonASCII = /[^\0-\u007E]/; // non-ASCII chars
96732         var regexSeparators = /[.\u3002\uFF0E\uFF61]/g; // RFC 3490 separators
96733         var OVERFLOW_ERROR = 'Overflow: input needs wider integers to process';
96734         var baseMinusTMin = base - tMin;
96735
96736         var RangeError$1 = global$2.RangeError;
96737         var exec$1 = uncurryThis$1(regexSeparators.exec);
96738         var floor$1 = Math.floor;
96739         var fromCharCode = String.fromCharCode;
96740         var charCodeAt = uncurryThis$1(''.charCodeAt);
96741         var join$1 = uncurryThis$1([].join);
96742         var push$1 = uncurryThis$1([].push);
96743         var replace$1 = uncurryThis$1(''.replace);
96744         var split$1 = uncurryThis$1(''.split);
96745         var toLowerCase$1 = uncurryThis$1(''.toLowerCase);
96746
96747         /**
96748          * Creates an array containing the numeric code points of each Unicode
96749          * character in the string. While JavaScript uses UCS-2 internally,
96750          * this function will convert a pair of surrogate halves (each of which
96751          * UCS-2 exposes as separate characters) into a single code point,
96752          * matching UTF-16.
96753          */
96754         var ucs2decode = function (string) {
96755           var output = [];
96756           var counter = 0;
96757           var length = string.length;
96758           while (counter < length) {
96759             var value = charCodeAt(string, counter++);
96760             if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
96761               // It's a high surrogate, and there is a next character.
96762               var extra = charCodeAt(string, counter++);
96763               if ((extra & 0xFC00) == 0xDC00) { // Low surrogate.
96764                 push$1(output, ((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
96765               } else {
96766                 // It's an unmatched surrogate; only append this code unit, in case the
96767                 // next code unit is the high surrogate of a surrogate pair.
96768                 push$1(output, value);
96769                 counter--;
96770               }
96771             } else {
96772               push$1(output, value);
96773             }
96774           }
96775           return output;
96776         };
96777
96778         /**
96779          * Converts a digit/integer into a basic code point.
96780          */
96781         var digitToBasic = function (digit) {
96782           //  0..25 map to ASCII a..z or A..Z
96783           // 26..35 map to ASCII 0..9
96784           return digit + 22 + 75 * (digit < 26);
96785         };
96786
96787         /**
96788          * Bias adaptation function as per section 3.4 of RFC 3492.
96789          * https://tools.ietf.org/html/rfc3492#section-3.4
96790          */
96791         var adapt = function (delta, numPoints, firstTime) {
96792           var k = 0;
96793           delta = firstTime ? floor$1(delta / damp) : delta >> 1;
96794           delta += floor$1(delta / numPoints);
96795           for (; delta > baseMinusTMin * tMax >> 1; k += base) {
96796             delta = floor$1(delta / baseMinusTMin);
96797           }
96798           return floor$1(k + (baseMinusTMin + 1) * delta / (delta + skew));
96799         };
96800
96801         /**
96802          * Converts a string of Unicode symbols (e.g. a domain name label) to a
96803          * Punycode string of ASCII-only symbols.
96804          */
96805         // eslint-disable-next-line max-statements -- TODO
96806         var encode = function (input) {
96807           var output = [];
96808
96809           // Convert the input in UCS-2 to an array of Unicode code points.
96810           input = ucs2decode(input);
96811
96812           // Cache the length.
96813           var inputLength = input.length;
96814
96815           // Initialize the state.
96816           var n = initialN;
96817           var delta = 0;
96818           var bias = initialBias;
96819           var i, currentValue;
96820
96821           // Handle the basic code points.
96822           for (i = 0; i < input.length; i++) {
96823             currentValue = input[i];
96824             if (currentValue < 0x80) {
96825               push$1(output, fromCharCode(currentValue));
96826             }
96827           }
96828
96829           var basicLength = output.length; // number of basic code points.
96830           var handledCPCount = basicLength; // number of code points that have been handled;
96831
96832           // Finish the basic string with a delimiter unless it's empty.
96833           if (basicLength) {
96834             push$1(output, delimiter);
96835           }
96836
96837           // Main encoding loop:
96838           while (handledCPCount < inputLength) {
96839             // All non-basic code points < n have been handled already. Find the next larger one:
96840             var m = maxInt;
96841             for (i = 0; i < input.length; i++) {
96842               currentValue = input[i];
96843               if (currentValue >= n && currentValue < m) {
96844                 m = currentValue;
96845               }
96846             }
96847
96848             // Increase `delta` enough to advance the decoder's <n,i> state to <m,0>, but guard against overflow.
96849             var handledCPCountPlusOne = handledCPCount + 1;
96850             if (m - n > floor$1((maxInt - delta) / handledCPCountPlusOne)) {
96851               throw RangeError$1(OVERFLOW_ERROR);
96852             }
96853
96854             delta += (m - n) * handledCPCountPlusOne;
96855             n = m;
96856
96857             for (i = 0; i < input.length; i++) {
96858               currentValue = input[i];
96859               if (currentValue < n && ++delta > maxInt) {
96860                 throw RangeError$1(OVERFLOW_ERROR);
96861               }
96862               if (currentValue == n) {
96863                 // Represent delta as a generalized variable-length integer.
96864                 var q = delta;
96865                 for (var k = base; /* no condition */; k += base) {
96866                   var t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
96867                   if (q < t) break;
96868                   var qMinusT = q - t;
96869                   var baseMinusT = base - t;
96870                   push$1(output, fromCharCode(digitToBasic(t + qMinusT % baseMinusT)));
96871                   q = floor$1(qMinusT / baseMinusT);
96872                 }
96873
96874                 push$1(output, fromCharCode(digitToBasic(q)));
96875                 bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
96876                 delta = 0;
96877                 ++handledCPCount;
96878               }
96879             }
96880
96881             ++delta;
96882             ++n;
96883           }
96884           return join$1(output, '');
96885         };
96886
96887         var stringPunycodeToAscii = function (input) {
96888           var encoded = [];
96889           var labels = split$1(replace$1(toLowerCase$1(input), regexSeparators, '\u002E'), '.');
96890           var i, label;
96891           for (i = 0; i < labels.length; i++) {
96892             label = labels[i];
96893             push$1(encoded, exec$1(regexNonASCII, label) ? 'xn--' + encode(label) : label);
96894           }
96895           return join$1(encoded, '.');
96896         };
96897
96898         // TODO: in core-js@4, move /modules/ dependencies to public entries for better optimization by tools like `preset-env`
96899
96900         var $ = _export;
96901         var DESCRIPTORS = descriptors;
96902         var USE_NATIVE_URL = nativeUrl;
96903         var global$1 = global$1m;
96904         var bind$2 = functionBindContext;
96905         var call = functionCall;
96906         var uncurryThis = functionUncurryThis;
96907         var defineProperties = objectDefineProperties;
96908         var redefine = redefine$h.exports;
96909         var anInstance = anInstance$7;
96910         var hasOwn = hasOwnProperty_1;
96911         var assign$1 = objectAssign;
96912         var arrayFrom = arrayFrom$1;
96913         var arraySlice = arraySlice$c;
96914         var codeAt = stringMultibyte.codeAt;
96915         var toASCII = stringPunycodeToAscii;
96916         var $toString = toString$k;
96917         var setToStringTag = setToStringTag$a;
96918         var URLSearchParamsModule = web_urlSearchParams;
96919         var InternalStateModule = internalState;
96920
96921         var setInternalState = InternalStateModule.set;
96922         var getInternalURLState = InternalStateModule.getterFor('URL');
96923         var URLSearchParams$1 = URLSearchParamsModule.URLSearchParams;
96924         var getInternalSearchParamsState = URLSearchParamsModule.getState;
96925
96926         var NativeURL = global$1.URL;
96927         var TypeError$1 = global$1.TypeError;
96928         var parseInt$1 = global$1.parseInt;
96929         var floor = Math.floor;
96930         var pow = Math.pow;
96931         var charAt = uncurryThis(''.charAt);
96932         var exec = uncurryThis(/./.exec);
96933         var join = uncurryThis([].join);
96934         var numberToString = uncurryThis(1.0.toString);
96935         var pop = uncurryThis([].pop);
96936         var push = uncurryThis([].push);
96937         var replace = uncurryThis(''.replace);
96938         var shift = uncurryThis([].shift);
96939         var split = uncurryThis(''.split);
96940         var stringSlice = uncurryThis(''.slice);
96941         var toLowerCase = uncurryThis(''.toLowerCase);
96942         var unshift = uncurryThis([].unshift);
96943
96944         var INVALID_AUTHORITY = 'Invalid authority';
96945         var INVALID_SCHEME = 'Invalid scheme';
96946         var INVALID_HOST = 'Invalid host';
96947         var INVALID_PORT = 'Invalid port';
96948
96949         var ALPHA = /[a-z]/i;
96950         // eslint-disable-next-line regexp/no-obscure-range -- safe
96951         var ALPHANUMERIC = /[\d+-.a-z]/i;
96952         var DIGIT = /\d/;
96953         var HEX_START = /^0x/i;
96954         var OCT = /^[0-7]+$/;
96955         var DEC = /^\d+$/;
96956         var HEX = /^[\da-f]+$/i;
96957         /* eslint-disable regexp/no-control-character -- safe */
96958         var FORBIDDEN_HOST_CODE_POINT = /[\0\t\n\r #%/:<>?@[\\\]^|]/;
96959         var FORBIDDEN_HOST_CODE_POINT_EXCLUDING_PERCENT = /[\0\t\n\r #/:<>?@[\\\]^|]/;
96960         var LEADING_AND_TRAILING_C0_CONTROL_OR_SPACE = /^[\u0000-\u0020]+|[\u0000-\u0020]+$/g;
96961         var TAB_AND_NEW_LINE = /[\t\n\r]/g;
96962         /* eslint-enable regexp/no-control-character -- safe */
96963         var EOF;
96964
96965         var parseHost = function (url, input) {
96966           var result, codePoints, index;
96967           if (charAt(input, 0) == '[') {
96968             if (charAt(input, input.length - 1) != ']') return INVALID_HOST;
96969             result = parseIPv6(stringSlice(input, 1, -1));
96970             if (!result) return INVALID_HOST;
96971             url.host = result;
96972           // opaque host
96973           } else if (!isSpecial(url)) {
96974             if (exec(FORBIDDEN_HOST_CODE_POINT_EXCLUDING_PERCENT, input)) return INVALID_HOST;
96975             result = '';
96976             codePoints = arrayFrom(input);
96977             for (index = 0; index < codePoints.length; index++) {
96978               result += percentEncode(codePoints[index], C0ControlPercentEncodeSet);
96979             }
96980             url.host = result;
96981           } else {
96982             input = toASCII(input);
96983             if (exec(FORBIDDEN_HOST_CODE_POINT, input)) return INVALID_HOST;
96984             result = parseIPv4(input);
96985             if (result === null) return INVALID_HOST;
96986             url.host = result;
96987           }
96988         };
96989
96990         var parseIPv4 = function (input) {
96991           var parts = split(input, '.');
96992           var partsLength, numbers, index, part, radix, number, ipv4;
96993           if (parts.length && parts[parts.length - 1] == '') {
96994             parts.length--;
96995           }
96996           partsLength = parts.length;
96997           if (partsLength > 4) return input;
96998           numbers = [];
96999           for (index = 0; index < partsLength; index++) {
97000             part = parts[index];
97001             if (part == '') return input;
97002             radix = 10;
97003             if (part.length > 1 && charAt(part, 0) == '0') {
97004               radix = exec(HEX_START, part) ? 16 : 8;
97005               part = stringSlice(part, radix == 8 ? 1 : 2);
97006             }
97007             if (part === '') {
97008               number = 0;
97009             } else {
97010               if (!exec(radix == 10 ? DEC : radix == 8 ? OCT : HEX, part)) return input;
97011               number = parseInt$1(part, radix);
97012             }
97013             push(numbers, number);
97014           }
97015           for (index = 0; index < partsLength; index++) {
97016             number = numbers[index];
97017             if (index == partsLength - 1) {
97018               if (number >= pow(256, 5 - partsLength)) return null;
97019             } else if (number > 255) return null;
97020           }
97021           ipv4 = pop(numbers);
97022           for (index = 0; index < numbers.length; index++) {
97023             ipv4 += numbers[index] * pow(256, 3 - index);
97024           }
97025           return ipv4;
97026         };
97027
97028         // eslint-disable-next-line max-statements -- TODO
97029         var parseIPv6 = function (input) {
97030           var address = [0, 0, 0, 0, 0, 0, 0, 0];
97031           var pieceIndex = 0;
97032           var compress = null;
97033           var pointer = 0;
97034           var value, length, numbersSeen, ipv4Piece, number, swaps, swap;
97035
97036           var chr = function () {
97037             return charAt(input, pointer);
97038           };
97039
97040           if (chr() == ':') {
97041             if (charAt(input, 1) != ':') return;
97042             pointer += 2;
97043             pieceIndex++;
97044             compress = pieceIndex;
97045           }
97046           while (chr()) {
97047             if (pieceIndex == 8) return;
97048             if (chr() == ':') {
97049               if (compress !== null) return;
97050               pointer++;
97051               pieceIndex++;
97052               compress = pieceIndex;
97053               continue;
97054             }
97055             value = length = 0;
97056             while (length < 4 && exec(HEX, chr())) {
97057               value = value * 16 + parseInt$1(chr(), 16);
97058               pointer++;
97059               length++;
97060             }
97061             if (chr() == '.') {
97062               if (length == 0) return;
97063               pointer -= length;
97064               if (pieceIndex > 6) return;
97065               numbersSeen = 0;
97066               while (chr()) {
97067                 ipv4Piece = null;
97068                 if (numbersSeen > 0) {
97069                   if (chr() == '.' && numbersSeen < 4) pointer++;
97070                   else return;
97071                 }
97072                 if (!exec(DIGIT, chr())) return;
97073                 while (exec(DIGIT, chr())) {
97074                   number = parseInt$1(chr(), 10);
97075                   if (ipv4Piece === null) ipv4Piece = number;
97076                   else if (ipv4Piece == 0) return;
97077                   else ipv4Piece = ipv4Piece * 10 + number;
97078                   if (ipv4Piece > 255) return;
97079                   pointer++;
97080                 }
97081                 address[pieceIndex] = address[pieceIndex] * 256 + ipv4Piece;
97082                 numbersSeen++;
97083                 if (numbersSeen == 2 || numbersSeen == 4) pieceIndex++;
97084               }
97085               if (numbersSeen != 4) return;
97086               break;
97087             } else if (chr() == ':') {
97088               pointer++;
97089               if (!chr()) return;
97090             } else if (chr()) return;
97091             address[pieceIndex++] = value;
97092           }
97093           if (compress !== null) {
97094             swaps = pieceIndex - compress;
97095             pieceIndex = 7;
97096             while (pieceIndex != 0 && swaps > 0) {
97097               swap = address[pieceIndex];
97098               address[pieceIndex--] = address[compress + swaps - 1];
97099               address[compress + --swaps] = swap;
97100             }
97101           } else if (pieceIndex != 8) return;
97102           return address;
97103         };
97104
97105         var findLongestZeroSequence = function (ipv6) {
97106           var maxIndex = null;
97107           var maxLength = 1;
97108           var currStart = null;
97109           var currLength = 0;
97110           var index = 0;
97111           for (; index < 8; index++) {
97112             if (ipv6[index] !== 0) {
97113               if (currLength > maxLength) {
97114                 maxIndex = currStart;
97115                 maxLength = currLength;
97116               }
97117               currStart = null;
97118               currLength = 0;
97119             } else {
97120               if (currStart === null) currStart = index;
97121               ++currLength;
97122             }
97123           }
97124           if (currLength > maxLength) {
97125             maxIndex = currStart;
97126             maxLength = currLength;
97127           }
97128           return maxIndex;
97129         };
97130
97131         var serializeHost = function (host) {
97132           var result, index, compress, ignore0;
97133           // ipv4
97134           if (typeof host == 'number') {
97135             result = [];
97136             for (index = 0; index < 4; index++) {
97137               unshift(result, host % 256);
97138               host = floor(host / 256);
97139             } return join(result, '.');
97140           // ipv6
97141           } else if (typeof host == 'object') {
97142             result = '';
97143             compress = findLongestZeroSequence(host);
97144             for (index = 0; index < 8; index++) {
97145               if (ignore0 && host[index] === 0) continue;
97146               if (ignore0) ignore0 = false;
97147               if (compress === index) {
97148                 result += index ? ':' : '::';
97149                 ignore0 = true;
97150               } else {
97151                 result += numberToString(host[index], 16);
97152                 if (index < 7) result += ':';
97153               }
97154             }
97155             return '[' + result + ']';
97156           } return host;
97157         };
97158
97159         var C0ControlPercentEncodeSet = {};
97160         var fragmentPercentEncodeSet = assign$1({}, C0ControlPercentEncodeSet, {
97161           ' ': 1, '"': 1, '<': 1, '>': 1, '`': 1
97162         });
97163         var pathPercentEncodeSet = assign$1({}, fragmentPercentEncodeSet, {
97164           '#': 1, '?': 1, '{': 1, '}': 1
97165         });
97166         var userinfoPercentEncodeSet = assign$1({}, pathPercentEncodeSet, {
97167           '/': 1, ':': 1, ';': 1, '=': 1, '@': 1, '[': 1, '\\': 1, ']': 1, '^': 1, '|': 1
97168         });
97169
97170         var percentEncode = function (chr, set) {
97171           var code = codeAt(chr, 0);
97172           return code > 0x20 && code < 0x7F && !hasOwn(set, chr) ? chr : encodeURIComponent(chr);
97173         };
97174
97175         var specialSchemes = {
97176           ftp: 21,
97177           file: null,
97178           http: 80,
97179           https: 443,
97180           ws: 80,
97181           wss: 443
97182         };
97183
97184         var isSpecial = function (url) {
97185           return hasOwn(specialSchemes, url.scheme);
97186         };
97187
97188         var includesCredentials = function (url) {
97189           return url.username != '' || url.password != '';
97190         };
97191
97192         var cannotHaveUsernamePasswordPort = function (url) {
97193           return !url.host || url.cannotBeABaseURL || url.scheme == 'file';
97194         };
97195
97196         var isWindowsDriveLetter = function (string, normalized) {
97197           var second;
97198           return string.length == 2 && exec(ALPHA, charAt(string, 0))
97199             && ((second = charAt(string, 1)) == ':' || (!normalized && second == '|'));
97200         };
97201
97202         var startsWithWindowsDriveLetter = function (string) {
97203           var third;
97204           return string.length > 1 && isWindowsDriveLetter(stringSlice(string, 0, 2)) && (
97205             string.length == 2 ||
97206             ((third = charAt(string, 2)) === '/' || third === '\\' || third === '?' || third === '#')
97207           );
97208         };
97209
97210         var shortenURLsPath = function (url) {
97211           var path = url.path;
97212           var pathSize = path.length;
97213           if (pathSize && (url.scheme != 'file' || pathSize != 1 || !isWindowsDriveLetter(path[0], true))) {
97214             path.length--;
97215           }
97216         };
97217
97218         var isSingleDot = function (segment) {
97219           return segment === '.' || toLowerCase(segment) === '%2e';
97220         };
97221
97222         var isDoubleDot = function (segment) {
97223           segment = toLowerCase(segment);
97224           return segment === '..' || segment === '%2e.' || segment === '.%2e' || segment === '%2e%2e';
97225         };
97226
97227         // States:
97228         var SCHEME_START = {};
97229         var SCHEME = {};
97230         var NO_SCHEME = {};
97231         var SPECIAL_RELATIVE_OR_AUTHORITY = {};
97232         var PATH_OR_AUTHORITY = {};
97233         var RELATIVE = {};
97234         var RELATIVE_SLASH = {};
97235         var SPECIAL_AUTHORITY_SLASHES = {};
97236         var SPECIAL_AUTHORITY_IGNORE_SLASHES = {};
97237         var AUTHORITY = {};
97238         var HOST = {};
97239         var HOSTNAME = {};
97240         var PORT = {};
97241         var FILE = {};
97242         var FILE_SLASH = {};
97243         var FILE_HOST = {};
97244         var PATH_START = {};
97245         var PATH = {};
97246         var CANNOT_BE_A_BASE_URL_PATH = {};
97247         var QUERY = {};
97248         var FRAGMENT = {};
97249
97250         // eslint-disable-next-line max-statements -- TODO
97251         var parseURL = function (url, input, stateOverride, base) {
97252           var state = stateOverride || SCHEME_START;
97253           var pointer = 0;
97254           var buffer = '';
97255           var seenAt = false;
97256           var seenBracket = false;
97257           var seenPasswordToken = false;
97258           var codePoints, chr, bufferCodePoints, failure;
97259
97260           if (!stateOverride) {
97261             url.scheme = '';
97262             url.username = '';
97263             url.password = '';
97264             url.host = null;
97265             url.port = null;
97266             url.path = [];
97267             url.query = null;
97268             url.fragment = null;
97269             url.cannotBeABaseURL = false;
97270             input = replace(input, LEADING_AND_TRAILING_C0_CONTROL_OR_SPACE, '');
97271           }
97272
97273           input = replace(input, TAB_AND_NEW_LINE, '');
97274
97275           codePoints = arrayFrom(input);
97276
97277           while (pointer <= codePoints.length) {
97278             chr = codePoints[pointer];
97279             switch (state) {
97280               case SCHEME_START:
97281                 if (chr && exec(ALPHA, chr)) {
97282                   buffer += toLowerCase(chr);
97283                   state = SCHEME;
97284                 } else if (!stateOverride) {
97285                   state = NO_SCHEME;
97286                   continue;
97287                 } else return INVALID_SCHEME;
97288                 break;
97289
97290               case SCHEME:
97291                 if (chr && (exec(ALPHANUMERIC, chr) || chr == '+' || chr == '-' || chr == '.')) {
97292                   buffer += toLowerCase(chr);
97293                 } else if (chr == ':') {
97294                   if (stateOverride && (
97295                     (isSpecial(url) != hasOwn(specialSchemes, buffer)) ||
97296                     (buffer == 'file' && (includesCredentials(url) || url.port !== null)) ||
97297                     (url.scheme == 'file' && !url.host)
97298                   )) return;
97299                   url.scheme = buffer;
97300                   if (stateOverride) {
97301                     if (isSpecial(url) && specialSchemes[url.scheme] == url.port) url.port = null;
97302                     return;
97303                   }
97304                   buffer = '';
97305                   if (url.scheme == 'file') {
97306                     state = FILE;
97307                   } else if (isSpecial(url) && base && base.scheme == url.scheme) {
97308                     state = SPECIAL_RELATIVE_OR_AUTHORITY;
97309                   } else if (isSpecial(url)) {
97310                     state = SPECIAL_AUTHORITY_SLASHES;
97311                   } else if (codePoints[pointer + 1] == '/') {
97312                     state = PATH_OR_AUTHORITY;
97313                     pointer++;
97314                   } else {
97315                     url.cannotBeABaseURL = true;
97316                     push(url.path, '');
97317                     state = CANNOT_BE_A_BASE_URL_PATH;
97318                   }
97319                 } else if (!stateOverride) {
97320                   buffer = '';
97321                   state = NO_SCHEME;
97322                   pointer = 0;
97323                   continue;
97324                 } else return INVALID_SCHEME;
97325                 break;
97326
97327               case NO_SCHEME:
97328                 if (!base || (base.cannotBeABaseURL && chr != '#')) return INVALID_SCHEME;
97329                 if (base.cannotBeABaseURL && chr == '#') {
97330                   url.scheme = base.scheme;
97331                   url.path = arraySlice(base.path);
97332                   url.query = base.query;
97333                   url.fragment = '';
97334                   url.cannotBeABaseURL = true;
97335                   state = FRAGMENT;
97336                   break;
97337                 }
97338                 state = base.scheme == 'file' ? FILE : RELATIVE;
97339                 continue;
97340
97341               case SPECIAL_RELATIVE_OR_AUTHORITY:
97342                 if (chr == '/' && codePoints[pointer + 1] == '/') {
97343                   state = SPECIAL_AUTHORITY_IGNORE_SLASHES;
97344                   pointer++;
97345                 } else {
97346                   state = RELATIVE;
97347                   continue;
97348                 } break;
97349
97350               case PATH_OR_AUTHORITY:
97351                 if (chr == '/') {
97352                   state = AUTHORITY;
97353                   break;
97354                 } else {
97355                   state = PATH;
97356                   continue;
97357                 }
97358
97359               case RELATIVE:
97360                 url.scheme = base.scheme;
97361                 if (chr == EOF) {
97362                   url.username = base.username;
97363                   url.password = base.password;
97364                   url.host = base.host;
97365                   url.port = base.port;
97366                   url.path = arraySlice(base.path);
97367                   url.query = base.query;
97368                 } else if (chr == '/' || (chr == '\\' && isSpecial(url))) {
97369                   state = RELATIVE_SLASH;
97370                 } else if (chr == '?') {
97371                   url.username = base.username;
97372                   url.password = base.password;
97373                   url.host = base.host;
97374                   url.port = base.port;
97375                   url.path = arraySlice(base.path);
97376                   url.query = '';
97377                   state = QUERY;
97378                 } else if (chr == '#') {
97379                   url.username = base.username;
97380                   url.password = base.password;
97381                   url.host = base.host;
97382                   url.port = base.port;
97383                   url.path = arraySlice(base.path);
97384                   url.query = base.query;
97385                   url.fragment = '';
97386                   state = FRAGMENT;
97387                 } else {
97388                   url.username = base.username;
97389                   url.password = base.password;
97390                   url.host = base.host;
97391                   url.port = base.port;
97392                   url.path = arraySlice(base.path);
97393                   url.path.length--;
97394                   state = PATH;
97395                   continue;
97396                 } break;
97397
97398               case RELATIVE_SLASH:
97399                 if (isSpecial(url) && (chr == '/' || chr == '\\')) {
97400                   state = SPECIAL_AUTHORITY_IGNORE_SLASHES;
97401                 } else if (chr == '/') {
97402                   state = AUTHORITY;
97403                 } else {
97404                   url.username = base.username;
97405                   url.password = base.password;
97406                   url.host = base.host;
97407                   url.port = base.port;
97408                   state = PATH;
97409                   continue;
97410                 } break;
97411
97412               case SPECIAL_AUTHORITY_SLASHES:
97413                 state = SPECIAL_AUTHORITY_IGNORE_SLASHES;
97414                 if (chr != '/' || charAt(buffer, pointer + 1) != '/') continue;
97415                 pointer++;
97416                 break;
97417
97418               case SPECIAL_AUTHORITY_IGNORE_SLASHES:
97419                 if (chr != '/' && chr != '\\') {
97420                   state = AUTHORITY;
97421                   continue;
97422                 } break;
97423
97424               case AUTHORITY:
97425                 if (chr == '@') {
97426                   if (seenAt) buffer = '%40' + buffer;
97427                   seenAt = true;
97428                   bufferCodePoints = arrayFrom(buffer);
97429                   for (var i = 0; i < bufferCodePoints.length; i++) {
97430                     var codePoint = bufferCodePoints[i];
97431                     if (codePoint == ':' && !seenPasswordToken) {
97432                       seenPasswordToken = true;
97433                       continue;
97434                     }
97435                     var encodedCodePoints = percentEncode(codePoint, userinfoPercentEncodeSet);
97436                     if (seenPasswordToken) url.password += encodedCodePoints;
97437                     else url.username += encodedCodePoints;
97438                   }
97439                   buffer = '';
97440                 } else if (
97441                   chr == EOF || chr == '/' || chr == '?' || chr == '#' ||
97442                   (chr == '\\' && isSpecial(url))
97443                 ) {
97444                   if (seenAt && buffer == '') return INVALID_AUTHORITY;
97445                   pointer -= arrayFrom(buffer).length + 1;
97446                   buffer = '';
97447                   state = HOST;
97448                 } else buffer += chr;
97449                 break;
97450
97451               case HOST:
97452               case HOSTNAME:
97453                 if (stateOverride && url.scheme == 'file') {
97454                   state = FILE_HOST;
97455                   continue;
97456                 } else if (chr == ':' && !seenBracket) {
97457                   if (buffer == '') return INVALID_HOST;
97458                   failure = parseHost(url, buffer);
97459                   if (failure) return failure;
97460                   buffer = '';
97461                   state = PORT;
97462                   if (stateOverride == HOSTNAME) return;
97463                 } else if (
97464                   chr == EOF || chr == '/' || chr == '?' || chr == '#' ||
97465                   (chr == '\\' && isSpecial(url))
97466                 ) {
97467                   if (isSpecial(url) && buffer == '') return INVALID_HOST;
97468                   if (stateOverride && buffer == '' && (includesCredentials(url) || url.port !== null)) return;
97469                   failure = parseHost(url, buffer);
97470                   if (failure) return failure;
97471                   buffer = '';
97472                   state = PATH_START;
97473                   if (stateOverride) return;
97474                   continue;
97475                 } else {
97476                   if (chr == '[') seenBracket = true;
97477                   else if (chr == ']') seenBracket = false;
97478                   buffer += chr;
97479                 } break;
97480
97481               case PORT:
97482                 if (exec(DIGIT, chr)) {
97483                   buffer += chr;
97484                 } else if (
97485                   chr == EOF || chr == '/' || chr == '?' || chr == '#' ||
97486                   (chr == '\\' && isSpecial(url)) ||
97487                   stateOverride
97488                 ) {
97489                   if (buffer != '') {
97490                     var port = parseInt$1(buffer, 10);
97491                     if (port > 0xFFFF) return INVALID_PORT;
97492                     url.port = (isSpecial(url) && port === specialSchemes[url.scheme]) ? null : port;
97493                     buffer = '';
97494                   }
97495                   if (stateOverride) return;
97496                   state = PATH_START;
97497                   continue;
97498                 } else return INVALID_PORT;
97499                 break;
97500
97501               case FILE:
97502                 url.scheme = 'file';
97503                 if (chr == '/' || chr == '\\') state = FILE_SLASH;
97504                 else if (base && base.scheme == 'file') {
97505                   if (chr == EOF) {
97506                     url.host = base.host;
97507                     url.path = arraySlice(base.path);
97508                     url.query = base.query;
97509                   } else if (chr == '?') {
97510                     url.host = base.host;
97511                     url.path = arraySlice(base.path);
97512                     url.query = '';
97513                     state = QUERY;
97514                   } else if (chr == '#') {
97515                     url.host = base.host;
97516                     url.path = arraySlice(base.path);
97517                     url.query = base.query;
97518                     url.fragment = '';
97519                     state = FRAGMENT;
97520                   } else {
97521                     if (!startsWithWindowsDriveLetter(join(arraySlice(codePoints, pointer), ''))) {
97522                       url.host = base.host;
97523                       url.path = arraySlice(base.path);
97524                       shortenURLsPath(url);
97525                     }
97526                     state = PATH;
97527                     continue;
97528                   }
97529                 } else {
97530                   state = PATH;
97531                   continue;
97532                 } break;
97533
97534               case FILE_SLASH:
97535                 if (chr == '/' || chr == '\\') {
97536                   state = FILE_HOST;
97537                   break;
97538                 }
97539                 if (base && base.scheme == 'file' && !startsWithWindowsDriveLetter(join(arraySlice(codePoints, pointer), ''))) {
97540                   if (isWindowsDriveLetter(base.path[0], true)) push(url.path, base.path[0]);
97541                   else url.host = base.host;
97542                 }
97543                 state = PATH;
97544                 continue;
97545
97546               case FILE_HOST:
97547                 if (chr == EOF || chr == '/' || chr == '\\' || chr == '?' || chr == '#') {
97548                   if (!stateOverride && isWindowsDriveLetter(buffer)) {
97549                     state = PATH;
97550                   } else if (buffer == '') {
97551                     url.host = '';
97552                     if (stateOverride) return;
97553                     state = PATH_START;
97554                   } else {
97555                     failure = parseHost(url, buffer);
97556                     if (failure) return failure;
97557                     if (url.host == 'localhost') url.host = '';
97558                     if (stateOverride) return;
97559                     buffer = '';
97560                     state = PATH_START;
97561                   } continue;
97562                 } else buffer += chr;
97563                 break;
97564
97565               case PATH_START:
97566                 if (isSpecial(url)) {
97567                   state = PATH;
97568                   if (chr != '/' && chr != '\\') continue;
97569                 } else if (!stateOverride && chr == '?') {
97570                   url.query = '';
97571                   state = QUERY;
97572                 } else if (!stateOverride && chr == '#') {
97573                   url.fragment = '';
97574                   state = FRAGMENT;
97575                 } else if (chr != EOF) {
97576                   state = PATH;
97577                   if (chr != '/') continue;
97578                 } break;
97579
97580               case PATH:
97581                 if (
97582                   chr == EOF || chr == '/' ||
97583                   (chr == '\\' && isSpecial(url)) ||
97584                   (!stateOverride && (chr == '?' || chr == '#'))
97585                 ) {
97586                   if (isDoubleDot(buffer)) {
97587                     shortenURLsPath(url);
97588                     if (chr != '/' && !(chr == '\\' && isSpecial(url))) {
97589                       push(url.path, '');
97590                     }
97591                   } else if (isSingleDot(buffer)) {
97592                     if (chr != '/' && !(chr == '\\' && isSpecial(url))) {
97593                       push(url.path, '');
97594                     }
97595                   } else {
97596                     if (url.scheme == 'file' && !url.path.length && isWindowsDriveLetter(buffer)) {
97597                       if (url.host) url.host = '';
97598                       buffer = charAt(buffer, 0) + ':'; // normalize windows drive letter
97599                     }
97600                     push(url.path, buffer);
97601                   }
97602                   buffer = '';
97603                   if (url.scheme == 'file' && (chr == EOF || chr == '?' || chr == '#')) {
97604                     while (url.path.length > 1 && url.path[0] === '') {
97605                       shift(url.path);
97606                     }
97607                   }
97608                   if (chr == '?') {
97609                     url.query = '';
97610                     state = QUERY;
97611                   } else if (chr == '#') {
97612                     url.fragment = '';
97613                     state = FRAGMENT;
97614                   }
97615                 } else {
97616                   buffer += percentEncode(chr, pathPercentEncodeSet);
97617                 } break;
97618
97619               case CANNOT_BE_A_BASE_URL_PATH:
97620                 if (chr == '?') {
97621                   url.query = '';
97622                   state = QUERY;
97623                 } else if (chr == '#') {
97624                   url.fragment = '';
97625                   state = FRAGMENT;
97626                 } else if (chr != EOF) {
97627                   url.path[0] += percentEncode(chr, C0ControlPercentEncodeSet);
97628                 } break;
97629
97630               case QUERY:
97631                 if (!stateOverride && chr == '#') {
97632                   url.fragment = '';
97633                   state = FRAGMENT;
97634                 } else if (chr != EOF) {
97635                   if (chr == "'" && isSpecial(url)) url.query += '%27';
97636                   else if (chr == '#') url.query += '%23';
97637                   else url.query += percentEncode(chr, C0ControlPercentEncodeSet);
97638                 } break;
97639
97640               case FRAGMENT:
97641                 if (chr != EOF) url.fragment += percentEncode(chr, fragmentPercentEncodeSet);
97642                 break;
97643             }
97644
97645             pointer++;
97646           }
97647         };
97648
97649         // `URL` constructor
97650         // https://url.spec.whatwg.org/#url-class
97651         var URLConstructor = function URL(url /* , base */) {
97652           var that = anInstance(this, URLPrototype);
97653           var base = arguments.length > 1 ? arguments[1] : undefined;
97654           var urlString = $toString(url);
97655           var state = setInternalState(that, { type: 'URL' });
97656           var baseState, failure;
97657           if (base !== undefined) {
97658             try {
97659               baseState = getInternalURLState(base);
97660             } catch (error) {
97661               failure = parseURL(baseState = {}, $toString(base));
97662               if (failure) throw TypeError$1(failure);
97663             }
97664           }
97665           failure = parseURL(state, urlString, null, baseState);
97666           if (failure) throw TypeError$1(failure);
97667           var searchParams = state.searchParams = new URLSearchParams$1();
97668           var searchParamsState = getInternalSearchParamsState(searchParams);
97669           searchParamsState.updateSearchParams(state.query);
97670           searchParamsState.updateURL = function () {
97671             state.query = $toString(searchParams) || null;
97672           };
97673           if (!DESCRIPTORS) {
97674             that.href = call(serializeURL, that);
97675             that.origin = call(getOrigin, that);
97676             that.protocol = call(getProtocol, that);
97677             that.username = call(getUsername, that);
97678             that.password = call(getPassword, that);
97679             that.host = call(getHost, that);
97680             that.hostname = call(getHostname, that);
97681             that.port = call(getPort, that);
97682             that.pathname = call(getPathname, that);
97683             that.search = call(getSearch, that);
97684             that.searchParams = call(getSearchParams, that);
97685             that.hash = call(getHash, that);
97686           }
97687         };
97688
97689         var URLPrototype = URLConstructor.prototype;
97690
97691         var serializeURL = function () {
97692           var url = getInternalURLState(this);
97693           var scheme = url.scheme;
97694           var username = url.username;
97695           var password = url.password;
97696           var host = url.host;
97697           var port = url.port;
97698           var path = url.path;
97699           var query = url.query;
97700           var fragment = url.fragment;
97701           var output = scheme + ':';
97702           if (host !== null) {
97703             output += '//';
97704             if (includesCredentials(url)) {
97705               output += username + (password ? ':' + password : '') + '@';
97706             }
97707             output += serializeHost(host);
97708             if (port !== null) output += ':' + port;
97709           } else if (scheme == 'file') output += '//';
97710           output += url.cannotBeABaseURL ? path[0] : path.length ? '/' + join(path, '/') : '';
97711           if (query !== null) output += '?' + query;
97712           if (fragment !== null) output += '#' + fragment;
97713           return output;
97714         };
97715
97716         var getOrigin = function () {
97717           var url = getInternalURLState(this);
97718           var scheme = url.scheme;
97719           var port = url.port;
97720           if (scheme == 'blob') try {
97721             return new URLConstructor(scheme.path[0]).origin;
97722           } catch (error) {
97723             return 'null';
97724           }
97725           if (scheme == 'file' || !isSpecial(url)) return 'null';
97726           return scheme + '://' + serializeHost(url.host) + (port !== null ? ':' + port : '');
97727         };
97728
97729         var getProtocol = function () {
97730           return getInternalURLState(this).scheme + ':';
97731         };
97732
97733         var getUsername = function () {
97734           return getInternalURLState(this).username;
97735         };
97736
97737         var getPassword = function () {
97738           return getInternalURLState(this).password;
97739         };
97740
97741         var getHost = function () {
97742           var url = getInternalURLState(this);
97743           var host = url.host;
97744           var port = url.port;
97745           return host === null ? ''
97746             : port === null ? serializeHost(host)
97747             : serializeHost(host) + ':' + port;
97748         };
97749
97750         var getHostname = function () {
97751           var host = getInternalURLState(this).host;
97752           return host === null ? '' : serializeHost(host);
97753         };
97754
97755         var getPort = function () {
97756           var port = getInternalURLState(this).port;
97757           return port === null ? '' : $toString(port);
97758         };
97759
97760         var getPathname = function () {
97761           var url = getInternalURLState(this);
97762           var path = url.path;
97763           return url.cannotBeABaseURL ? path[0] : path.length ? '/' + join(path, '/') : '';
97764         };
97765
97766         var getSearch = function () {
97767           var query = getInternalURLState(this).query;
97768           return query ? '?' + query : '';
97769         };
97770
97771         var getSearchParams = function () {
97772           return getInternalURLState(this).searchParams;
97773         };
97774
97775         var getHash = function () {
97776           var fragment = getInternalURLState(this).fragment;
97777           return fragment ? '#' + fragment : '';
97778         };
97779
97780         var accessorDescriptor = function (getter, setter) {
97781           return { get: getter, set: setter, configurable: true, enumerable: true };
97782         };
97783
97784         if (DESCRIPTORS) {
97785           defineProperties(URLPrototype, {
97786             // `URL.prototype.href` accessors pair
97787             // https://url.spec.whatwg.org/#dom-url-href
97788             href: accessorDescriptor(serializeURL, function (href) {
97789               var url = getInternalURLState(this);
97790               var urlString = $toString(href);
97791               var failure = parseURL(url, urlString);
97792               if (failure) throw TypeError$1(failure);
97793               getInternalSearchParamsState(url.searchParams).updateSearchParams(url.query);
97794             }),
97795             // `URL.prototype.origin` getter
97796             // https://url.spec.whatwg.org/#dom-url-origin
97797             origin: accessorDescriptor(getOrigin),
97798             // `URL.prototype.protocol` accessors pair
97799             // https://url.spec.whatwg.org/#dom-url-protocol
97800             protocol: accessorDescriptor(getProtocol, function (protocol) {
97801               var url = getInternalURLState(this);
97802               parseURL(url, $toString(protocol) + ':', SCHEME_START);
97803             }),
97804             // `URL.prototype.username` accessors pair
97805             // https://url.spec.whatwg.org/#dom-url-username
97806             username: accessorDescriptor(getUsername, function (username) {
97807               var url = getInternalURLState(this);
97808               var codePoints = arrayFrom($toString(username));
97809               if (cannotHaveUsernamePasswordPort(url)) return;
97810               url.username = '';
97811               for (var i = 0; i < codePoints.length; i++) {
97812                 url.username += percentEncode(codePoints[i], userinfoPercentEncodeSet);
97813               }
97814             }),
97815             // `URL.prototype.password` accessors pair
97816             // https://url.spec.whatwg.org/#dom-url-password
97817             password: accessorDescriptor(getPassword, function (password) {
97818               var url = getInternalURLState(this);
97819               var codePoints = arrayFrom($toString(password));
97820               if (cannotHaveUsernamePasswordPort(url)) return;
97821               url.password = '';
97822               for (var i = 0; i < codePoints.length; i++) {
97823                 url.password += percentEncode(codePoints[i], userinfoPercentEncodeSet);
97824               }
97825             }),
97826             // `URL.prototype.host` accessors pair
97827             // https://url.spec.whatwg.org/#dom-url-host
97828             host: accessorDescriptor(getHost, function (host) {
97829               var url = getInternalURLState(this);
97830               if (url.cannotBeABaseURL) return;
97831               parseURL(url, $toString(host), HOST);
97832             }),
97833             // `URL.prototype.hostname` accessors pair
97834             // https://url.spec.whatwg.org/#dom-url-hostname
97835             hostname: accessorDescriptor(getHostname, function (hostname) {
97836               var url = getInternalURLState(this);
97837               if (url.cannotBeABaseURL) return;
97838               parseURL(url, $toString(hostname), HOSTNAME);
97839             }),
97840             // `URL.prototype.port` accessors pair
97841             // https://url.spec.whatwg.org/#dom-url-port
97842             port: accessorDescriptor(getPort, function (port) {
97843               var url = getInternalURLState(this);
97844               if (cannotHaveUsernamePasswordPort(url)) return;
97845               port = $toString(port);
97846               if (port == '') url.port = null;
97847               else parseURL(url, port, PORT);
97848             }),
97849             // `URL.prototype.pathname` accessors pair
97850             // https://url.spec.whatwg.org/#dom-url-pathname
97851             pathname: accessorDescriptor(getPathname, function (pathname) {
97852               var url = getInternalURLState(this);
97853               if (url.cannotBeABaseURL) return;
97854               url.path = [];
97855               parseURL(url, $toString(pathname), PATH_START);
97856             }),
97857             // `URL.prototype.search` accessors pair
97858             // https://url.spec.whatwg.org/#dom-url-search
97859             search: accessorDescriptor(getSearch, function (search) {
97860               var url = getInternalURLState(this);
97861               search = $toString(search);
97862               if (search == '') {
97863                 url.query = null;
97864               } else {
97865                 if ('?' == charAt(search, 0)) search = stringSlice(search, 1);
97866                 url.query = '';
97867                 parseURL(url, search, QUERY);
97868               }
97869               getInternalSearchParamsState(url.searchParams).updateSearchParams(url.query);
97870             }),
97871             // `URL.prototype.searchParams` getter
97872             // https://url.spec.whatwg.org/#dom-url-searchparams
97873             searchParams: accessorDescriptor(getSearchParams),
97874             // `URL.prototype.hash` accessors pair
97875             // https://url.spec.whatwg.org/#dom-url-hash
97876             hash: accessorDescriptor(getHash, function (hash) {
97877               var url = getInternalURLState(this);
97878               hash = $toString(hash);
97879               if (hash == '') {
97880                 url.fragment = null;
97881                 return;
97882               }
97883               if ('#' == charAt(hash, 0)) hash = stringSlice(hash, 1);
97884               url.fragment = '';
97885               parseURL(url, hash, FRAGMENT);
97886             })
97887           });
97888         }
97889
97890         // `URL.prototype.toJSON` method
97891         // https://url.spec.whatwg.org/#dom-url-tojson
97892         redefine(URLPrototype, 'toJSON', function toJSON() {
97893           return call(serializeURL, this);
97894         }, { enumerable: true });
97895
97896         // `URL.prototype.toString` method
97897         // https://url.spec.whatwg.org/#URL-stringification-behavior
97898         redefine(URLPrototype, 'toString', function toString() {
97899           return call(serializeURL, this);
97900         }, { enumerable: true });
97901
97902         if (NativeURL) {
97903           var nativeCreateObjectURL = NativeURL.createObjectURL;
97904           var nativeRevokeObjectURL = NativeURL.revokeObjectURL;
97905           // `URL.createObjectURL` method
97906           // https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL
97907           if (nativeCreateObjectURL) redefine(URLConstructor, 'createObjectURL', bind$2(nativeCreateObjectURL, NativeURL));
97908           // `URL.revokeObjectURL` method
97909           // https://developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL
97910           if (nativeRevokeObjectURL) redefine(URLConstructor, 'revokeObjectURL', bind$2(nativeRevokeObjectURL, NativeURL));
97911         }
97912
97913         setToStringTag(URLConstructor, 'URL');
97914
97915         $({ global: true, forced: !USE_NATIVE_URL, sham: !DESCRIPTORS }, {
97916           URL: URLConstructor
97917         });
97918
97919         function uiFieldText(field, context) {
97920           var dispatch = dispatch$8('change');
97921           var input = select(null);
97922           var outlinkButton = select(null);
97923           var wrap = select(null);
97924           var _entityIDs = [];
97925
97926           var _tags;
97927
97928           var _phoneFormats = {};
97929
97930           if (field.type === 'tel') {
97931             _mainFileFetcher.get('phone_formats').then(function (d) {
97932               _phoneFormats = d;
97933               updatePhonePlaceholder();
97934             })["catch"](function () {
97935               /* ignore */
97936             });
97937           }
97938
97939           function calcLocked() {
97940             // Protect certain fields that have a companion `*:wikidata` value
97941             var isLocked = (field.id === 'brand' || field.id === 'network' || field.id === 'operator' || field.id === 'flag') && _entityIDs.length && _entityIDs.some(function (entityID) {
97942               var entity = context.graph().hasEntity(entityID);
97943               if (!entity) return false; // Features linked to Wikidata are likely important and should be protected
97944
97945               if (entity.tags.wikidata) return true;
97946               var preset = _mainPresetIndex.match(entity, context.graph());
97947               var isSuggestion = preset && preset.suggestion; // Lock the field if there is a value and a companion `*:wikidata` value
97948
97949               var which = field.id; // 'brand', 'network', 'operator', 'flag'
97950
97951               return isSuggestion && !!entity.tags[which] && !!entity.tags[which + ':wikidata'];
97952             });
97953
97954             field.locked(isLocked);
97955           }
97956
97957           function i(selection) {
97958             calcLocked();
97959             var isLocked = field.locked();
97960             wrap = selection.selectAll('.form-field-input-wrap').data([0]);
97961             wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
97962             input = wrap.selectAll('input').data([0]);
97963             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);
97964             input.classed('disabled', !!isLocked).attr('readonly', isLocked || null).on('input', change(true)).on('blur', change()).on('change', change());
97965
97966             if (field.type === 'tel') {
97967               updatePhonePlaceholder();
97968             } else if (field.type === 'number') {
97969               var rtl = _mainLocalizer.textDirection() === 'rtl';
97970               input.attr('type', 'text');
97971               var inc = field.increment;
97972               var buttons = wrap.selectAll('.increment, .decrement').data(rtl ? [inc, -inc] : [-inc, inc]);
97973               buttons.enter().append('button').attr('class', function (d) {
97974                 var which = d > 0 ? 'increment' : 'decrement';
97975                 return 'form-field-button ' + which;
97976               }).attr('title', function (d) {
97977                 var which = d > 0 ? 'increment' : 'decrement';
97978                 return _t("inspector.".concat(which));
97979               }).merge(buttons).on('click', function (d3_event, d) {
97980                 d3_event.preventDefault();
97981                 var raw_vals = input.node().value || '0';
97982                 var vals = raw_vals.split(';');
97983                 vals = vals.map(function (v) {
97984                   var num = parseFloat(v.trim(), 10);
97985                   return isFinite(num) ? clamped(num + d) : v.trim();
97986                 });
97987                 input.node().value = vals.join(';');
97988                 change()();
97989               });
97990             } else if (field.type === 'identifier' && field.urlFormat && field.pattern) {
97991               input.attr('type', 'text');
97992               outlinkButton = wrap.selectAll('.foreign-id-permalink').data([0]);
97993               outlinkButton.enter().append('button').call(svgIcon('#iD-icon-out-link')).attr('class', 'form-field-button foreign-id-permalink').attr('title', function () {
97994                 var domainResults = /^https?:\/\/(.{1,}?)\//.exec(field.urlFormat);
97995
97996                 if (domainResults.length >= 2 && domainResults[1]) {
97997                   var domain = domainResults[1];
97998                   return _t('icons.view_on', {
97999                     domain: domain
98000                   });
98001                 }
98002
98003                 return '';
98004               }).on('click', function (d3_event) {
98005                 d3_event.preventDefault();
98006                 var value = validIdentifierValueForLink();
98007
98008                 if (value) {
98009                   var url = field.urlFormat.replace(/{value}/, encodeURIComponent(value));
98010                   window.open(url, '_blank');
98011                 }
98012               }).merge(outlinkButton);
98013             } else if (field.type === 'url') {
98014               input.attr('type', 'text');
98015               outlinkButton = wrap.selectAll('.foreign-id-permalink').data([0]);
98016               outlinkButton.enter().append('button').call(svgIcon('#iD-icon-out-link')).attr('class', 'form-field-button foreign-id-permalink').attr('title', function () {
98017                 return _t('icons.visit_website');
98018               }).on('click', function (d3_event) {
98019                 d3_event.preventDefault();
98020                 var value = validIdentifierValueForLink();
98021                 if (value) window.open(value, '_blank');
98022               }).merge(outlinkButton);
98023             } else if (field.key.split(':').includes('colour')) {
98024               input.attr('type', 'text');
98025               updateColourPreview();
98026             }
98027           }
98028
98029           function isColourValid(colour) {
98030             if (!colour.match(/^(#([0-9a-fA-F]{3}){1,2}|\w+)$/)) {
98031               // OSM only supports hex or named colors
98032               return false;
98033             } else if (!CSS.supports('color', colour) || ['unset', 'inherit', 'initial', 'revert'].includes(colour)) {
98034               // see https://stackoverflow.com/a/68217760/1627467
98035               return false;
98036             }
98037
98038             return true;
98039           }
98040
98041           function updateColourPreview() {
98042             wrap.selectAll('.colour-preview').remove();
98043             var colour = utilGetSetValue(input);
98044             if (!isColourValid(colour) && colour !== '') return;
98045             var colourSelector = wrap.selectAll('.colour-selector').data([0]);
98046             outlinkButton = wrap.selectAll('.colour-preview').data([colour]);
98047             colourSelector.enter().append('input').attr('type', 'color').attr('class', 'form-field-button colour-selector').attr('value', colour).on('input', debounce(function (d3_event) {
98048               d3_event.preventDefault();
98049               var colour = this.value;
98050               if (!isColourValid(colour)) return;
98051               utilGetSetValue(input, this.value);
98052               change()();
98053               updateColourPreview();
98054             }, 100));
98055             outlinkButton = outlinkButton.enter().append('div').attr('class', 'form-field-button colour-preview').append('div').style('background-color', function (d) {
98056               return d;
98057             }).attr('class', 'colour-box');
98058
98059             if (colour === '') {
98060               outlinkButton = outlinkButton.call(svgIcon('#iD-icon-edit'));
98061             }
98062
98063             outlinkButton.on('click', function () {
98064               return wrap.select('.colour-selector').node().click();
98065             }).merge(outlinkButton);
98066           }
98067
98068           function updatePhonePlaceholder() {
98069             if (input.empty() || !Object.keys(_phoneFormats).length) return;
98070             var extent = combinedEntityExtent();
98071             var countryCode = extent && iso1A2Code(extent.center());
98072
98073             var format = countryCode && _phoneFormats[countryCode.toLowerCase()];
98074
98075             if (format) input.attr('placeholder', format);
98076           }
98077
98078           function validIdentifierValueForLink() {
98079             var value = utilGetSetValue(input).trim();
98080
98081             if (field.type === 'url' && value) {
98082               try {
98083                 return new URL(value).href;
98084               } catch (e) {
98085                 return null;
98086               }
98087             }
98088
98089             if (field.type === 'identifier' && field.pattern) {
98090               return value && value.match(new RegExp(field.pattern))[0];
98091             }
98092
98093             return null;
98094           } // clamp number to min/max
98095
98096
98097           function clamped(num) {
98098             if (field.minValue !== undefined) {
98099               num = Math.max(num, field.minValue);
98100             }
98101
98102             if (field.maxValue !== undefined) {
98103               num = Math.min(num, field.maxValue);
98104             }
98105
98106             return num;
98107           }
98108
98109           function change(onInput) {
98110             return function () {
98111               var t = {};
98112               var val = utilGetSetValue(input);
98113               if (!onInput) val = context.cleanTagValue(val); // don't override multiple values with blank string
98114
98115               if (!val && Array.isArray(_tags[field.key])) return;
98116
98117               if (!onInput) {
98118                 if (field.type === 'number' && val) {
98119                   var vals = val.split(';');
98120                   vals = vals.map(function (v) {
98121                     var num = parseFloat(v.trim(), 10);
98122                     return isFinite(num) ? clamped(num) : v.trim();
98123                   });
98124                   val = vals.join(';');
98125                 }
98126
98127                 utilGetSetValue(input, val);
98128               }
98129
98130               t[field.key] = val || undefined;
98131               dispatch.call('change', this, t, onInput);
98132             };
98133           }
98134
98135           i.entityIDs = function (val) {
98136             if (!arguments.length) return _entityIDs;
98137             _entityIDs = val;
98138             return i;
98139           };
98140
98141           i.tags = function (tags) {
98142             _tags = tags;
98143             var isMixed = Array.isArray(tags[field.key]);
98144             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);
98145             if (field.key.split(':').includes('colour')) updateColourPreview();
98146
98147             if (outlinkButton && !outlinkButton.empty()) {
98148               var disabled = !validIdentifierValueForLink();
98149               outlinkButton.classed('disabled', disabled);
98150             }
98151           };
98152
98153           i.focus = function () {
98154             var node = input.node();
98155             if (node) node.focus();
98156           };
98157
98158           function combinedEntityExtent() {
98159             return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
98160           }
98161
98162           return utilRebind(i, dispatch, 'on');
98163         }
98164
98165         function uiFieldAccess(field, context) {
98166           var dispatch = dispatch$8('change');
98167           var items = select(null);
98168
98169           var _tags;
98170
98171           function access(selection) {
98172             var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
98173             wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
98174             var list = wrap.selectAll('ul').data([0]);
98175             list = list.enter().append('ul').attr('class', 'rows').merge(list);
98176             items = list.selectAll('li').data(field.keys); // Enter
98177
98178             var enter = items.enter().append('li').attr('class', function (d) {
98179               return 'labeled-input preset-access-' + d;
98180             });
98181             enter.append('span').attr('class', 'label preset-label-access').attr('for', function (d) {
98182               return 'preset-input-access-' + d;
98183             }).html(function (d) {
98184               return field.t.html('types.' + d);
98185             });
98186             enter.append('div').attr('class', 'preset-input-access-wrap').append('input').attr('type', 'text').attr('class', function (d) {
98187               return 'preset-input-access preset-input-access-' + d;
98188             }).call(utilNoAuto).each(function (d) {
98189               select(this).call(uiCombobox(context, 'access-' + d).data(access.options(d)));
98190             }); // Update
98191
98192             items = items.merge(enter);
98193             wrap.selectAll('.preset-input-access').on('change', change).on('blur', change);
98194           }
98195
98196           function change(d3_event, d) {
98197             var tag = {};
98198             var value = context.cleanTagValue(utilGetSetValue(select(this))); // don't override multiple values with blank string
98199
98200             if (!value && typeof _tags[d] !== 'string') return;
98201             tag[d] = value || undefined;
98202             dispatch.call('change', this, tag);
98203           }
98204
98205           access.options = function (type) {
98206             var options = ['no', 'permissive', 'private', 'permit', 'destination', 'customers', 'unknown'];
98207
98208             if (type !== 'access') {
98209               options.unshift('yes');
98210               options.push('designated');
98211
98212               if (type === 'bicycle') {
98213                 options.push('dismount');
98214               }
98215             }
98216
98217             return options.map(function (option) {
98218               return {
98219                 title: field.t('options.' + option + '.description'),
98220                 value: option
98221               };
98222             });
98223           };
98224
98225           var placeholdersByHighway = {
98226             footway: {
98227               foot: 'designated',
98228               motor_vehicle: 'no'
98229             },
98230             steps: {
98231               foot: 'yes',
98232               motor_vehicle: 'no',
98233               bicycle: 'no',
98234               horse: 'no'
98235             },
98236             pedestrian: {
98237               foot: 'yes',
98238               motor_vehicle: 'no'
98239             },
98240             cycleway: {
98241               motor_vehicle: 'no',
98242               bicycle: 'designated'
98243             },
98244             bridleway: {
98245               motor_vehicle: 'no',
98246               horse: 'designated'
98247             },
98248             path: {
98249               foot: 'yes',
98250               motor_vehicle: 'no',
98251               bicycle: 'yes',
98252               horse: 'yes'
98253             },
98254             motorway: {
98255               foot: 'no',
98256               motor_vehicle: 'yes',
98257               bicycle: 'no',
98258               horse: 'no'
98259             },
98260             trunk: {
98261               motor_vehicle: 'yes'
98262             },
98263             primary: {
98264               foot: 'yes',
98265               motor_vehicle: 'yes',
98266               bicycle: 'yes',
98267               horse: 'yes'
98268             },
98269             secondary: {
98270               foot: 'yes',
98271               motor_vehicle: 'yes',
98272               bicycle: 'yes',
98273               horse: 'yes'
98274             },
98275             tertiary: {
98276               foot: 'yes',
98277               motor_vehicle: 'yes',
98278               bicycle: 'yes',
98279               horse: 'yes'
98280             },
98281             residential: {
98282               foot: 'yes',
98283               motor_vehicle: 'yes',
98284               bicycle: 'yes',
98285               horse: 'yes'
98286             },
98287             unclassified: {
98288               foot: 'yes',
98289               motor_vehicle: 'yes',
98290               bicycle: 'yes',
98291               horse: 'yes'
98292             },
98293             service: {
98294               foot: 'yes',
98295               motor_vehicle: 'yes',
98296               bicycle: 'yes',
98297               horse: 'yes'
98298             },
98299             motorway_link: {
98300               foot: 'no',
98301               motor_vehicle: 'yes',
98302               bicycle: 'no',
98303               horse: 'no'
98304             },
98305             trunk_link: {
98306               motor_vehicle: 'yes'
98307             },
98308             primary_link: {
98309               foot: 'yes',
98310               motor_vehicle: 'yes',
98311               bicycle: 'yes',
98312               horse: 'yes'
98313             },
98314             secondary_link: {
98315               foot: 'yes',
98316               motor_vehicle: 'yes',
98317               bicycle: 'yes',
98318               horse: 'yes'
98319             },
98320             tertiary_link: {
98321               foot: 'yes',
98322               motor_vehicle: 'yes',
98323               bicycle: 'yes',
98324               horse: 'yes'
98325             }
98326           };
98327
98328           access.tags = function (tags) {
98329             _tags = tags;
98330             utilGetSetValue(items.selectAll('.preset-input-access'), function (d) {
98331               return typeof tags[d] === 'string' ? tags[d] : '';
98332             }).classed('mixed', function (d) {
98333               return tags[d] && Array.isArray(tags[d]);
98334             }).attr('title', function (d) {
98335               return tags[d] && Array.isArray(tags[d]) && tags[d].filter(Boolean).join('\n');
98336             }).attr('placeholder', function (d) {
98337               if (tags[d] && Array.isArray(tags[d])) {
98338                 return _t('inspector.multiple_values');
98339               }
98340
98341               if (d === 'access') {
98342                 return 'yes';
98343               }
98344
98345               if (tags.access && typeof tags.access === 'string') {
98346                 return tags.access;
98347               }
98348
98349               if (tags.highway) {
98350                 if (typeof tags.highway === 'string') {
98351                   if (placeholdersByHighway[tags.highway] && placeholdersByHighway[tags.highway][d]) {
98352                     return placeholdersByHighway[tags.highway][d];
98353                   }
98354                 } else {
98355                   var impliedAccesses = tags.highway.filter(Boolean).map(function (highwayVal) {
98356                     return placeholdersByHighway[highwayVal] && placeholdersByHighway[highwayVal][d];
98357                   }).filter(Boolean);
98358
98359                   if (impliedAccesses.length === tags.highway.length && new Set(impliedAccesses).size === 1) {
98360                     // if all the highway values have the same implied access for this type then use that
98361                     return impliedAccesses[0];
98362                   }
98363                 }
98364               }
98365
98366               return field.placeholder();
98367             });
98368           };
98369
98370           access.focus = function () {
98371             items.selectAll('.preset-input-access').node().focus();
98372           };
98373
98374           return utilRebind(access, dispatch, 'on');
98375         }
98376
98377         function uiFieldAddress(field, context) {
98378           var dispatch = dispatch$8('change');
98379
98380           var _selection = select(null);
98381
98382           var _wrap = select(null);
98383
98384           var addrField = _mainPresetIndex.field('address'); // needed for placeholder strings
98385
98386           var _entityIDs = [];
98387
98388           var _tags;
98389
98390           var _countryCode;
98391
98392           var _addressFormats = [{
98393             format: [['housenumber', 'street'], ['city', 'postcode']]
98394           }];
98395           _mainFileFetcher.get('address_formats').then(function (d) {
98396             _addressFormats = d;
98397
98398             if (!_selection.empty()) {
98399               _selection.call(address);
98400             }
98401           })["catch"](function () {
98402             /* ignore */
98403           });
98404
98405           function getNearStreets() {
98406             var extent = combinedEntityExtent();
98407             var l = extent.center();
98408             var box = geoExtent(l).padByMeters(200);
98409             var streets = context.history().intersects(box).filter(isAddressable).map(function (d) {
98410               var loc = context.projection([(extent[0][0] + extent[1][0]) / 2, (extent[0][1] + extent[1][1]) / 2]);
98411               var choice = geoChooseEdge(context.graph().childNodes(d), loc, context.projection);
98412               return {
98413                 title: d.tags.name,
98414                 value: d.tags.name,
98415                 dist: choice.distance
98416               };
98417             }).sort(function (a, b) {
98418               return a.dist - b.dist;
98419             });
98420             return utilArrayUniqBy(streets, 'value');
98421
98422             function isAddressable(d) {
98423               return d.tags.highway && d.tags.name && d.type === 'way';
98424             }
98425           }
98426
98427           function getNearCities() {
98428             var extent = combinedEntityExtent();
98429             var l = extent.center();
98430             var box = geoExtent(l).padByMeters(200);
98431             var cities = context.history().intersects(box).filter(isAddressable).map(function (d) {
98432               return {
98433                 title: d.tags['addr:city'] || d.tags.name,
98434                 value: d.tags['addr:city'] || d.tags.name,
98435                 dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
98436               };
98437             }).sort(function (a, b) {
98438               return a.dist - b.dist;
98439             });
98440             return utilArrayUniqBy(cities, 'value');
98441
98442             function isAddressable(d) {
98443               if (d.tags.name) {
98444                 if (d.tags.admin_level === '8' && d.tags.boundary === 'administrative') return true;
98445                 if (d.tags.border_type === 'city') return true;
98446                 if (d.tags.place === 'city' || d.tags.place === 'town' || d.tags.place === 'village') return true;
98447               }
98448
98449               if (d.tags['addr:city']) return true;
98450               return false;
98451             }
98452           }
98453
98454           function getNearValues(key) {
98455             var extent = combinedEntityExtent();
98456             var l = extent.center();
98457             var box = geoExtent(l).padByMeters(200);
98458             var results = context.history().intersects(box).filter(function hasTag(d) {
98459               return _entityIDs.indexOf(d.id) === -1 && d.tags[key];
98460             }).map(function (d) {
98461               return {
98462                 title: d.tags[key],
98463                 value: d.tags[key],
98464                 dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
98465               };
98466             }).sort(function (a, b) {
98467               return a.dist - b.dist;
98468             });
98469             return utilArrayUniqBy(results, 'value');
98470           }
98471
98472           function updateForCountryCode() {
98473             if (!_countryCode) return;
98474             var addressFormat;
98475
98476             for (var i = 0; i < _addressFormats.length; i++) {
98477               var format = _addressFormats[i];
98478
98479               if (!format.countryCodes) {
98480                 addressFormat = format; // choose the default format, keep going
98481               } else if (format.countryCodes.indexOf(_countryCode) !== -1) {
98482                 addressFormat = format; // choose the country format, stop here
98483
98484                 break;
98485               }
98486             }
98487
98488             var dropdowns = addressFormat.dropdowns || ['city', 'county', 'country', 'district', 'hamlet', 'neighbourhood', 'place', 'postcode', 'province', 'quarter', 'state', 'street', 'subdistrict', 'suburb'];
98489             var widths = addressFormat.widths || {
98490               housenumber: 1 / 3,
98491               street: 2 / 3,
98492               city: 2 / 3,
98493               state: 1 / 4,
98494               postcode: 1 / 3
98495             };
98496
98497             function row(r) {
98498               // Normalize widths.
98499               var total = r.reduce(function (sum, key) {
98500                 return sum + (widths[key] || 0.5);
98501               }, 0);
98502               return r.map(function (key) {
98503                 return {
98504                   id: key,
98505                   width: (widths[key] || 0.5) / total
98506                 };
98507               });
98508             }
98509
98510             var rows = _wrap.selectAll('.addr-row').data(addressFormat.format, function (d) {
98511               return d.toString();
98512             });
98513
98514             rows.exit().remove();
98515             rows.enter().append('div').attr('class', 'addr-row').selectAll('input').data(row).enter().append('input').property('type', 'text').call(updatePlaceholder).attr('class', function (d) {
98516               return 'addr-' + d.id;
98517             }).call(utilNoAuto).each(addDropdown).style('width', function (d) {
98518               return d.width * 100 + '%';
98519             });
98520
98521             function addDropdown(d) {
98522               if (dropdowns.indexOf(d.id) === -1) return; // not a dropdown
98523
98524               var nearValues = d.id === 'street' ? getNearStreets : d.id === 'city' ? getNearCities : getNearValues;
98525               select(this).call(uiCombobox(context, 'address-' + d.id).minItems(1).caseSensitive(true).fetcher(function (value, callback) {
98526                 callback(nearValues('addr:' + d.id));
98527               }));
98528             }
98529
98530             _wrap.selectAll('input').on('blur', change()).on('change', change());
98531
98532             _wrap.selectAll('input:not(.combobox-input)').on('input', change(true));
98533
98534             if (_tags) updateTags(_tags);
98535           }
98536
98537           function address(selection) {
98538             _selection = selection;
98539             _wrap = selection.selectAll('.form-field-input-wrap').data([0]);
98540             _wrap = _wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(_wrap);
98541             var extent = combinedEntityExtent();
98542
98543             if (extent) {
98544               var countryCode;
98545
98546               if (context.inIntro()) {
98547                 // localize the address format for the walkthrough
98548                 countryCode = _t('intro.graph.countrycode');
98549               } else {
98550                 var center = extent.center();
98551                 countryCode = iso1A2Code(center);
98552               }
98553
98554               if (countryCode) {
98555                 _countryCode = countryCode.toLowerCase();
98556                 updateForCountryCode();
98557               }
98558             }
98559           }
98560
98561           function change(onInput) {
98562             return function () {
98563               var tags = {};
98564
98565               _wrap.selectAll('input').each(function (subfield) {
98566                 var key = field.key + ':' + subfield.id;
98567                 var value = this.value;
98568                 if (!onInput) value = context.cleanTagValue(value); // don't override multiple values with blank string
98569
98570                 if (Array.isArray(_tags[key]) && !value) return;
98571                 tags[key] = value || undefined;
98572               });
98573
98574               dispatch.call('change', this, tags, onInput);
98575             };
98576           }
98577
98578           function updatePlaceholder(inputSelection) {
98579             return inputSelection.attr('placeholder', function (subfield) {
98580               if (_tags && Array.isArray(_tags[field.key + ':' + subfield.id])) {
98581                 return _t('inspector.multiple_values');
98582               }
98583
98584               if (_countryCode) {
98585                 var localkey = subfield.id + '!' + _countryCode;
98586                 var tkey = addrField.hasTextForStringId('placeholders.' + localkey) ? localkey : subfield.id;
98587                 return addrField.t('placeholders.' + tkey);
98588               }
98589             });
98590           }
98591
98592           function updateTags(tags) {
98593             utilGetSetValue(_wrap.selectAll('input'), function (subfield) {
98594               var val = tags[field.key + ':' + subfield.id];
98595               return typeof val === 'string' ? val : '';
98596             }).attr('title', function (subfield) {
98597               var val = tags[field.key + ':' + subfield.id];
98598               return val && Array.isArray(val) ? val.filter(Boolean).join('\n') : undefined;
98599             }).classed('mixed', function (subfield) {
98600               return Array.isArray(tags[field.key + ':' + subfield.id]);
98601             }).call(updatePlaceholder);
98602           }
98603
98604           function combinedEntityExtent() {
98605             return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
98606           }
98607
98608           address.entityIDs = function (val) {
98609             if (!arguments.length) return _entityIDs;
98610             _entityIDs = val;
98611             return address;
98612           };
98613
98614           address.tags = function (tags) {
98615             _tags = tags;
98616             updateTags(tags);
98617           };
98618
98619           address.focus = function () {
98620             var node = _wrap.selectAll('input').node();
98621
98622             if (node) node.focus();
98623           };
98624
98625           return utilRebind(address, dispatch, 'on');
98626         }
98627
98628         function uiFieldCycleway(field, context) {
98629           var dispatch = dispatch$8('change');
98630           var items = select(null);
98631           var wrap = select(null);
98632
98633           var _tags;
98634
98635           function cycleway(selection) {
98636             function stripcolon(s) {
98637               return s.replace(':', '');
98638             }
98639
98640             wrap = selection.selectAll('.form-field-input-wrap').data([0]);
98641             wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
98642             var div = wrap.selectAll('ul').data([0]);
98643             div = div.enter().append('ul').attr('class', 'rows').merge(div);
98644             var keys = ['cycleway:left', 'cycleway:right'];
98645             items = div.selectAll('li').data(keys);
98646             var enter = items.enter().append('li').attr('class', function (d) {
98647               return 'labeled-input preset-cycleway-' + stripcolon(d);
98648             });
98649             enter.append('span').attr('class', 'label preset-label-cycleway').attr('for', function (d) {
98650               return 'preset-input-cycleway-' + stripcolon(d);
98651             }).html(function (d) {
98652               return field.t.html('types.' + d);
98653             });
98654             enter.append('div').attr('class', 'preset-input-cycleway-wrap').append('input').attr('type', 'text').attr('class', function (d) {
98655               return 'preset-input-cycleway preset-input-' + stripcolon(d);
98656             }).call(utilNoAuto).each(function (d) {
98657               select(this).call(uiCombobox(context, 'cycleway-' + stripcolon(d)).data(cycleway.options(d)));
98658             });
98659             items = items.merge(enter); // Update
98660
98661             wrap.selectAll('.preset-input-cycleway').on('change', change).on('blur', change);
98662           }
98663
98664           function change(d3_event, key) {
98665             var newValue = context.cleanTagValue(utilGetSetValue(select(this))); // don't override multiple values with blank string
98666
98667             if (!newValue && (Array.isArray(_tags.cycleway) || Array.isArray(_tags[key]))) return;
98668
98669             if (newValue === 'none' || newValue === '') {
98670               newValue = undefined;
98671             }
98672
98673             var otherKey = key === 'cycleway:left' ? 'cycleway:right' : 'cycleway:left';
98674             var otherValue = typeof _tags.cycleway === 'string' ? _tags.cycleway : _tags[otherKey];
98675
98676             if (otherValue && Array.isArray(otherValue)) {
98677               // we must always have an explicit value for comparison
98678               otherValue = otherValue[0];
98679             }
98680
98681             if (otherValue === 'none' || otherValue === '') {
98682               otherValue = undefined;
98683             }
98684
98685             var tag = {}; // If the left and right tags match, use the cycleway tag to tag both
98686             // sides the same way
98687
98688             if (newValue === otherValue) {
98689               tag = {
98690                 cycleway: newValue,
98691                 'cycleway:left': undefined,
98692                 'cycleway:right': undefined
98693               };
98694             } else {
98695               // Always set both left and right as changing one can affect the other
98696               tag = {
98697                 cycleway: undefined
98698               };
98699               tag[key] = newValue;
98700               tag[otherKey] = otherValue;
98701             }
98702
98703             dispatch.call('change', this, tag);
98704           }
98705
98706           cycleway.options = function () {
98707             return field.options.map(function (option) {
98708               return {
98709                 title: field.t('options.' + option + '.description'),
98710                 value: option
98711               };
98712             });
98713           };
98714
98715           cycleway.tags = function (tags) {
98716             _tags = tags; // If cycleway is set, use that instead of individual values
98717
98718             var commonValue = typeof tags.cycleway === 'string' && tags.cycleway;
98719             utilGetSetValue(items.selectAll('.preset-input-cycleway'), function (d) {
98720               if (commonValue) return commonValue;
98721               return !tags.cycleway && typeof tags[d] === 'string' ? tags[d] : '';
98722             }).attr('title', function (d) {
98723               if (Array.isArray(tags.cycleway) || Array.isArray(tags[d])) {
98724                 var vals = [];
98725
98726                 if (Array.isArray(tags.cycleway)) {
98727                   vals = vals.concat(tags.cycleway);
98728                 }
98729
98730                 if (Array.isArray(tags[d])) {
98731                   vals = vals.concat(tags[d]);
98732                 }
98733
98734                 return vals.filter(Boolean).join('\n');
98735               }
98736
98737               return null;
98738             }).attr('placeholder', function (d) {
98739               if (Array.isArray(tags.cycleway) || Array.isArray(tags[d])) {
98740                 return _t('inspector.multiple_values');
98741               }
98742
98743               return field.placeholder();
98744             }).classed('mixed', function (d) {
98745               return Array.isArray(tags.cycleway) || Array.isArray(tags[d]);
98746             });
98747           };
98748
98749           cycleway.focus = function () {
98750             var node = wrap.selectAll('input').node();
98751             if (node) node.focus();
98752           };
98753
98754           return utilRebind(cycleway, dispatch, 'on');
98755         }
98756
98757         function uiFieldLanes(field, context) {
98758           var dispatch = dispatch$8('change');
98759           var LANE_WIDTH = 40;
98760           var LANE_HEIGHT = 200;
98761           var _entityIDs = [];
98762
98763           function lanes(selection) {
98764             var lanesData = context.entity(_entityIDs[0]).lanes();
98765
98766             if (!context.container().select('.inspector-wrap.inspector-hidden').empty() || !selection.node().parentNode) {
98767               selection.call(lanes.off);
98768               return;
98769             }
98770
98771             var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
98772             wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
98773             var surface = wrap.selectAll('.surface').data([0]);
98774             var d = utilGetDimensions(wrap);
98775             var freeSpace = d[0] - lanesData.lanes.length * LANE_WIDTH * 1.5 + LANE_WIDTH * 0.5;
98776             surface = surface.enter().append('svg').attr('width', d[0]).attr('height', 300).attr('class', 'surface').merge(surface);
98777             var lanesSelection = surface.selectAll('.lanes').data([0]);
98778             lanesSelection = lanesSelection.enter().append('g').attr('class', 'lanes').merge(lanesSelection);
98779             lanesSelection.attr('transform', function () {
98780               return 'translate(' + freeSpace / 2 + ', 0)';
98781             });
98782             var lane = lanesSelection.selectAll('.lane').data(lanesData.lanes);
98783             lane.exit().remove();
98784             var enter = lane.enter().append('g').attr('class', 'lane');
98785             enter.append('g').append('rect').attr('y', 50).attr('width', LANE_WIDTH).attr('height', LANE_HEIGHT);
98786             enter.append('g').attr('class', 'forward').append('text').attr('y', 40).attr('x', 14).text('▲');
98787             enter.append('g').attr('class', 'bothways').append('text').attr('y', 40).attr('x', 14).text('▲▼');
98788             enter.append('g').attr('class', 'backward').append('text').attr('y', 40).attr('x', 14).text('▼');
98789             lane = lane.merge(enter);
98790             lane.attr('transform', function (d) {
98791               return 'translate(' + LANE_WIDTH * d.index * 1.5 + ', 0)';
98792             });
98793             lane.select('.forward').style('visibility', function (d) {
98794               return d.direction === 'forward' ? 'visible' : 'hidden';
98795             });
98796             lane.select('.bothways').style('visibility', function (d) {
98797               return d.direction === 'bothways' ? 'visible' : 'hidden';
98798             });
98799             lane.select('.backward').style('visibility', function (d) {
98800               return d.direction === 'backward' ? 'visible' : 'hidden';
98801             });
98802           }
98803
98804           lanes.entityIDs = function (val) {
98805             _entityIDs = val;
98806           };
98807
98808           lanes.tags = function () {};
98809
98810           lanes.focus = function () {};
98811
98812           lanes.off = function () {};
98813
98814           return utilRebind(lanes, dispatch, 'on');
98815         }
98816         uiFieldLanes.supportsMultiselection = false;
98817
98818         var _languagesArray = [];
98819         function uiFieldLocalized(field, context) {
98820           var dispatch = dispatch$8('change', 'input');
98821           var wikipedia = services.wikipedia;
98822           var input = select(null);
98823           var localizedInputs = select(null);
98824
98825           var _countryCode;
98826
98827           var _tags; // A concern here in switching to async data means that _languagesArray will not
98828           // be available the first time through, so things like the fetchers and
98829           // the language() function will not work immediately.
98830
98831
98832           _mainFileFetcher.get('languages').then(loadLanguagesArray)["catch"](function () {
98833             /* ignore */
98834           });
98835           var _territoryLanguages = {};
98836           _mainFileFetcher.get('territory_languages').then(function (d) {
98837             _territoryLanguages = d;
98838           })["catch"](function () {
98839             /* ignore */
98840           }); // reuse these combos
98841
98842           var langCombo = uiCombobox(context, 'localized-lang').fetcher(fetchLanguages).minItems(0);
98843
98844           var _selection = select(null);
98845
98846           var _multilingual = [];
98847
98848           var _buttonTip = uiTooltip().title(_t.html('translate.translate')).placement('left');
98849
98850           var _wikiTitles;
98851
98852           var _entityIDs = [];
98853
98854           function loadLanguagesArray(dataLanguages) {
98855             if (_languagesArray.length !== 0) return; // some conversion is needed to ensure correct OSM tags are used
98856
98857             var replacements = {
98858               sr: 'sr-Cyrl',
98859               // in OSM, `sr` implies Cyrillic
98860               'sr-Cyrl': false // `sr-Cyrl` isn't used in OSM
98861
98862             };
98863
98864             for (var code in dataLanguages) {
98865               if (replacements[code] === false) continue;
98866               var metaCode = code;
98867               if (replacements[code]) metaCode = replacements[code];
98868
98869               _languagesArray.push({
98870                 localName: _mainLocalizer.languageName(metaCode, {
98871                   localOnly: true
98872                 }),
98873                 nativeName: dataLanguages[metaCode].nativeName,
98874                 code: code,
98875                 label: _mainLocalizer.languageName(metaCode)
98876               });
98877             }
98878           }
98879
98880           function calcLocked() {
98881             // Protect name field for suggestion presets that don't display a brand/operator field
98882             var isLocked = field.id === 'name' && _entityIDs.length && _entityIDs.some(function (entityID) {
98883               var entity = context.graph().hasEntity(entityID);
98884               if (!entity) return false; // Features linked to Wikidata are likely important and should be protected
98885
98886               if (entity.tags.wikidata) return true; // Assume the name has already been confirmed if its source has been researched
98887
98888               if (entity.tags['name:etymology:wikidata']) return true; // Lock the `name` if this is a suggestion preset that assigns the name,
98889               // and the preset does not display a `brand` or `operator` field.
98890               // (For presets like hotels, car dealerships, post offices, the `name` should remain editable)
98891               // see also similar logic in `outdated_tags.js`
98892
98893               var preset = _mainPresetIndex.match(entity, context.graph());
98894
98895               if (preset) {
98896                 var isSuggestion = preset.suggestion;
98897                 var fields = preset.fields();
98898                 var showsBrandField = fields.some(function (d) {
98899                   return d.id === 'brand';
98900                 });
98901                 var showsOperatorField = fields.some(function (d) {
98902                   return d.id === 'operator';
98903                 });
98904                 var setsName = preset.addTags.name;
98905                 var setsBrandWikidata = preset.addTags['brand:wikidata'];
98906                 var setsOperatorWikidata = preset.addTags['operator:wikidata'];
98907                 return isSuggestion && setsName && (setsBrandWikidata && !showsBrandField || setsOperatorWikidata && !showsOperatorField);
98908               }
98909
98910               return false;
98911             });
98912
98913             field.locked(isLocked);
98914           } // update _multilingual, maintaining the existing order
98915
98916
98917           function calcMultilingual(tags) {
98918             var existingLangsOrdered = _multilingual.map(function (item) {
98919               return item.lang;
98920             });
98921
98922             var existingLangs = new Set(existingLangsOrdered.filter(Boolean));
98923
98924             for (var k in tags) {
98925               var m = k.match(/^(.*):(.*)$/);
98926
98927               if (m && m[1] === field.key && m[2]) {
98928                 var item = {
98929                   lang: m[2],
98930                   value: tags[k]
98931                 };
98932
98933                 if (existingLangs.has(item.lang)) {
98934                   // update the value
98935                   _multilingual[existingLangsOrdered.indexOf(item.lang)].value = item.value;
98936                   existingLangs["delete"](item.lang);
98937                 } else {
98938                   _multilingual.push(item);
98939                 }
98940               }
98941             } // Don't remove items based on deleted tags, since this makes the UI
98942             // disappear unexpectedly when clearing values - #8164
98943
98944
98945             _multilingual.forEach(function (item) {
98946               if (item.lang && existingLangs.has(item.lang)) {
98947                 item.value = '';
98948               }
98949             });
98950           }
98951
98952           function localized(selection) {
98953             _selection = selection;
98954             calcLocked();
98955             var isLocked = field.locked();
98956             var wrap = selection.selectAll('.form-field-input-wrap').data([0]); // enter/update
98957
98958             wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
98959             input = wrap.selectAll('.localized-main').data([0]); // enter/update
98960
98961             input = input.enter().append('input').attr('type', 'text').attr('id', field.domId).attr('class', 'localized-main').call(utilNoAuto).merge(input);
98962             input.classed('disabled', !!isLocked).attr('readonly', isLocked || null).on('input', change(true)).on('blur', change()).on('change', change());
98963             var translateButton = wrap.selectAll('.localized-add').data([0]);
98964             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);
98965             translateButton.classed('disabled', !!isLocked).call(isLocked ? _buttonTip.destroy : _buttonTip).on('click', addNew);
98966
98967             if (_tags && !_multilingual.length) {
98968               calcMultilingual(_tags);
98969             }
98970
98971             localizedInputs = selection.selectAll('.localized-multilingual').data([0]);
98972             localizedInputs = localizedInputs.enter().append('div').attr('class', 'localized-multilingual').merge(localizedInputs);
98973             localizedInputs.call(renderMultilingual);
98974             localizedInputs.selectAll('button, input').classed('disabled', !!isLocked).attr('readonly', isLocked || null);
98975             selection.selectAll('.combobox-caret').classed('nope', true);
98976
98977             function addNew(d3_event) {
98978               d3_event.preventDefault();
98979               if (field.locked()) return;
98980               var defaultLang = _mainLocalizer.languageCode().toLowerCase();
98981
98982               var langExists = _multilingual.find(function (datum) {
98983                 return datum.lang === defaultLang;
98984               });
98985
98986               var isLangEn = defaultLang.indexOf('en') > -1;
98987
98988               if (isLangEn || langExists) {
98989                 defaultLang = '';
98990                 langExists = _multilingual.find(function (datum) {
98991                   return datum.lang === defaultLang;
98992                 });
98993               }
98994
98995               if (!langExists) {
98996                 // prepend the value so it appears at the top
98997                 _multilingual.unshift({
98998                   lang: defaultLang,
98999                   value: ''
99000                 });
99001
99002                 localizedInputs.call(renderMultilingual);
99003               }
99004             }
99005
99006             function change(onInput) {
99007               return function (d3_event) {
99008                 if (field.locked()) {
99009                   d3_event.preventDefault();
99010                   return;
99011                 }
99012
99013                 var val = utilGetSetValue(select(this));
99014                 if (!onInput) val = context.cleanTagValue(val); // don't override multiple values with blank string
99015
99016                 if (!val && Array.isArray(_tags[field.key])) return;
99017                 var t = {};
99018                 t[field.key] = val || undefined;
99019                 dispatch.call('change', this, t, onInput);
99020               };
99021             }
99022           }
99023
99024           function key(lang) {
99025             return field.key + ':' + lang;
99026           }
99027
99028           function changeLang(d3_event, d) {
99029             var tags = {}; // make sure unrecognized suffixes are lowercase - #7156
99030
99031             var lang = utilGetSetValue(select(this)).toLowerCase();
99032
99033             var language = _languagesArray.find(function (d) {
99034               return d.label.toLowerCase() === lang || d.localName && d.localName.toLowerCase() === lang || d.nativeName && d.nativeName.toLowerCase() === lang;
99035             });
99036
99037             if (language) lang = language.code;
99038
99039             if (d.lang && d.lang !== lang) {
99040               tags[key(d.lang)] = undefined;
99041             }
99042
99043             var newKey = lang && context.cleanTagKey(key(lang));
99044             var value = utilGetSetValue(select(this.parentNode).selectAll('.localized-value'));
99045
99046             if (newKey && value) {
99047               tags[newKey] = value;
99048             } else if (newKey && _wikiTitles && _wikiTitles[d.lang]) {
99049               tags[newKey] = _wikiTitles[d.lang];
99050             }
99051
99052             d.lang = lang;
99053             dispatch.call('change', this, tags);
99054           }
99055
99056           function changeValue(d3_event, d) {
99057             if (!d.lang) return;
99058             var value = context.cleanTagValue(utilGetSetValue(select(this))) || undefined; // don't override multiple values with blank string
99059
99060             if (!value && Array.isArray(d.value)) return;
99061             var t = {};
99062             t[key(d.lang)] = value;
99063             d.value = value;
99064             dispatch.call('change', this, t);
99065           }
99066
99067           function fetchLanguages(value, cb) {
99068             var v = value.toLowerCase(); // show the user's language first
99069
99070             var langCodes = [_mainLocalizer.localeCode(), _mainLocalizer.languageCode()];
99071
99072             if (_countryCode && _territoryLanguages[_countryCode]) {
99073               langCodes = langCodes.concat(_territoryLanguages[_countryCode]);
99074             }
99075
99076             var langItems = [];
99077             langCodes.forEach(function (code) {
99078               var langItem = _languagesArray.find(function (item) {
99079                 return item.code === code;
99080               });
99081
99082               if (langItem) langItems.push(langItem);
99083             });
99084             langItems = utilArrayUniq(langItems.concat(_languagesArray));
99085             cb(langItems.filter(function (d) {
99086               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;
99087             }).map(function (d) {
99088               return {
99089                 value: d.label
99090               };
99091             }));
99092           }
99093
99094           function renderMultilingual(selection) {
99095             var entries = selection.selectAll('div.entry').data(_multilingual, function (d) {
99096               return d.lang;
99097             });
99098             entries.exit().style('top', '0').style('max-height', '240px').transition().duration(200).style('opacity', '0').style('max-height', '0px').remove();
99099             var entriesEnter = entries.enter().append('div').attr('class', 'entry').each(function (_, index) {
99100               var wrap = select(this);
99101               var domId = utilUniqueDomId(index);
99102               var label = wrap.append('label').attr('class', 'field-label').attr('for', domId);
99103               var text = label.append('span').attr('class', 'label-text');
99104               text.append('span').attr('class', 'label-textvalue').call(_t.append('translate.localized_translation_label'));
99105               text.append('span').attr('class', 'label-textannotation');
99106               label.append('button').attr('class', 'remove-icon-multilingual').attr('title', _t('icons.remove')).on('click', function (d3_event, d) {
99107                 if (field.locked()) return;
99108                 d3_event.preventDefault(); // remove the UI item manually
99109
99110                 _multilingual.splice(_multilingual.indexOf(d), 1);
99111
99112                 var langKey = d.lang && key(d.lang);
99113
99114                 if (langKey && langKey in _tags) {
99115                   delete _tags[langKey]; // remove from entity tags
99116
99117                   var t = {};
99118                   t[langKey] = undefined;
99119                   dispatch.call('change', this, t);
99120                   return;
99121                 }
99122
99123                 renderMultilingual(selection);
99124               }).call(svgIcon('#iD-operation-delete'));
99125               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);
99126               wrap.append('input').attr('type', 'text').attr('class', 'localized-value').on('blur', changeValue).on('change', changeValue);
99127             });
99128             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 () {
99129               select(this).style('max-height', '').style('overflow', 'visible');
99130             });
99131             entries = entries.merge(entriesEnter);
99132             entries.order(); // allow removing the entry UIs even if there isn't a tag to remove
99133
99134             entries.classed('present', true);
99135             utilGetSetValue(entries.select('.localized-lang'), function (d) {
99136               var langItem = _languagesArray.find(function (item) {
99137                 return item.code === d.lang;
99138               });
99139
99140               if (langItem) return langItem.label;
99141               return d.lang;
99142             });
99143             utilGetSetValue(entries.select('.localized-value'), function (d) {
99144               return typeof d.value === 'string' ? d.value : '';
99145             }).attr('title', function (d) {
99146               return Array.isArray(d.value) ? d.value.filter(Boolean).join('\n') : null;
99147             }).attr('placeholder', function (d) {
99148               return Array.isArray(d.value) ? _t('inspector.multiple_values') : _t('translate.localized_translation_name');
99149             }).classed('mixed', function (d) {
99150               return Array.isArray(d.value);
99151             });
99152           }
99153
99154           localized.tags = function (tags) {
99155             _tags = tags; // Fetch translations from wikipedia
99156
99157             if (typeof tags.wikipedia === 'string' && !_wikiTitles) {
99158               _wikiTitles = {};
99159               var wm = tags.wikipedia.match(/([^:]+):(.+)/);
99160
99161               if (wm && wm[0] && wm[1]) {
99162                 wikipedia.translations(wm[1], wm[2], function (err, d) {
99163                   if (err || !d) return;
99164                   _wikiTitles = d;
99165                 });
99166               }
99167             }
99168
99169             var isMixed = Array.isArray(tags[field.key]);
99170             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);
99171             calcMultilingual(tags);
99172
99173             _selection.call(localized);
99174           };
99175
99176           localized.focus = function () {
99177             input.node().focus();
99178           };
99179
99180           localized.entityIDs = function (val) {
99181             if (!arguments.length) return _entityIDs;
99182             _entityIDs = val;
99183             _multilingual = [];
99184             loadCountryCode();
99185             return localized;
99186           };
99187
99188           function loadCountryCode() {
99189             var extent = combinedEntityExtent();
99190             var countryCode = extent && iso1A2Code(extent.center());
99191             _countryCode = countryCode && countryCode.toLowerCase();
99192           }
99193
99194           function combinedEntityExtent() {
99195             return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
99196           }
99197
99198           return utilRebind(localized, dispatch, 'on');
99199         }
99200
99201         function uiFieldRoadheight(field, context) {
99202           var dispatch = dispatch$8('change');
99203           var primaryUnitInput = select(null);
99204           var primaryInput = select(null);
99205           var secondaryInput = select(null);
99206           var secondaryUnitInput = select(null);
99207           var _entityIDs = [];
99208
99209           var _tags;
99210
99211           var _isImperial;
99212
99213           var primaryUnits = [{
99214             value: 'm',
99215             title: _t('inspector.roadheight.meter')
99216           }, {
99217             value: 'ft',
99218             title: _t('inspector.roadheight.foot')
99219           }];
99220           var unitCombo = uiCombobox(context, 'roadheight-unit').data(primaryUnits);
99221
99222           function roadheight(selection) {
99223             var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
99224             wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
99225             primaryInput = wrap.selectAll('input.roadheight-number').data([0]);
99226             primaryInput = primaryInput.enter().append('input').attr('type', 'text').attr('class', 'roadheight-number').attr('id', field.domId).call(utilNoAuto).merge(primaryInput);
99227             primaryInput.on('change', change).on('blur', change);
99228             var loc = combinedEntityExtent().center();
99229             _isImperial = roadHeightUnit(loc) === 'ft';
99230             primaryUnitInput = wrap.selectAll('input.roadheight-unit').data([0]);
99231             primaryUnitInput = primaryUnitInput.enter().append('input').attr('type', 'text').attr('class', 'roadheight-unit').call(unitCombo).merge(primaryUnitInput);
99232             primaryUnitInput.on('blur', changeUnits).on('change', changeUnits);
99233             secondaryInput = wrap.selectAll('input.roadheight-secondary-number').data([0]);
99234             secondaryInput = secondaryInput.enter().append('input').attr('type', 'text').attr('class', 'roadheight-secondary-number').call(utilNoAuto).merge(secondaryInput);
99235             secondaryInput.on('change', change).on('blur', change);
99236             secondaryUnitInput = wrap.selectAll('input.roadheight-secondary-unit').data([0]);
99237             secondaryUnitInput = secondaryUnitInput.enter().append('input').attr('type', 'text').call(utilNoAuto).classed('disabled', true).classed('roadheight-secondary-unit', true).attr('readonly', 'readonly').merge(secondaryUnitInput);
99238
99239             function changeUnits() {
99240               _isImperial = utilGetSetValue(primaryUnitInput) === 'ft';
99241               utilGetSetValue(primaryUnitInput, _isImperial ? 'ft' : 'm');
99242               setUnitSuggestions();
99243               change();
99244             }
99245           }
99246
99247           function setUnitSuggestions() {
99248             utilGetSetValue(primaryUnitInput, _isImperial ? 'ft' : 'm');
99249           }
99250
99251           function change() {
99252             var tag = {};
99253             var primaryValue = utilGetSetValue(primaryInput).trim();
99254             var secondaryValue = utilGetSetValue(secondaryInput).trim(); // don't override multiple values with blank string
99255
99256             if (!primaryValue && !secondaryValue && Array.isArray(_tags[field.key])) return;
99257
99258             if (!primaryValue && !secondaryValue) {
99259               tag[field.key] = undefined;
99260             } else if (isNaN(primaryValue) || isNaN(secondaryValue) || !_isImperial) {
99261               tag[field.key] = context.cleanTagValue(primaryValue);
99262             } else {
99263               if (primaryValue !== '') {
99264                 primaryValue = context.cleanTagValue(primaryValue + '\'');
99265               }
99266
99267               if (secondaryValue !== '') {
99268                 secondaryValue = context.cleanTagValue(secondaryValue + '"');
99269               }
99270
99271               tag[field.key] = primaryValue + secondaryValue;
99272             }
99273
99274             dispatch.call('change', this, tag);
99275           }
99276
99277           roadheight.tags = function (tags) {
99278             _tags = tags;
99279             var primaryValue = tags[field.key];
99280             var secondaryValue;
99281             var isMixed = Array.isArray(primaryValue);
99282
99283             if (!isMixed) {
99284               if (primaryValue && (primaryValue.indexOf('\'') >= 0 || primaryValue.indexOf('"') >= 0)) {
99285                 secondaryValue = primaryValue.match(/(-?[\d.]+)"/);
99286
99287                 if (secondaryValue !== null) {
99288                   secondaryValue = secondaryValue[1];
99289                 }
99290
99291                 primaryValue = primaryValue.match(/(-?[\d.]+)'/);
99292
99293                 if (primaryValue !== null) {
99294                   primaryValue = primaryValue[1];
99295                 }
99296
99297                 _isImperial = true;
99298               } else if (primaryValue) {
99299                 _isImperial = false;
99300               }
99301             }
99302
99303             setUnitSuggestions();
99304             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);
99305             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');
99306             secondaryUnitInput.attr('value', _isImperial ? _t('inspector.roadheight.inch') : null);
99307           };
99308
99309           roadheight.focus = function () {
99310             primaryInput.node().focus();
99311           };
99312
99313           roadheight.entityIDs = function (val) {
99314             _entityIDs = val;
99315           };
99316
99317           function combinedEntityExtent() {
99318             return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
99319           }
99320
99321           return utilRebind(roadheight, dispatch, 'on');
99322         }
99323
99324         function uiFieldRoadspeed(field, context) {
99325           var dispatch = dispatch$8('change');
99326           var unitInput = select(null);
99327           var input = select(null);
99328           var _entityIDs = [];
99329
99330           var _tags;
99331
99332           var _isImperial;
99333
99334           var speedCombo = uiCombobox(context, 'roadspeed');
99335           var unitCombo = uiCombobox(context, 'roadspeed-unit').data(['km/h', 'mph'].map(comboValues));
99336           var metricValues = [20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120];
99337           var imperialValues = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80];
99338
99339           function roadspeed(selection) {
99340             var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
99341             wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
99342             input = wrap.selectAll('input.roadspeed-number').data([0]);
99343             input = input.enter().append('input').attr('type', 'text').attr('class', 'roadspeed-number').attr('id', field.domId).call(utilNoAuto).call(speedCombo).merge(input);
99344             input.on('change', change).on('blur', change);
99345             var loc = combinedEntityExtent().center();
99346             _isImperial = roadSpeedUnit(loc) === 'mph';
99347             unitInput = wrap.selectAll('input.roadspeed-unit').data([0]);
99348             unitInput = unitInput.enter().append('input').attr('type', 'text').attr('class', 'roadspeed-unit').attr('aria-label', _t('inspector.speed_unit')).call(unitCombo).merge(unitInput);
99349             unitInput.on('blur', changeUnits).on('change', changeUnits);
99350
99351             function changeUnits() {
99352               _isImperial = utilGetSetValue(unitInput) === 'mph';
99353               utilGetSetValue(unitInput, _isImperial ? 'mph' : 'km/h');
99354               setUnitSuggestions();
99355               change();
99356             }
99357           }
99358
99359           function setUnitSuggestions() {
99360             speedCombo.data((_isImperial ? imperialValues : metricValues).map(comboValues));
99361             utilGetSetValue(unitInput, _isImperial ? 'mph' : 'km/h');
99362           }
99363
99364           function comboValues(d) {
99365             return {
99366               value: d.toString(),
99367               title: d.toString()
99368             };
99369           }
99370
99371           function change() {
99372             var tag = {};
99373             var value = utilGetSetValue(input).trim(); // don't override multiple values with blank string
99374
99375             if (!value && Array.isArray(_tags[field.key])) return;
99376
99377             if (!value) {
99378               tag[field.key] = undefined;
99379             } else if (isNaN(value) || !_isImperial) {
99380               tag[field.key] = context.cleanTagValue(value);
99381             } else {
99382               tag[field.key] = context.cleanTagValue(value + ' mph');
99383             }
99384
99385             dispatch.call('change', this, tag);
99386           }
99387
99388           roadspeed.tags = function (tags) {
99389             _tags = tags;
99390             var value = tags[field.key];
99391             var isMixed = Array.isArray(value);
99392
99393             if (!isMixed) {
99394               if (value && value.indexOf('mph') >= 0) {
99395                 value = parseInt(value, 10).toString();
99396                 _isImperial = true;
99397               } else if (value) {
99398                 _isImperial = false;
99399               }
99400             }
99401
99402             setUnitSuggestions();
99403             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);
99404           };
99405
99406           roadspeed.focus = function () {
99407             input.node().focus();
99408           };
99409
99410           roadspeed.entityIDs = function (val) {
99411             _entityIDs = val;
99412           };
99413
99414           function combinedEntityExtent() {
99415             return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
99416           }
99417
99418           return utilRebind(roadspeed, dispatch, 'on');
99419         }
99420
99421         function uiFieldRadio(field, context) {
99422           var dispatch = dispatch$8('change');
99423           var placeholder = select(null);
99424           var wrap = select(null);
99425           var labels = select(null);
99426           var radios = select(null);
99427           var radioData = (field.options || field.keys).slice(); // shallow copy
99428
99429           var typeField;
99430           var layerField;
99431           var _oldType = {};
99432           var _entityIDs = [];
99433
99434           function selectedKey() {
99435             var node = wrap.selectAll('.form-field-input-radio label.active input');
99436             return !node.empty() && node.datum();
99437           }
99438
99439           function radio(selection) {
99440             selection.classed('preset-radio', true);
99441             wrap = selection.selectAll('.form-field-input-wrap').data([0]);
99442             var enter = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-radio');
99443             enter.append('span').attr('class', 'placeholder');
99444             wrap = wrap.merge(enter);
99445             placeholder = wrap.selectAll('.placeholder');
99446             labels = wrap.selectAll('label').data(radioData);
99447             enter = labels.enter().append('label');
99448             enter.append('input').attr('type', 'radio').attr('name', field.id).attr('value', function (d) {
99449               return field.t('options.' + d, {
99450                 'default': d
99451               });
99452             }).attr('checked', false);
99453             enter.append('span').html(function (d) {
99454               return field.t.html('options.' + d, {
99455                 'default': d
99456               });
99457             });
99458             labels = labels.merge(enter);
99459             radios = labels.selectAll('input').on('change', changeRadio);
99460           }
99461
99462           function structureExtras(selection, tags) {
99463             var selected = selectedKey() || tags.layer !== undefined;
99464             var type = _mainPresetIndex.field(selected);
99465             var layer = _mainPresetIndex.field('layer');
99466             var showLayer = selected === 'bridge' || selected === 'tunnel' || tags.layer !== undefined;
99467             var extrasWrap = selection.selectAll('.structure-extras-wrap').data(selected ? [0] : []);
99468             extrasWrap.exit().remove();
99469             extrasWrap = extrasWrap.enter().append('div').attr('class', 'structure-extras-wrap').merge(extrasWrap);
99470             var list = extrasWrap.selectAll('ul').data([0]);
99471             list = list.enter().append('ul').attr('class', 'rows').merge(list); // Type
99472
99473             if (type) {
99474               if (!typeField || typeField.id !== selected) {
99475                 typeField = uiField(context, type, _entityIDs, {
99476                   wrap: false
99477                 }).on('change', changeType);
99478               }
99479
99480               typeField.tags(tags);
99481             } else {
99482               typeField = null;
99483             }
99484
99485             var typeItem = list.selectAll('.structure-type-item').data(typeField ? [typeField] : [], function (d) {
99486               return d.id;
99487             }); // Exit
99488
99489             typeItem.exit().remove(); // Enter
99490
99491             var typeEnter = typeItem.enter().insert('li', ':first-child').attr('class', 'labeled-input structure-type-item');
99492             typeEnter.append('span').attr('class', 'label structure-label-type').attr('for', 'preset-input-' + selected).call(_t.append('inspector.radio.structure.type'));
99493             typeEnter.append('div').attr('class', 'structure-input-type-wrap'); // Update
99494
99495             typeItem = typeItem.merge(typeEnter);
99496
99497             if (typeField) {
99498               typeItem.selectAll('.structure-input-type-wrap').call(typeField.render);
99499             } // Layer
99500
99501
99502             if (layer && showLayer) {
99503               if (!layerField) {
99504                 layerField = uiField(context, layer, _entityIDs, {
99505                   wrap: false
99506                 }).on('change', changeLayer);
99507               }
99508
99509               layerField.tags(tags);
99510               field.keys = utilArrayUnion(field.keys, ['layer']);
99511             } else {
99512               layerField = null;
99513               field.keys = field.keys.filter(function (k) {
99514                 return k !== 'layer';
99515               });
99516             }
99517
99518             var layerItem = list.selectAll('.structure-layer-item').data(layerField ? [layerField] : []); // Exit
99519
99520             layerItem.exit().remove(); // Enter
99521
99522             var layerEnter = layerItem.enter().append('li').attr('class', 'labeled-input structure-layer-item');
99523             layerEnter.append('span').attr('class', 'label structure-label-layer').attr('for', 'preset-input-layer').call(_t.append('inspector.radio.structure.layer'));
99524             layerEnter.append('div').attr('class', 'structure-input-layer-wrap'); // Update
99525
99526             layerItem = layerItem.merge(layerEnter);
99527
99528             if (layerField) {
99529               layerItem.selectAll('.structure-input-layer-wrap').call(layerField.render);
99530             }
99531           }
99532
99533           function changeType(t, onInput) {
99534             var key = selectedKey();
99535             if (!key) return;
99536             var val = t[key];
99537
99538             if (val !== 'no') {
99539               _oldType[key] = val;
99540             }
99541
99542             if (field.type === 'structureRadio') {
99543               // remove layer if it should not be set
99544               if (val === 'no' || key !== 'bridge' && key !== 'tunnel' || key === 'tunnel' && val === 'building_passage') {
99545                 t.layer = undefined;
99546               } // add layer if it should be set
99547
99548
99549               if (t.layer === undefined) {
99550                 if (key === 'bridge' && val !== 'no') {
99551                   t.layer = '1';
99552                 }
99553
99554                 if (key === 'tunnel' && val !== 'no' && val !== 'building_passage') {
99555                   t.layer = '-1';
99556                 }
99557               }
99558             }
99559
99560             dispatch.call('change', this, t, onInput);
99561           }
99562
99563           function changeLayer(t, onInput) {
99564             if (t.layer === '0') {
99565               t.layer = undefined;
99566             }
99567
99568             dispatch.call('change', this, t, onInput);
99569           }
99570
99571           function changeRadio() {
99572             var t = {};
99573             var activeKey;
99574
99575             if (field.key) {
99576               t[field.key] = undefined;
99577             }
99578
99579             radios.each(function (d) {
99580               var active = select(this).property('checked');
99581               if (active) activeKey = d;
99582
99583               if (field.key) {
99584                 if (active) t[field.key] = d;
99585               } else {
99586                 var val = _oldType[activeKey] || 'yes';
99587                 t[d] = active ? val : undefined;
99588               }
99589             });
99590
99591             if (field.type === 'structureRadio') {
99592               if (activeKey === 'bridge') {
99593                 t.layer = '1';
99594               } else if (activeKey === 'tunnel' && t.tunnel !== 'building_passage') {
99595                 t.layer = '-1';
99596               } else {
99597                 t.layer = undefined;
99598               }
99599             }
99600
99601             dispatch.call('change', this, t);
99602           }
99603
99604           radio.tags = function (tags) {
99605             function isOptionChecked(d) {
99606               if (field.key) {
99607                 return tags[field.key] === d;
99608               }
99609
99610               return !!(typeof tags[d] === 'string' && tags[d].toLowerCase() !== 'no');
99611             }
99612
99613             function isMixed(d) {
99614               if (field.key) {
99615                 return Array.isArray(tags[field.key]) && tags[field.key].includes(d);
99616               }
99617
99618               return Array.isArray(tags[d]);
99619             }
99620
99621             radios.property('checked', function (d) {
99622               return isOptionChecked(d) && (field.key || field.options.filter(isOptionChecked).length === 1);
99623             });
99624             labels.classed('active', function (d) {
99625               if (field.key) {
99626                 return Array.isArray(tags[field.key]) && tags[field.key].includes(d) || tags[field.key] === d;
99627               }
99628
99629               return Array.isArray(tags[d]) && tags[d].some(function (v) {
99630                 return typeof v === 'string' && v.toLowerCase() !== 'no';
99631               }) || !!(typeof tags[d] === 'string' && tags[d].toLowerCase() !== 'no');
99632             }).classed('mixed', isMixed).attr('title', function (d) {
99633               return isMixed(d) ? _t('inspector.unshared_value_tooltip') : null;
99634             });
99635             var selection = radios.filter(function () {
99636               return this.checked;
99637             });
99638
99639             if (selection.empty()) {
99640               placeholder.call(_t.append('inspector.none'));
99641             } else {
99642               placeholder.text(selection.attr('value'));
99643               _oldType[selection.datum()] = tags[selection.datum()];
99644             }
99645
99646             if (field.type === 'structureRadio') {
99647               // For waterways without a tunnel tag, set 'culvert' as
99648               // the _oldType to default to if the user picks 'tunnel'
99649               if (!!tags.waterway && !_oldType.tunnel) {
99650                 _oldType.tunnel = 'culvert';
99651               }
99652
99653               wrap.call(structureExtras, tags);
99654             }
99655           };
99656
99657           radio.focus = function () {
99658             radios.node().focus();
99659           };
99660
99661           radio.entityIDs = function (val) {
99662             if (!arguments.length) return _entityIDs;
99663             _entityIDs = val;
99664             _oldType = {};
99665             return radio;
99666           };
99667
99668           radio.isAllowed = function () {
99669             return _entityIDs.length === 1;
99670           };
99671
99672           return utilRebind(radio, dispatch, 'on');
99673         }
99674
99675         function uiFieldRestrictions(field, context) {
99676           var dispatch = dispatch$8('change');
99677           var breathe = behaviorBreathe();
99678           corePreferences('turn-restriction-via-way', null); // remove old key
99679
99680           var storedViaWay = corePreferences('turn-restriction-via-way0'); // use new key #6922
99681
99682           var storedDistance = corePreferences('turn-restriction-distance');
99683
99684           var _maxViaWay = storedViaWay !== null ? +storedViaWay : 0;
99685
99686           var _maxDistance = storedDistance ? +storedDistance : 30;
99687
99688           var _initialized = false;
99689
99690           var _parent = select(null); // the entire field
99691
99692
99693           var _container = select(null); // just the map
99694
99695
99696           var _oldTurns;
99697
99698           var _graph;
99699
99700           var _vertexID;
99701
99702           var _intersection;
99703
99704           var _fromWayID;
99705
99706           var _lastXPos;
99707
99708           function restrictions(selection) {
99709             _parent = selection; // try to reuse the intersection, but always rebuild it if the graph has changed
99710
99711             if (_vertexID && (context.graph() !== _graph || !_intersection)) {
99712               _graph = context.graph();
99713               _intersection = osmIntersection(_graph, _vertexID, _maxDistance);
99714             } // It's possible for there to be no actual intersection here.
99715             // for example, a vertex of two `highway=path`
99716             // In this case, hide the field.
99717
99718
99719             var isOK = _intersection && _intersection.vertices.length && // has vertices
99720             _intersection.vertices // has the vertex that the user selected
99721             .filter(function (vertex) {
99722               return vertex.id === _vertexID;
99723             }).length && _intersection.ways.length > 2 && // has more than 2 ways
99724             _intersection.ways // has more than 1 TO way
99725             .filter(function (way) {
99726               return way.__to;
99727             }).length > 1; // Also hide in the case where
99728
99729             select(selection.node().parentNode).classed('hide', !isOK); // if form field is hidden or has detached from dom, clean up.
99730
99731             if (!isOK || !context.container().select('.inspector-wrap.inspector-hidden').empty() || !selection.node().parentNode || !selection.node().parentNode.parentNode) {
99732               selection.call(restrictions.off);
99733               return;
99734             }
99735
99736             var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
99737             wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
99738             var container = wrap.selectAll('.restriction-container').data([0]); // enter
99739
99740             var containerEnter = container.enter().append('div').attr('class', 'restriction-container');
99741             containerEnter.append('div').attr('class', 'restriction-help'); // update
99742
99743             _container = containerEnter.merge(container).call(renderViewer);
99744             var controls = wrap.selectAll('.restriction-controls').data([0]); // enter/update
99745
99746             controls.enter().append('div').attr('class', 'restriction-controls-container').append('div').attr('class', 'restriction-controls').merge(controls).call(renderControls);
99747           }
99748
99749           function renderControls(selection) {
99750             var distControl = selection.selectAll('.restriction-distance').data([0]);
99751             distControl.exit().remove();
99752             var distControlEnter = distControl.enter().append('div').attr('class', 'restriction-control restriction-distance');
99753             distControlEnter.append('span').attr('class', 'restriction-control-label restriction-distance-label').call(_t.append('restriction.controls.distance', {
99754               suffix: ':'
99755             }));
99756             distControlEnter.append('input').attr('class', 'restriction-distance-input').attr('type', 'range').attr('min', '20').attr('max', '50').attr('step', '5');
99757             distControlEnter.append('span').attr('class', 'restriction-distance-text'); // update
99758
99759             selection.selectAll('.restriction-distance-input').property('value', _maxDistance).on('input', function () {
99760               var val = select(this).property('value');
99761               _maxDistance = +val;
99762               _intersection = null;
99763
99764               _container.selectAll('.layer-osm .layer-turns *').remove();
99765
99766               corePreferences('turn-restriction-distance', _maxDistance);
99767
99768               _parent.call(restrictions);
99769             });
99770             selection.selectAll('.restriction-distance-text').call(displayMaxDistance(_maxDistance));
99771             var viaControl = selection.selectAll('.restriction-via-way').data([0]);
99772             viaControl.exit().remove();
99773             var viaControlEnter = viaControl.enter().append('div').attr('class', 'restriction-control restriction-via-way');
99774             viaControlEnter.append('span').attr('class', 'restriction-control-label restriction-via-way-label').call(_t.append('restriction.controls.via', {
99775               suffix: ':'
99776             }));
99777             viaControlEnter.append('input').attr('class', 'restriction-via-way-input').attr('type', 'range').attr('min', '0').attr('max', '2').attr('step', '1');
99778             viaControlEnter.append('span').attr('class', 'restriction-via-way-text'); // update
99779
99780             selection.selectAll('.restriction-via-way-input').property('value', _maxViaWay).on('input', function () {
99781               var val = select(this).property('value');
99782               _maxViaWay = +val;
99783
99784               _container.selectAll('.layer-osm .layer-turns *').remove();
99785
99786               corePreferences('turn-restriction-via-way0', _maxViaWay);
99787
99788               _parent.call(restrictions);
99789             });
99790             selection.selectAll('.restriction-via-way-text').call(displayMaxVia(_maxViaWay));
99791           }
99792
99793           function renderViewer(selection) {
99794             if (!_intersection) return;
99795             var vgraph = _intersection.graph;
99796             var filter = utilFunctor(true);
99797             var projection = geoRawMercator(); // Reflow warning: `utilGetDimensions` calls `getBoundingClientRect`
99798             // Instead of asking the restriction-container for its dimensions,
99799             //  we can ask the .sidebar, which can have its dimensions cached.
99800             // width: calc as sidebar - padding
99801             // height: hardcoded (from `80_app.css`)
99802             // var d = utilGetDimensions(selection);
99803
99804             var sdims = utilGetDimensions(context.container().select('.sidebar'));
99805             var d = [sdims[0] - 50, 370];
99806             var c = geoVecScale(d, 0.5);
99807             var z = 22;
99808             projection.scale(geoZoomToScale(z)); // Calculate extent of all key vertices
99809
99810             var extent = geoExtent();
99811
99812             for (var i = 0; i < _intersection.vertices.length; i++) {
99813               extent._extend(_intersection.vertices[i].extent());
99814             }
99815
99816             var padTop = 35; // reserve top space for hint text
99817             // If this is a large intersection, adjust zoom to fit extent
99818
99819             if (_intersection.vertices.length > 1) {
99820               var hPadding = Math.min(160, Math.max(110, d[0] * 0.4));
99821               var vPadding = 160;
99822               var tl = projection([extent[0][0], extent[1][1]]);
99823               var br = projection([extent[1][0], extent[0][1]]);
99824               var hFactor = (br[0] - tl[0]) / (d[0] - hPadding);
99825               var vFactor = (br[1] - tl[1]) / (d[1] - vPadding - padTop);
99826               var hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2;
99827               var vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2;
99828               z = z - Math.max(hZoomDiff, vZoomDiff);
99829               projection.scale(geoZoomToScale(z));
99830             }
99831
99832             var extentCenter = projection(extent.center());
99833             extentCenter[1] = extentCenter[1] - padTop / 2;
99834             projection.translate(geoVecSubtract(c, extentCenter)).clipExtent([[0, 0], d]);
99835             var drawLayers = svgLayers(projection, context).only(['osm', 'touch']).dimensions(d);
99836             var drawVertices = svgVertices(projection, context);
99837             var drawLines = svgLines(projection, context);
99838             var drawTurns = svgTurns(projection, context);
99839             var firstTime = selection.selectAll('.surface').empty();
99840             selection.call(drawLayers);
99841             var surface = selection.selectAll('.surface').classed('tr', true);
99842
99843             if (firstTime) {
99844               _initialized = true;
99845               surface.call(breathe);
99846             } // This can happen if we've lowered the detail while a FROM way
99847             // is selected, and that way is no longer part of the intersection.
99848
99849
99850             if (_fromWayID && !vgraph.hasEntity(_fromWayID)) {
99851               _fromWayID = null;
99852               _oldTurns = null;
99853             }
99854
99855             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));
99856             surface.on('click.restrictions', click).on('mouseover.restrictions', mouseover);
99857             surface.selectAll('.selected').classed('selected', false);
99858             surface.selectAll('.related').classed('related', false);
99859             var way;
99860
99861             if (_fromWayID) {
99862               way = vgraph.entity(_fromWayID);
99863               surface.selectAll('.' + _fromWayID).classed('selected', true).classed('related', true);
99864             }
99865
99866             document.addEventListener('resizeWindow', function () {
99867               utilSetDimensions(_container, null);
99868               redraw(1);
99869             }, false);
99870             updateHints(null);
99871
99872             function click(d3_event) {
99873               surface.call(breathe.off).call(breathe);
99874               var datum = d3_event.target.__data__;
99875               var entity = datum && datum.properties && datum.properties.entity;
99876
99877               if (entity) {
99878                 datum = entity;
99879               }
99880
99881               if (datum instanceof osmWay && (datum.__from || datum.__via)) {
99882                 _fromWayID = datum.id;
99883                 _oldTurns = null;
99884                 redraw();
99885               } else if (datum instanceof osmTurn) {
99886                 var actions, extraActions, turns, i;
99887                 var restrictionType = osmInferRestriction(vgraph, datum, projection);
99888
99889                 if (datum.restrictionID && !datum.direct) {
99890                   return;
99891                 } else if (datum.restrictionID && !datum.only) {
99892                   // NO -> ONLY
99893                   var seen = {};
99894                   var datumOnly = JSON.parse(JSON.stringify(datum)); // deep clone the datum
99895
99896                   datumOnly.only = true; // but change this property
99897
99898                   restrictionType = restrictionType.replace(/^no/, 'only'); // Adding an ONLY restriction should destroy all other direct restrictions from the FROM towards the VIA.
99899                   // We will remember them in _oldTurns, and restore them if the user clicks again.
99900
99901                   turns = _intersection.turns(_fromWayID, 2);
99902                   extraActions = [];
99903                   _oldTurns = [];
99904
99905                   for (i = 0; i < turns.length; i++) {
99906                     var turn = turns[i];
99907                     if (seen[turn.restrictionID]) continue; // avoid deleting the turn twice (#4968, #4928)
99908
99909                     if (turn.direct && turn.path[1] === datum.path[1]) {
99910                       seen[turns[i].restrictionID] = true;
99911                       turn.restrictionType = osmInferRestriction(vgraph, turn, projection);
99912
99913                       _oldTurns.push(turn);
99914
99915                       extraActions.push(actionUnrestrictTurn(turn));
99916                     }
99917                   }
99918
99919                   actions = _intersection.actions.concat(extraActions, [actionRestrictTurn(datumOnly, restrictionType), _t('operations.restriction.annotation.create')]);
99920                 } else if (datum.restrictionID) {
99921                   // ONLY -> Allowed
99922                   // Restore whatever restrictions we might have destroyed by cycling thru the ONLY state.
99923                   // This relies on the assumption that the intersection was already split up when we
99924                   // performed the previous action (NO -> ONLY), so the IDs in _oldTurns shouldn't have changed.
99925                   turns = _oldTurns || [];
99926                   extraActions = [];
99927
99928                   for (i = 0; i < turns.length; i++) {
99929                     if (turns[i].key !== datum.key) {
99930                       extraActions.push(actionRestrictTurn(turns[i], turns[i].restrictionType));
99931                     }
99932                   }
99933
99934                   _oldTurns = null;
99935                   actions = _intersection.actions.concat(extraActions, [actionUnrestrictTurn(datum), _t('operations.restriction.annotation.delete')]);
99936                 } else {
99937                   // Allowed -> NO
99938                   actions = _intersection.actions.concat([actionRestrictTurn(datum, restrictionType), _t('operations.restriction.annotation.create')]);
99939                 }
99940
99941                 context.perform.apply(context, actions); // At this point the datum will be changed, but will have same key..
99942                 // Refresh it and update the help..
99943
99944                 var s = surface.selectAll('.' + datum.key);
99945                 datum = s.empty() ? null : s.datum();
99946                 updateHints(datum);
99947               } else {
99948                 _fromWayID = null;
99949                 _oldTurns = null;
99950                 redraw();
99951               }
99952             }
99953
99954             function mouseover(d3_event) {
99955               var datum = d3_event.target.__data__;
99956               updateHints(datum);
99957             }
99958
99959             _lastXPos = _lastXPos || sdims[0];
99960
99961             function redraw(minChange) {
99962               var xPos = -1;
99963
99964               if (minChange) {
99965                 xPos = utilGetDimensions(context.container().select('.sidebar'))[0];
99966               }
99967
99968               if (!minChange || minChange && Math.abs(xPos - _lastXPos) >= minChange) {
99969                 if (context.hasEntity(_vertexID)) {
99970                   _lastXPos = xPos;
99971
99972                   _container.call(renderViewer);
99973                 }
99974               }
99975             }
99976
99977             function highlightPathsFrom(wayID) {
99978               surface.selectAll('.related').classed('related', false).classed('allow', false).classed('restrict', false).classed('only', false);
99979               surface.selectAll('.' + wayID).classed('related', true);
99980
99981               if (wayID) {
99982                 var turns = _intersection.turns(wayID, _maxViaWay);
99983
99984                 for (var i = 0; i < turns.length; i++) {
99985                   var turn = turns[i];
99986                   var ids = [turn.to.way];
99987                   var klass = turn.no ? 'restrict' : turn.only ? 'only' : 'allow';
99988
99989                   if (turn.only || turns.length === 1) {
99990                     if (turn.via.ways) {
99991                       ids = ids.concat(turn.via.ways);
99992                     }
99993                   } else if (turn.to.way === wayID) {
99994                     continue;
99995                   }
99996
99997                   surface.selectAll(utilEntitySelector(ids)).classed('related', true).classed('allow', klass === 'allow').classed('restrict', klass === 'restrict').classed('only', klass === 'only');
99998                 }
99999               }
100000             }
100001
100002             function updateHints(datum) {
100003               var help = _container.selectAll('.restriction-help').html('');
100004
100005               var placeholders = {};
100006               ['from', 'via', 'to'].forEach(function (k) {
100007                 placeholders[k] = {
100008                   html: '<span class="qualifier">' + _t('restriction.help.' + k) + '</span>'
100009                 };
100010               });
100011               var entity = datum && datum.properties && datum.properties.entity;
100012
100013               if (entity) {
100014                 datum = entity;
100015               }
100016
100017               if (_fromWayID) {
100018                 way = vgraph.entity(_fromWayID);
100019                 surface.selectAll('.' + _fromWayID).classed('selected', true).classed('related', true);
100020               } // Hovering a way
100021
100022
100023               if (datum instanceof osmWay && datum.__from) {
100024                 way = datum;
100025                 highlightPathsFrom(_fromWayID ? null : way.id);
100026                 surface.selectAll('.' + way.id).classed('related', true);
100027                 var clickSelect = !_fromWayID || _fromWayID !== way.id;
100028                 help.append('div') // "Click to select FROM {fromName}." / "FROM {fromName}"
100029                 .html(_t.html('restriction.help.' + (clickSelect ? 'select_from_name' : 'from_name'), {
100030                   from: placeholders.from,
100031                   fromName: displayName(way.id, vgraph)
100032                 })); // Hovering a turn arrow
100033               } else if (datum instanceof osmTurn) {
100034                 var restrictionType = osmInferRestriction(vgraph, datum, projection);
100035                 var turnType = restrictionType.replace(/^(only|no)\_/, '');
100036                 var indirect = datum.direct === false ? _t.html('restriction.help.indirect') : '';
100037                 var klass, turnText, nextText;
100038
100039                 if (datum.no) {
100040                   klass = 'restrict';
100041                   turnText = _t.html('restriction.help.turn.no_' + turnType, {
100042                     indirect: indirect
100043                   });
100044                   nextText = _t.html('restriction.help.turn.only_' + turnType, {
100045                     indirect: ''
100046                   });
100047                 } else if (datum.only) {
100048                   klass = 'only';
100049                   turnText = _t.html('restriction.help.turn.only_' + turnType, {
100050                     indirect: indirect
100051                   });
100052                   nextText = _t.html('restriction.help.turn.allowed_' + turnType, {
100053                     indirect: ''
100054                   });
100055                 } else {
100056                   klass = 'allow';
100057                   turnText = _t.html('restriction.help.turn.allowed_' + turnType, {
100058                     indirect: indirect
100059                   });
100060                   nextText = _t.html('restriction.help.turn.no_' + turnType, {
100061                     indirect: ''
100062                   });
100063                 }
100064
100065                 help.append('div') // "NO Right Turn (indirect)"
100066                 .attr('class', 'qualifier ' + klass).html(turnText);
100067                 help.append('div') // "FROM {fromName} TO {toName}"
100068                 .html(_t.html('restriction.help.from_name_to_name', {
100069                   from: placeholders.from,
100070                   fromName: displayName(datum.from.way, vgraph),
100071                   to: placeholders.to,
100072                   toName: displayName(datum.to.way, vgraph)
100073                 }));
100074
100075                 if (datum.via.ways && datum.via.ways.length) {
100076                   var names = [];
100077
100078                   for (var i = 0; i < datum.via.ways.length; i++) {
100079                     var prev = names[names.length - 1];
100080                     var curr = displayName(datum.via.ways[i], vgraph);
100081
100082                     if (!prev || curr !== prev) {
100083                       // collapse identical names
100084                       names.push(curr);
100085                     }
100086                   }
100087
100088                   help.append('div') // "VIA {viaNames}"
100089                   .html(_t.html('restriction.help.via_names', {
100090                     via: placeholders.via,
100091                     viaNames: names.join(', ')
100092                   }));
100093                 }
100094
100095                 if (!indirect) {
100096                   help.append('div') // Click for "No Right Turn"
100097                   .html(_t.html('restriction.help.toggle', {
100098                     turn: {
100099                       html: nextText.trim()
100100                     }
100101                   }));
100102                 }
100103
100104                 highlightPathsFrom(null);
100105                 var alongIDs = datum.path.slice();
100106                 surface.selectAll(utilEntitySelector(alongIDs)).classed('related', true).classed('allow', klass === 'allow').classed('restrict', klass === 'restrict').classed('only', klass === 'only'); // Hovering empty surface
100107               } else {
100108                 highlightPathsFrom(null);
100109
100110                 if (_fromWayID) {
100111                   help.append('div') // "FROM {fromName}"
100112                   .html(_t.html('restriction.help.from_name', {
100113                     from: placeholders.from,
100114                     fromName: displayName(_fromWayID, vgraph)
100115                   }));
100116                 } else {
100117                   help.append('div') // "Click to select a FROM segment."
100118                   .html(_t.html('restriction.help.select_from', {
100119                     from: placeholders.from
100120                   }));
100121                 }
100122               }
100123             }
100124           }
100125
100126           function displayMaxDistance(maxDist) {
100127             return function (selection) {
100128               var isImperial = !_mainLocalizer.usesMetric();
100129               var opts;
100130
100131               if (isImperial) {
100132                 var distToFeet = {
100133                   // imprecise conversion for prettier display
100134                   20: 70,
100135                   25: 85,
100136                   30: 100,
100137                   35: 115,
100138                   40: 130,
100139                   45: 145,
100140                   50: 160
100141                 }[maxDist];
100142                 opts = {
100143                   distance: _t('units.feet', {
100144                     quantity: distToFeet
100145                   })
100146                 };
100147               } else {
100148                 opts = {
100149                   distance: _t('units.meters', {
100150                     quantity: maxDist
100151                   })
100152                 };
100153               }
100154
100155               return selection.html('').call(_t.append('restriction.controls.distance_up_to', opts));
100156             };
100157           }
100158
100159           function displayMaxVia(maxVia) {
100160             return function (selection) {
100161               selection = selection.html('');
100162               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'));
100163             };
100164           }
100165
100166           function displayName(entityID, graph) {
100167             var entity = graph.entity(entityID);
100168             var name = utilDisplayName(entity) || '';
100169             var matched = _mainPresetIndex.match(entity, graph);
100170             var type = matched && matched.name() || utilDisplayType(entity.id);
100171             return name || type;
100172           }
100173
100174           restrictions.entityIDs = function (val) {
100175             _intersection = null;
100176             _fromWayID = null;
100177             _oldTurns = null;
100178             _vertexID = val[0];
100179           };
100180
100181           restrictions.tags = function () {};
100182
100183           restrictions.focus = function () {};
100184
100185           restrictions.off = function (selection) {
100186             if (!_initialized) return;
100187             selection.selectAll('.surface').call(breathe.off).on('click.restrictions', null).on('mouseover.restrictions', null);
100188             select(window).on('resize.restrictions', null);
100189           };
100190
100191           return utilRebind(restrictions, dispatch, 'on');
100192         }
100193         uiFieldRestrictions.supportsMultiselection = false;
100194
100195         function uiFieldTextarea(field, context) {
100196           var dispatch = dispatch$8('change');
100197           var input = select(null);
100198
100199           var _tags;
100200
100201           function textarea(selection) {
100202             var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
100203             wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
100204             input = wrap.selectAll('textarea').data([0]);
100205             input = input.enter().append('textarea').attr('id', field.domId).call(utilNoAuto).on('input', change(true)).on('blur', change()).on('change', change()).merge(input);
100206           }
100207
100208           function change(onInput) {
100209             return function () {
100210               var val = utilGetSetValue(input);
100211               if (!onInput) val = context.cleanTagValue(val); // don't override multiple values with blank string
100212
100213               if (!val && Array.isArray(_tags[field.key])) return;
100214               var t = {};
100215               t[field.key] = val || undefined;
100216               dispatch.call('change', this, t, onInput);
100217             };
100218           }
100219
100220           textarea.tags = function (tags) {
100221             _tags = tags;
100222             var isMixed = Array.isArray(tags[field.key]);
100223             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);
100224           };
100225
100226           textarea.focus = function () {
100227             input.node().focus();
100228           };
100229
100230           return utilRebind(textarea, dispatch, 'on');
100231         }
100232
100233         function uiFieldWikidata(field, context) {
100234           var wikidata = services.wikidata;
100235           var dispatch = dispatch$8('change');
100236
100237           var _selection = select(null);
100238
100239           var _searchInput = select(null);
100240
100241           var _qid = null;
100242           var _wikidataEntity = null;
100243           var _wikiURL = '';
100244           var _entityIDs = [];
100245
100246           var _wikipediaKey = field.keys && field.keys.find(function (key) {
100247             return key.includes('wikipedia');
100248           }),
100249               _hintKey = field.key === 'wikidata' ? 'name' : field.key.split(':')[0];
100250
100251           var combobox = uiCombobox(context, 'combo-' + field.safeid).caseSensitive(true).minItems(1);
100252
100253           function wiki(selection) {
100254             _selection = selection;
100255             var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
100256             wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
100257             var list = wrap.selectAll('ul').data([0]);
100258             list = list.enter().append('ul').attr('class', 'rows').merge(list);
100259             var searchRow = list.selectAll('li.wikidata-search').data([0]);
100260             var searchRowEnter = searchRow.enter().append('li').attr('class', 'wikidata-search');
100261             searchRowEnter.append('input').attr('type', 'text').attr('id', field.domId).style('flex', '1').call(utilNoAuto).on('focus', function () {
100262               var node = select(this).node();
100263               node.setSelectionRange(0, node.value.length);
100264             }).on('blur', function () {
100265               setLabelForEntity();
100266             }).call(combobox.fetcher(fetchWikidataItems));
100267             combobox.on('accept', function (d) {
100268               if (d) {
100269                 _qid = d.id;
100270                 change();
100271               }
100272             }).on('cancel', function () {
100273               setLabelForEntity();
100274             });
100275             searchRowEnter.append('button').attr('class', 'form-field-button wiki-link').attr('title', _t('icons.view_on', {
100276               domain: 'wikidata.org'
100277             })).call(svgIcon('#iD-icon-out-link')).on('click', function (d3_event) {
100278               d3_event.preventDefault();
100279               if (_wikiURL) window.open(_wikiURL, '_blank');
100280             });
100281             searchRow = searchRow.merge(searchRowEnter);
100282             _searchInput = searchRow.select('input');
100283             var wikidataProperties = ['description', 'identifier'];
100284             var items = list.selectAll('li.labeled-input').data(wikidataProperties); // Enter
100285
100286             var enter = items.enter().append('li').attr('class', function (d) {
100287               return 'labeled-input preset-wikidata-' + d;
100288             });
100289             enter.append('span').attr('class', 'label').html(function (d) {
100290               return _t.html('wikidata.' + d);
100291             });
100292             enter.append('input').attr('type', 'text').call(utilNoAuto).classed('disabled', 'true').attr('readonly', 'true');
100293             enter.append('button').attr('class', 'form-field-button').attr('title', _t('icons.copy')).call(svgIcon('#iD-operation-copy')).on('click', function (d3_event) {
100294               d3_event.preventDefault();
100295               select(this.parentNode).select('input').node().select();
100296               document.execCommand('copy');
100297             });
100298           }
100299
100300           function fetchWikidataItems(q, callback) {
100301             if (!q && _hintKey) {
100302               // other tags may be good search terms
100303               for (var i in _entityIDs) {
100304                 var entity = context.hasEntity(_entityIDs[i]);
100305
100306                 if (entity.tags[_hintKey]) {
100307                   q = entity.tags[_hintKey];
100308                   break;
100309                 }
100310               }
100311             }
100312
100313             wikidata.itemsForSearchQuery(q, function (err, data) {
100314               if (err) return;
100315
100316               for (var i in data) {
100317                 data[i].value = data[i].label + ' (' + data[i].id + ')';
100318                 data[i].title = data[i].description;
100319               }
100320
100321               if (callback) callback(data);
100322             });
100323           }
100324
100325           function change() {
100326             var syncTags = {};
100327             syncTags[field.key] = _qid;
100328             dispatch.call('change', this, syncTags); // attempt asynchronous update of wikidata tag..
100329
100330             var initGraph = context.graph();
100331             var initEntityIDs = _entityIDs;
100332             wikidata.entityByQID(_qid, function (err, entity) {
100333               if (err) return; // If graph has changed, we can't apply this update.
100334
100335               if (context.graph() !== initGraph) return;
100336               if (!entity.sitelinks) return;
100337               var langs = wikidata.languagesToQuery(); // use the label and description languages as fallbacks
100338
100339               ['labels', 'descriptions'].forEach(function (key) {
100340                 if (!entity[key]) return;
100341                 var valueLangs = Object.keys(entity[key]);
100342                 if (valueLangs.length === 0) return;
100343                 var valueLang = valueLangs[0];
100344
100345                 if (langs.indexOf(valueLang) === -1) {
100346                   langs.push(valueLang);
100347                 }
100348               });
100349               var newWikipediaValue;
100350
100351               if (_wikipediaKey) {
100352                 var foundPreferred;
100353
100354                 for (var i in langs) {
100355                   var lang = langs[i];
100356                   var siteID = lang.replace('-', '_') + 'wiki';
100357
100358                   if (entity.sitelinks[siteID]) {
100359                     foundPreferred = true;
100360                     newWikipediaValue = lang + ':' + entity.sitelinks[siteID].title; // use the first match
100361
100362                     break;
100363                   }
100364                 }
100365
100366                 if (!foundPreferred) {
100367                   // No wikipedia sites available in the user's language or the fallback languages,
100368                   // default to any wikipedia sitelink
100369                   var wikiSiteKeys = Object.keys(entity.sitelinks).filter(function (site) {
100370                     return site.endsWith('wiki');
100371                   });
100372
100373                   if (wikiSiteKeys.length === 0) {
100374                     // if no wikipedia pages are linked to this wikidata entity, delete that tag
100375                     newWikipediaValue = null;
100376                   } else {
100377                     var wikiLang = wikiSiteKeys[0].slice(0, -4).replace('_', '-');
100378                     var wikiTitle = entity.sitelinks[wikiSiteKeys[0]].title;
100379                     newWikipediaValue = wikiLang + ':' + wikiTitle;
100380                   }
100381                 }
100382               }
100383
100384               if (newWikipediaValue) {
100385                 newWikipediaValue = context.cleanTagValue(newWikipediaValue);
100386               }
100387
100388               if (typeof newWikipediaValue === 'undefined') return;
100389               var actions = initEntityIDs.map(function (entityID) {
100390                 var entity = context.hasEntity(entityID);
100391                 if (!entity) return null;
100392                 var currTags = Object.assign({}, entity.tags); // shallow copy
100393
100394                 if (newWikipediaValue === null) {
100395                   if (!currTags[_wikipediaKey]) return null;
100396                   delete currTags[_wikipediaKey];
100397                 } else {
100398                   currTags[_wikipediaKey] = newWikipediaValue;
100399                 }
100400
100401                 return actionChangeTags(entityID, currTags);
100402               }).filter(Boolean);
100403               if (!actions.length) return; // Coalesce the update of wikidata tag into the previous tag change
100404
100405               context.overwrite(function actionUpdateWikipediaTags(graph) {
100406                 actions.forEach(function (action) {
100407                   graph = action(graph);
100408                 });
100409                 return graph;
100410               }, context.history().undoAnnotation()); // do not dispatch.call('change') here, because entity_editor
100411               // changeTags() is not intended to be called asynchronously
100412             });
100413           }
100414
100415           function setLabelForEntity() {
100416             var label = '';
100417
100418             if (_wikidataEntity) {
100419               label = entityPropertyForDisplay(_wikidataEntity, 'labels');
100420
100421               if (label.length === 0) {
100422                 label = _wikidataEntity.id.toString();
100423               }
100424             }
100425
100426             utilGetSetValue(_searchInput, label);
100427           }
100428
100429           wiki.tags = function (tags) {
100430             var isMixed = Array.isArray(tags[field.key]);
100431
100432             _searchInput.attr('title', isMixed ? tags[field.key].filter(Boolean).join('\n') : null).attr('placeholder', isMixed ? _t('inspector.multiple_values') : '').classed('mixed', isMixed);
100433
100434             _qid = typeof tags[field.key] === 'string' && tags[field.key] || '';
100435
100436             if (!/^Q[0-9]*$/.test(_qid)) {
100437               // not a proper QID
100438               unrecognized();
100439               return;
100440             } // QID value in correct format
100441
100442
100443             _wikiURL = 'https://wikidata.org/wiki/' + _qid;
100444             wikidata.entityByQID(_qid, function (err, entity) {
100445               if (err) {
100446                 unrecognized();
100447                 return;
100448               }
100449
100450               _wikidataEntity = entity;
100451               setLabelForEntity();
100452               var description = entityPropertyForDisplay(entity, 'descriptions');
100453
100454               _selection.select('button.wiki-link').classed('disabled', false);
100455
100456               _selection.select('.preset-wikidata-description').style('display', function () {
100457                 return description.length > 0 ? 'flex' : 'none';
100458               }).select('input').attr('value', description);
100459
100460               _selection.select('.preset-wikidata-identifier').style('display', function () {
100461                 return entity.id ? 'flex' : 'none';
100462               }).select('input').attr('value', entity.id);
100463             }); // not a proper QID
100464
100465             function unrecognized() {
100466               _wikidataEntity = null;
100467               setLabelForEntity();
100468
100469               _selection.select('.preset-wikidata-description').style('display', 'none');
100470
100471               _selection.select('.preset-wikidata-identifier').style('display', 'none');
100472
100473               _selection.select('button.wiki-link').classed('disabled', true);
100474
100475               if (_qid && _qid !== '') {
100476                 _wikiURL = 'https://wikidata.org/wiki/Special:Search?search=' + _qid;
100477               } else {
100478                 _wikiURL = '';
100479               }
100480             }
100481           };
100482
100483           function entityPropertyForDisplay(wikidataEntity, propKey) {
100484             if (!wikidataEntity[propKey]) return '';
100485             var propObj = wikidataEntity[propKey];
100486             var langKeys = Object.keys(propObj);
100487             if (langKeys.length === 0) return ''; // sorted by priority, since we want to show the user's language first if possible
100488
100489             var langs = wikidata.languagesToQuery();
100490
100491             for (var i in langs) {
100492               var lang = langs[i];
100493               var valueObj = propObj[lang];
100494               if (valueObj && valueObj.value && valueObj.value.length > 0) return valueObj.value;
100495             } // default to any available value
100496
100497
100498             return propObj[langKeys[0]].value;
100499           }
100500
100501           wiki.entityIDs = function (val) {
100502             if (!arguments.length) return _entityIDs;
100503             _entityIDs = val;
100504             return wiki;
100505           };
100506
100507           wiki.focus = function () {
100508             _searchInput.node().focus();
100509           };
100510
100511           return utilRebind(wiki, dispatch, 'on');
100512         }
100513
100514         function uiFieldWikipedia(field, context) {
100515           var _arguments = arguments;
100516           var dispatch = dispatch$8('change');
100517           var wikipedia = services.wikipedia;
100518           var wikidata = services.wikidata;
100519
100520           var _langInput = select(null);
100521
100522           var _titleInput = select(null);
100523
100524           var _wikiURL = '';
100525
100526           var _entityIDs;
100527
100528           var _tags;
100529
100530           var _dataWikipedia = [];
100531           _mainFileFetcher.get('wmf_sitematrix').then(function (d) {
100532             _dataWikipedia = d;
100533             if (_tags) updateForTags(_tags);
100534           })["catch"](function () {
100535             /* ignore */
100536           });
100537           var langCombo = uiCombobox(context, 'wikipedia-lang').fetcher(function (value, callback) {
100538             var v = value.toLowerCase();
100539             callback(_dataWikipedia.filter(function (d) {
100540               return d[0].toLowerCase().indexOf(v) >= 0 || d[1].toLowerCase().indexOf(v) >= 0 || d[2].toLowerCase().indexOf(v) >= 0;
100541             }).map(function (d) {
100542               return {
100543                 value: d[1]
100544               };
100545             }));
100546           });
100547           var titleCombo = uiCombobox(context, 'wikipedia-title').fetcher(function (value, callback) {
100548             if (!value) {
100549               value = '';
100550
100551               for (var i in _entityIDs) {
100552                 var entity = context.hasEntity(_entityIDs[i]);
100553
100554                 if (entity.tags.name) {
100555                   value = entity.tags.name;
100556                   break;
100557                 }
100558               }
100559             }
100560
100561             var searchfn = value.length > 7 ? wikipedia.search : wikipedia.suggestions;
100562             searchfn(language()[2], value, function (query, data) {
100563               callback(data.map(function (d) {
100564                 return {
100565                   value: d
100566                 };
100567               }));
100568             });
100569           });
100570
100571           function wiki(selection) {
100572             var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
100573             wrap = wrap.enter().append('div').attr('class', "form-field-input-wrap form-field-input-".concat(field.type)).merge(wrap);
100574             var langContainer = wrap.selectAll('.wiki-lang-container').data([0]);
100575             langContainer = langContainer.enter().append('div').attr('class', 'wiki-lang-container').merge(langContainer);
100576             _langInput = langContainer.selectAll('input.wiki-lang').data([0]);
100577             _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);
100578
100579             _langInput.on('blur', changeLang).on('change', changeLang);
100580
100581             var titleContainer = wrap.selectAll('.wiki-title-container').data([0]);
100582             titleContainer = titleContainer.enter().append('div').attr('class', 'wiki-title-container').merge(titleContainer);
100583             _titleInput = titleContainer.selectAll('input.wiki-title').data([0]);
100584             _titleInput = _titleInput.enter().append('input').attr('type', 'text').attr('class', 'wiki-title').attr('id', field.domId).call(utilNoAuto).call(titleCombo).merge(_titleInput);
100585
100586             _titleInput.on('blur', function () {
100587               change(true);
100588             }).on('change', function () {
100589               change(false);
100590             });
100591
100592             var link = titleContainer.selectAll('.wiki-link').data([0]);
100593             link = link.enter().append('button').attr('class', 'form-field-button wiki-link').attr('title', _t('icons.view_on', {
100594               domain: 'wikipedia.org'
100595             })).call(svgIcon('#iD-icon-out-link')).merge(link);
100596             link.on('click', function (d3_event) {
100597               d3_event.preventDefault();
100598               if (_wikiURL) window.open(_wikiURL, '_blank');
100599             });
100600           }
100601
100602           function defaultLanguageInfo(skipEnglishFallback) {
100603             var langCode = _mainLocalizer.languageCode().toLowerCase();
100604
100605             for (var i in _dataWikipedia) {
100606               var d = _dataWikipedia[i]; // default to the language of iD's current locale
100607
100608               if (d[2] === langCode) return d;
100609             } // fallback to English
100610
100611
100612             return skipEnglishFallback ? ['', '', ''] : ['English', 'English', 'en'];
100613           }
100614
100615           function language(skipEnglishFallback) {
100616             var value = utilGetSetValue(_langInput).toLowerCase();
100617
100618             for (var i in _dataWikipedia) {
100619               var d = _dataWikipedia[i]; // return the language already set in the UI, if supported
100620
100621               if (d[0].toLowerCase() === value || d[1].toLowerCase() === value || d[2] === value) return d;
100622             } // fallback to English
100623
100624
100625             return defaultLanguageInfo(skipEnglishFallback);
100626           }
100627
100628           function changeLang() {
100629             utilGetSetValue(_langInput, language()[1]);
100630             change(true);
100631           }
100632
100633           function change(skipWikidata) {
100634             var value = utilGetSetValue(_titleInput);
100635             var m = value.match(/https?:\/\/([-a-z]+)\.wikipedia\.org\/(?:wiki|\1-[-a-z]+)\/([^#]+)(?:#(.+))?/);
100636
100637             var langInfo = m && _dataWikipedia.find(function (d) {
100638               return m[1] === d[2];
100639             });
100640
100641             var syncTags = {};
100642
100643             if (langInfo) {
100644               var nativeLangName = langInfo[1]; // Normalize title http://www.mediawiki.org/wiki/API:Query#Title_normalization
100645
100646               value = decodeURIComponent(m[2]).replace(/_/g, ' ');
100647
100648               if (m[3]) {
100649                 var anchor; // try {
100650                 // leave this out for now - #6232
100651                 // Best-effort `anchordecode:` implementation
100652                 // anchor = decodeURIComponent(m[3].replace(/\.([0-9A-F]{2})/g, '%$1'));
100653                 // } catch (e) {
100654
100655                 anchor = decodeURIComponent(m[3]); // }
100656
100657                 value += '#' + anchor.replace(/_/g, ' ');
100658               }
100659
100660               value = value.slice(0, 1).toUpperCase() + value.slice(1);
100661               utilGetSetValue(_langInput, nativeLangName);
100662               utilGetSetValue(_titleInput, value);
100663             }
100664
100665             if (value) {
100666               syncTags.wikipedia = context.cleanTagValue(language()[2] + ':' + value);
100667             } else {
100668               syncTags.wikipedia = undefined;
100669             }
100670
100671             dispatch.call('change', this, syncTags);
100672             if (skipWikidata || !value || !language()[2]) return; // attempt asynchronous update of wikidata tag..
100673
100674             var initGraph = context.graph();
100675             var initEntityIDs = _entityIDs;
100676             wikidata.itemsByTitle(language()[2], value, function (err, data) {
100677               if (err || !data || !Object.keys(data).length) return; // If graph has changed, we can't apply this update.
100678
100679               if (context.graph() !== initGraph) return;
100680               var qids = Object.keys(data);
100681               var value = qids && qids.find(function (id) {
100682                 return id.match(/^Q\d+$/);
100683               });
100684               var actions = initEntityIDs.map(function (entityID) {
100685                 var entity = context.entity(entityID).tags;
100686                 var currTags = Object.assign({}, entity); // shallow copy
100687
100688                 if (currTags.wikidata !== value) {
100689                   currTags.wikidata = value;
100690                   return actionChangeTags(entityID, currTags);
100691                 }
100692
100693                 return null;
100694               }).filter(Boolean);
100695               if (!actions.length) return; // Coalesce the update of wikidata tag into the previous tag change
100696
100697               context.overwrite(function actionUpdateWikidataTags(graph) {
100698                 actions.forEach(function (action) {
100699                   graph = action(graph);
100700                 });
100701                 return graph;
100702               }, context.history().undoAnnotation()); // do not dispatch.call('change') here, because entity_editor
100703               // changeTags() is not intended to be called asynchronously
100704             });
100705           }
100706
100707           wiki.tags = function (tags) {
100708             _tags = tags;
100709             updateForTags(tags);
100710           };
100711
100712           function updateForTags(tags) {
100713             var value = typeof tags[field.key] === 'string' ? tags[field.key] : ''; // Expect tag format of `tagLang:tagArticleTitle`, e.g. `fr:Paris`, with
100714             // optional suffix of `#anchor`
100715
100716             var m = value.match(/([^:]+):([^#]+)(?:#(.+))?/);
100717             var tagLang = m && m[1];
100718             var tagArticleTitle = m && m[2];
100719             var anchor = m && m[3];
100720
100721             var tagLangInfo = tagLang && _dataWikipedia.find(function (d) {
100722               return tagLang === d[2];
100723             }); // value in correct format
100724
100725
100726             if (tagLangInfo) {
100727               var nativeLangName = tagLangInfo[1];
100728               utilGetSetValue(_langInput, nativeLangName);
100729               utilGetSetValue(_titleInput, tagArticleTitle + (anchor ? '#' + anchor : ''));
100730
100731               if (anchor) {
100732                 try {
100733                   // Best-effort `anchorencode:` implementation
100734                   anchor = encodeURIComponent(anchor.replace(/ /g, '_')).replace(/%/g, '.');
100735                 } catch (e) {
100736                   anchor = anchor.replace(/ /g, '_');
100737                 }
100738               }
100739
100740               _wikiURL = 'https://' + tagLang + '.wikipedia.org/wiki/' + tagArticleTitle.replace(/ /g, '_') + (anchor ? '#' + anchor : ''); // unrecognized value format
100741             } else {
100742               utilGetSetValue(_titleInput, value);
100743
100744               if (value && value !== '') {
100745                 utilGetSetValue(_langInput, '');
100746                 var defaultLangInfo = defaultLanguageInfo();
100747                 _wikiURL = "https://".concat(defaultLangInfo[2], ".wikipedia.org/w/index.php?fulltext=1&search=").concat(value);
100748               } else {
100749                 var shownOrDefaultLangInfo = language(true
100750                 /* skipEnglishFallback */
100751                 );
100752                 utilGetSetValue(_langInput, shownOrDefaultLangInfo[1]);
100753                 _wikiURL = '';
100754               }
100755             }
100756           }
100757
100758           wiki.entityIDs = function (val) {
100759             if (!_arguments.length) return _entityIDs;
100760             _entityIDs = val;
100761             return wiki;
100762           };
100763
100764           wiki.focus = function () {
100765             _titleInput.node().focus();
100766           };
100767
100768           return utilRebind(wiki, dispatch, 'on');
100769         }
100770         uiFieldWikipedia.supportsMultiselection = false;
100771
100772         var uiFields = {
100773           access: uiFieldAccess,
100774           address: uiFieldAddress,
100775           check: uiFieldCheck,
100776           combo: uiFieldCombo,
100777           cycleway: uiFieldCycleway,
100778           defaultCheck: uiFieldCheck,
100779           email: uiFieldText,
100780           identifier: uiFieldText,
100781           lanes: uiFieldLanes,
100782           localized: uiFieldLocalized,
100783           roadheight: uiFieldRoadheight,
100784           roadspeed: uiFieldRoadspeed,
100785           manyCombo: uiFieldCombo,
100786           multiCombo: uiFieldCombo,
100787           networkCombo: uiFieldCombo,
100788           number: uiFieldText,
100789           onewayCheck: uiFieldCheck,
100790           radio: uiFieldRadio,
100791           restrictions: uiFieldRestrictions,
100792           semiCombo: uiFieldCombo,
100793           structureRadio: uiFieldRadio,
100794           tel: uiFieldText,
100795           text: uiFieldText,
100796           textarea: uiFieldTextarea,
100797           typeCombo: uiFieldCombo,
100798           url: uiFieldText,
100799           wikidata: uiFieldWikidata,
100800           wikipedia: uiFieldWikipedia
100801         };
100802
100803         function uiField(context, presetField, entityIDs, options) {
100804           options = Object.assign({
100805             show: true,
100806             wrap: true,
100807             remove: true,
100808             revert: true,
100809             info: true
100810           }, options);
100811           var dispatch = dispatch$8('change', 'revert');
100812           var field = Object.assign({}, presetField); // shallow copy
100813
100814           field.domId = utilUniqueDomId('form-field-' + field.safeid);
100815           var _show = options.show;
100816           var _state = '';
100817           var _tags = {};
100818
100819           var _entityExtent;
100820
100821           if (entityIDs && entityIDs.length) {
100822             _entityExtent = entityIDs.reduce(function (extent, entityID) {
100823               var entity = context.graph().entity(entityID);
100824               return extent.extend(entity.extent(context.graph()));
100825             }, geoExtent());
100826           }
100827
100828           var _locked = false;
100829
100830           var _lockedTip = uiTooltip().title(_t.html('inspector.lock.suggestion', {
100831             label: field.label
100832           })).placement('bottom');
100833
100834           field.keys = field.keys || [field.key]; // only create the fields that are actually being shown
100835
100836           if (_show && !field.impl) {
100837             createField();
100838           } // Creates the field.. This is done lazily,
100839           // once we know that the field will be shown.
100840
100841
100842           function createField() {
100843             field.impl = uiFields[field.type](field, context).on('change', function (t, onInput) {
100844               dispatch.call('change', field, t, onInput);
100845             });
100846
100847             if (entityIDs) {
100848               field.entityIDs = entityIDs; // if this field cares about the entities, pass them along
100849
100850               if (field.impl.entityIDs) {
100851                 field.impl.entityIDs(entityIDs);
100852               }
100853             }
100854           }
100855
100856           function isModified() {
100857             if (!entityIDs || !entityIDs.length) return false;
100858             return entityIDs.some(function (entityID) {
100859               var original = context.graph().base().entities[entityID];
100860               var latest = context.graph().entity(entityID);
100861               return field.keys.some(function (key) {
100862                 return original ? latest.tags[key] !== original.tags[key] : latest.tags[key];
100863               });
100864             });
100865           }
100866
100867           function tagsContainFieldKey() {
100868             return field.keys.some(function (key) {
100869               if (field.type === 'multiCombo') {
100870                 for (var tagKey in _tags) {
100871                   if (tagKey.indexOf(key) === 0) {
100872                     return true;
100873                   }
100874                 }
100875
100876                 return false;
100877               }
100878
100879               return _tags[key] !== undefined;
100880             });
100881           }
100882
100883           function revert(d3_event, d) {
100884             d3_event.stopPropagation();
100885             d3_event.preventDefault();
100886             if (!entityIDs || _locked) return;
100887             dispatch.call('revert', d, d.keys);
100888           }
100889
100890           function remove(d3_event, d) {
100891             d3_event.stopPropagation();
100892             d3_event.preventDefault();
100893             if (_locked) return;
100894             var t = {};
100895             d.keys.forEach(function (key) {
100896               t[key] = undefined;
100897             });
100898             dispatch.call('change', d, t);
100899           }
100900
100901           field.render = function (selection) {
100902             var container = selection.selectAll('.form-field').data([field]); // Enter
100903
100904             var enter = container.enter().append('div').attr('class', function (d) {
100905               return 'form-field form-field-' + d.safeid;
100906             }).classed('nowrap', !options.wrap);
100907
100908             if (options.wrap) {
100909               var labelEnter = enter.append('label').attr('class', 'field-label').attr('for', function (d) {
100910                 return d.domId;
100911               });
100912               var textEnter = labelEnter.append('span').attr('class', 'label-text');
100913               textEnter.append('span').attr('class', 'label-textvalue').html(function (d) {
100914                 return d.label();
100915               });
100916               textEnter.append('span').attr('class', 'label-textannotation');
100917
100918               if (options.remove) {
100919                 labelEnter.append('button').attr('class', 'remove-icon').attr('title', _t('icons.remove')).call(svgIcon('#iD-operation-delete'));
100920               }
100921
100922               if (options.revert) {
100923                 labelEnter.append('button').attr('class', 'modified-icon').attr('title', _t('icons.undo')).call(svgIcon(_mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-redo' : '#iD-icon-undo'));
100924               }
100925             } // Update
100926
100927
100928             container = container.merge(enter);
100929             container.select('.field-label > .remove-icon') // propagate bound data
100930             .on('click', remove);
100931             container.select('.field-label > .modified-icon') // propagate bound data
100932             .on('click', revert);
100933             container.each(function (d) {
100934               var selection = select(this);
100935
100936               if (!d.impl) {
100937                 createField();
100938               }
100939
100940               var reference, help; // instantiate field help
100941
100942               if (options.wrap && field.type === 'restrictions') {
100943                 help = uiFieldHelp(context, 'restrictions');
100944               } // instantiate tag reference
100945
100946
100947               if (options.wrap && options.info) {
100948                 var referenceKey = d.key || '';
100949
100950                 if (d.type === 'multiCombo') {
100951                   // lookup key without the trailing ':'
100952                   referenceKey = referenceKey.replace(/:$/, '');
100953                 }
100954
100955                 reference = uiTagReference(d.reference || {
100956                   key: referenceKey
100957                 });
100958
100959                 if (_state === 'hover') {
100960                   reference.showing(false);
100961                 }
100962               }
100963
100964               selection.call(d.impl); // add field help components
100965
100966               if (help) {
100967                 selection.call(help.body).select('.field-label').call(help.button);
100968               } // add tag reference components
100969
100970
100971               if (reference) {
100972                 selection.call(reference.body).select('.field-label').call(reference.button);
100973               }
100974
100975               d.impl.tags(_tags);
100976             });
100977             container.classed('locked', _locked).classed('modified', isModified()).classed('present', tagsContainFieldKey()); // show a tip and lock icon if the field is locked
100978
100979             var annotation = container.selectAll('.field-label .label-textannotation');
100980             var icon = annotation.selectAll('.icon').data(_locked ? [0] : []);
100981             icon.exit().remove();
100982             icon.enter().append('svg').attr('class', 'icon').append('use').attr('xlink:href', '#fas-lock');
100983             container.call(_locked ? _lockedTip : _lockedTip.destroy);
100984           };
100985
100986           field.state = function (val) {
100987             if (!arguments.length) return _state;
100988             _state = val;
100989             return field;
100990           };
100991
100992           field.tags = function (val) {
100993             if (!arguments.length) return _tags;
100994             _tags = val;
100995
100996             if (tagsContainFieldKey() && !_show) {
100997               // always show a field if it has a value to display
100998               _show = true;
100999
101000               if (!field.impl) {
101001                 createField();
101002               }
101003             }
101004
101005             return field;
101006           };
101007
101008           field.locked = function (val) {
101009             if (!arguments.length) return _locked;
101010             _locked = val;
101011             return field;
101012           };
101013
101014           field.show = function () {
101015             _show = true;
101016
101017             if (!field.impl) {
101018               createField();
101019             }
101020
101021             if (field["default"] && field.key && _tags[field.key] !== field["default"]) {
101022               var t = {};
101023               t[field.key] = field["default"];
101024               dispatch.call('change', this, t);
101025             }
101026           }; // A shown field has a visible UI, a non-shown field is in the 'Add field' dropdown
101027
101028
101029           field.isShown = function () {
101030             return _show;
101031           }; // An allowed field can appear in the UI or in the 'Add field' dropdown.
101032           // A non-allowed field is hidden from the user altogether
101033
101034
101035           field.isAllowed = function () {
101036             if (entityIDs && entityIDs.length > 1 && uiFields[field.type].supportsMultiselection === false) return false;
101037             if (field.geometry && !entityIDs.every(function (entityID) {
101038               return field.matchGeometry(context.graph().geometry(entityID));
101039             })) return false;
101040
101041             if (entityIDs && _entityExtent && field.locationSetID) {
101042               // is field allowed in this location?
101043               var validLocations = _mainLocations.locationsAt(_entityExtent.center());
101044               if (!validLocations[field.locationSetID]) return false;
101045             }
101046
101047             var prerequisiteTag = field.prerequisiteTag;
101048
101049             if (entityIDs && !tagsContainFieldKey() && // ignore tagging prerequisites if a value is already present
101050             prerequisiteTag) {
101051               if (!entityIDs.every(function (entityID) {
101052                 var entity = context.graph().entity(entityID);
101053
101054                 if (prerequisiteTag.key) {
101055                   var value = entity.tags[prerequisiteTag.key];
101056                   if (!value) return false;
101057
101058                   if (prerequisiteTag.valueNot) {
101059                     return prerequisiteTag.valueNot !== value;
101060                   }
101061
101062                   if (prerequisiteTag.value) {
101063                     return prerequisiteTag.value === value;
101064                   }
101065                 } else if (prerequisiteTag.keyNot) {
101066                   if (entity.tags[prerequisiteTag.keyNot]) return false;
101067                 }
101068
101069                 return true;
101070               })) return false;
101071             }
101072
101073             return true;
101074           };
101075
101076           field.focus = function () {
101077             if (field.impl) {
101078               field.impl.focus();
101079             }
101080           };
101081
101082           return utilRebind(field, dispatch, 'on');
101083         }
101084
101085         function uiFormFields(context) {
101086           var moreCombo = uiCombobox(context, 'more-fields').minItems(1);
101087           var _fieldsArr = [];
101088           var _lastPlaceholder = '';
101089           var _state = '';
101090           var _klass = '';
101091
101092           function formFields(selection) {
101093             var allowedFields = _fieldsArr.filter(function (field) {
101094               return field.isAllowed();
101095             });
101096
101097             var shown = allowedFields.filter(function (field) {
101098               return field.isShown();
101099             });
101100             var notShown = allowedFields.filter(function (field) {
101101               return !field.isShown();
101102             });
101103             var container = selection.selectAll('.form-fields-container').data([0]);
101104             container = container.enter().append('div').attr('class', 'form-fields-container ' + (_klass || '')).merge(container);
101105             var fields = container.selectAll('.wrap-form-field').data(shown, function (d) {
101106               return d.id + (d.entityIDs ? d.entityIDs.join() : '');
101107             });
101108             fields.exit().remove(); // Enter
101109
101110             var enter = fields.enter().append('div').attr('class', function (d) {
101111               return 'wrap-form-field wrap-form-field-' + d.safeid;
101112             }); // Update
101113
101114             fields = fields.merge(enter);
101115             fields.order().each(function (d) {
101116               select(this).call(d.render);
101117             });
101118             var titles = [];
101119             var moreFields = notShown.map(function (field) {
101120               var title = field.title();
101121               titles.push(title);
101122               var terms = field.terms();
101123               if (field.key) terms.push(field.key);
101124               if (field.keys) terms = terms.concat(field.keys);
101125               return {
101126                 display: field.label(),
101127                 value: title,
101128                 title: title,
101129                 field: field,
101130                 terms: terms
101131               };
101132             });
101133             var placeholder = titles.slice(0, 3).join(', ') + (titles.length > 3 ? '…' : '');
101134             var more = selection.selectAll('.more-fields').data(_state === 'hover' || moreFields.length === 0 ? [] : [0]);
101135             more.exit().remove();
101136             var moreEnter = more.enter().append('div').attr('class', 'more-fields').append('label');
101137             moreEnter.append('span').call(_t.append('inspector.add_fields'));
101138             more = moreEnter.merge(more);
101139             var input = more.selectAll('.value').data([0]);
101140             input.exit().remove();
101141             input = input.enter().append('input').attr('class', 'value').attr('type', 'text').attr('placeholder', placeholder).call(utilNoAuto).merge(input);
101142             input.call(utilGetSetValue, '').call(moreCombo.data(moreFields).on('accept', function (d) {
101143               if (!d) return; // user entered something that was not matched
101144
101145               var field = d.field;
101146               field.show();
101147               selection.call(formFields); // rerender
101148
101149               field.focus();
101150             })); // avoid updating placeholder excessively (triggers style recalc)
101151
101152             if (_lastPlaceholder !== placeholder) {
101153               input.attr('placeholder', placeholder);
101154               _lastPlaceholder = placeholder;
101155             }
101156           }
101157
101158           formFields.fieldsArr = function (val) {
101159             if (!arguments.length) return _fieldsArr;
101160             _fieldsArr = val || [];
101161             return formFields;
101162           };
101163
101164           formFields.state = function (val) {
101165             if (!arguments.length) return _state;
101166             _state = val;
101167             return formFields;
101168           };
101169
101170           formFields.klass = function (val) {
101171             if (!arguments.length) return _klass;
101172             _klass = val;
101173             return formFields;
101174           };
101175
101176           return formFields;
101177         }
101178
101179         function uiChangesetEditor(context) {
101180           var dispatch = dispatch$8('change');
101181           var formFields = uiFormFields(context);
101182           var commentCombo = uiCombobox(context, 'comment').caseSensitive(true);
101183
101184           var _fieldsArr;
101185
101186           var _tags;
101187
101188           var _changesetID;
101189
101190           function changesetEditor(selection) {
101191             render(selection);
101192           }
101193
101194           function render(selection) {
101195             var initial = false;
101196
101197             if (!_fieldsArr) {
101198               initial = true;
101199               var presets = _mainPresetIndex;
101200               _fieldsArr = [uiField(context, presets.field('comment'), null, {
101201                 show: true,
101202                 revert: false
101203               }), uiField(context, presets.field('source'), null, {
101204                 show: false,
101205                 revert: false
101206               }), uiField(context, presets.field('hashtags'), null, {
101207                 show: false,
101208                 revert: false
101209               })];
101210
101211               _fieldsArr.forEach(function (field) {
101212                 field.on('change', function (t, onInput) {
101213                   dispatch.call('change', field, undefined, t, onInput);
101214                 });
101215               });
101216             }
101217
101218             _fieldsArr.forEach(function (field) {
101219               field.tags(_tags);
101220             });
101221
101222             selection.call(formFields.fieldsArr(_fieldsArr));
101223
101224             if (initial) {
101225               var commentField = selection.select('.form-field-comment textarea');
101226               var commentNode = commentField.node();
101227
101228               if (commentNode) {
101229                 commentNode.focus();
101230                 commentNode.select();
101231               } // trigger a 'blur' event so that comment field can be cleaned
101232               // and checked for hashtags, even if retrieved from localstorage
101233
101234
101235               utilTriggerEvent(commentField, 'blur');
101236               var osm = context.connection();
101237
101238               if (osm) {
101239                 osm.userChangesets(function (err, changesets) {
101240                   if (err) return;
101241                   var comments = changesets.map(function (changeset) {
101242                     var comment = changeset.tags.comment;
101243                     return comment ? {
101244                       title: comment,
101245                       value: comment
101246                     } : null;
101247                   }).filter(Boolean);
101248                   commentField.call(commentCombo.data(utilArrayUniqBy(comments, 'title')));
101249                 });
101250               }
101251             } // Add warning if comment mentions Google
101252
101253
101254             var hasGoogle = _tags.comment.match(/google/i);
101255
101256             var commentWarning = selection.select('.form-field-comment').selectAll('.comment-warning').data(hasGoogle ? [0] : []);
101257             commentWarning.exit().transition().duration(200).style('opacity', 0).remove();
101258             var commentEnter = commentWarning.enter().insert('div', '.tag-reference-body').attr('class', 'field-warning comment-warning').style('opacity', 0);
101259             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'));
101260             commentEnter.transition().duration(200).style('opacity', 1);
101261           }
101262
101263           changesetEditor.tags = function (_) {
101264             if (!arguments.length) return _tags;
101265             _tags = _; // Don't reset _fieldsArr here.
101266
101267             return changesetEditor;
101268           };
101269
101270           changesetEditor.changesetID = function (_) {
101271             if (!arguments.length) return _changesetID;
101272             if (_changesetID === _) return changesetEditor;
101273             _changesetID = _;
101274             _fieldsArr = null;
101275             return changesetEditor;
101276           };
101277
101278           return utilRebind(changesetEditor, dispatch, 'on');
101279         }
101280
101281         var JXON = new function () {
101282           var sValueProp = 'keyValue',
101283               sAttributesProp = 'keyAttributes',
101284               sAttrPref = '@',
101285
101286           /* you can customize these values */
101287           aCache = [],
101288               rIsNull = /^\s*$/,
101289               rIsBool = /^(?:true|false)$/i;
101290
101291           function parseText(sValue) {
101292             if (rIsNull.test(sValue)) {
101293               return null;
101294             }
101295
101296             if (rIsBool.test(sValue)) {
101297               return sValue.toLowerCase() === 'true';
101298             }
101299
101300             if (isFinite(sValue)) {
101301               return parseFloat(sValue);
101302             }
101303
101304             if (isFinite(Date.parse(sValue))) {
101305               return new Date(sValue);
101306             }
101307
101308             return sValue;
101309           }
101310
101311           function EmptyTree() {}
101312
101313           EmptyTree.prototype.toString = function () {
101314             return 'null';
101315           };
101316
101317           EmptyTree.prototype.valueOf = function () {
101318             return null;
101319           };
101320
101321           function objectify(vValue) {
101322             return vValue === null ? new EmptyTree() : vValue instanceof Object ? vValue : new vValue.constructor(vValue);
101323           }
101324
101325           function createObjTree(oParentNode, nVerb, bFreeze, bNesteAttr) {
101326             var nLevelStart = aCache.length,
101327                 bChildren = oParentNode.hasChildNodes(),
101328                 bAttributes = oParentNode.hasAttributes(),
101329                 bHighVerb = Boolean(nVerb & 2);
101330             var sProp,
101331                 vContent,
101332                 nLength = 0,
101333                 sCollectedTxt = '',
101334                 vResult = bHighVerb ? {} :
101335             /* put here the default value for empty nodes: */
101336             true;
101337
101338             if (bChildren) {
101339               for (var oNode, nItem = 0; nItem < oParentNode.childNodes.length; nItem++) {
101340                 oNode = oParentNode.childNodes.item(nItem);
101341
101342                 if (oNode.nodeType === 4) {
101343                   /* nodeType is 'CDATASection' (4) */
101344                   sCollectedTxt += oNode.nodeValue;
101345                 } else if (oNode.nodeType === 3) {
101346                   /* nodeType is 'Text' (3) */
101347                   sCollectedTxt += oNode.nodeValue.trim();
101348                 } else if (oNode.nodeType === 1 && !oNode.prefix) {
101349                   /* nodeType is 'Element' (1) */
101350                   aCache.push(oNode);
101351                 }
101352               }
101353             }
101354
101355             var nLevelEnd = aCache.length,
101356                 vBuiltVal = parseText(sCollectedTxt);
101357
101358             if (!bHighVerb && (bChildren || bAttributes)) {
101359               vResult = nVerb === 0 ? objectify(vBuiltVal) : {};
101360             }
101361
101362             for (var nElId = nLevelStart; nElId < nLevelEnd; nElId++) {
101363               sProp = aCache[nElId].nodeName.toLowerCase();
101364               vContent = createObjTree(aCache[nElId], nVerb, bFreeze, bNesteAttr);
101365
101366               if (vResult.hasOwnProperty(sProp)) {
101367                 if (vResult[sProp].constructor !== Array) {
101368                   vResult[sProp] = [vResult[sProp]];
101369                 }
101370
101371                 vResult[sProp].push(vContent);
101372               } else {
101373                 vResult[sProp] = vContent;
101374                 nLength++;
101375               }
101376             }
101377
101378             if (bAttributes) {
101379               var nAttrLen = oParentNode.attributes.length,
101380                   sAPrefix = bNesteAttr ? '' : sAttrPref,
101381                   oAttrParent = bNesteAttr ? {} : vResult;
101382
101383               for (var oAttrib, nAttrib = 0; nAttrib < nAttrLen; nLength++, nAttrib++) {
101384                 oAttrib = oParentNode.attributes.item(nAttrib);
101385                 oAttrParent[sAPrefix + oAttrib.name.toLowerCase()] = parseText(oAttrib.value.trim());
101386               }
101387
101388               if (bNesteAttr) {
101389                 if (bFreeze) {
101390                   Object.freeze(oAttrParent);
101391                 }
101392
101393                 vResult[sAttributesProp] = oAttrParent;
101394                 nLength -= nAttrLen - 1;
101395               }
101396             }
101397
101398             if (nVerb === 3 || (nVerb === 2 || nVerb === 1 && nLength > 0) && sCollectedTxt) {
101399               vResult[sValueProp] = vBuiltVal;
101400             } else if (!bHighVerb && nLength === 0 && sCollectedTxt) {
101401               vResult = vBuiltVal;
101402             }
101403
101404             if (bFreeze && (bHighVerb || nLength > 0)) {
101405               Object.freeze(vResult);
101406             }
101407
101408             aCache.length = nLevelStart;
101409             return vResult;
101410           }
101411
101412           function loadObjTree(oXMLDoc, oParentEl, oParentObj) {
101413             var vValue, oChild;
101414
101415             if (oParentObj instanceof String || oParentObj instanceof Number || oParentObj instanceof Boolean) {
101416               oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toString()));
101417               /* verbosity level is 0 */
101418             } else if (oParentObj.constructor === Date) {
101419               oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toGMTString()));
101420             }
101421
101422             for (var sName in oParentObj) {
101423               vValue = oParentObj[sName];
101424
101425               if (isFinite(sName) || vValue instanceof Function) {
101426                 continue;
101427               }
101428               /* verbosity level is 0 */
101429
101430
101431               if (sName === sValueProp) {
101432                 if (vValue !== null && vValue !== true) {
101433                   oParentEl.appendChild(oXMLDoc.createTextNode(vValue.constructor === Date ? vValue.toGMTString() : String(vValue)));
101434                 }
101435               } else if (sName === sAttributesProp) {
101436                 /* verbosity level is 3 */
101437                 for (var sAttrib in vValue) {
101438                   oParentEl.setAttribute(sAttrib, vValue[sAttrib]);
101439                 }
101440               } else if (sName.charAt(0) === sAttrPref) {
101441                 oParentEl.setAttribute(sName.slice(1), vValue);
101442               } else if (vValue.constructor === Array) {
101443                 for (var nItem = 0; nItem < vValue.length; nItem++) {
101444                   oChild = oXMLDoc.createElement(sName);
101445                   loadObjTree(oXMLDoc, oChild, vValue[nItem]);
101446                   oParentEl.appendChild(oChild);
101447                 }
101448               } else {
101449                 oChild = oXMLDoc.createElement(sName);
101450
101451                 if (vValue instanceof Object) {
101452                   loadObjTree(oXMLDoc, oChild, vValue);
101453                 } else if (vValue !== null && vValue !== true) {
101454                   oChild.appendChild(oXMLDoc.createTextNode(vValue.toString()));
101455                 }
101456
101457                 oParentEl.appendChild(oChild);
101458               }
101459             }
101460           }
101461
101462           this.build = function (oXMLParent, nVerbosity
101463           /* optional */
101464           , bFreeze
101465           /* optional */
101466           , bNesteAttributes
101467           /* optional */
101468           ) {
101469             var _nVerb = arguments.length > 1 && typeof nVerbosity === 'number' ? nVerbosity & 3 :
101470             /* put here the default verbosity level: */
101471             1;
101472
101473             return createObjTree(oXMLParent, _nVerb, bFreeze || false, arguments.length > 3 ? bNesteAttributes : _nVerb === 3);
101474           };
101475
101476           this.unbuild = function (oObjTree) {
101477             var oNewDoc = document.implementation.createDocument('', '', null);
101478             loadObjTree(oNewDoc, oNewDoc, oObjTree);
101479             return oNewDoc;
101480           };
101481
101482           this.stringify = function (oObjTree) {
101483             return new XMLSerializer().serializeToString(JXON.unbuild(oObjTree));
101484           };
101485         }(); // var myObject = JXON.build(doc);
101486         // we got our javascript object! try: alert(JSON.stringify(myObject));
101487         // var newDoc = JXON.unbuild(myObject);
101488         // we got our Document instance! try: alert((new XMLSerializer()).serializeToString(newDoc));
101489
101490         function uiSectionChanges(context) {
101491           var detected = utilDetect();
101492           var _discardTags = {};
101493           _mainFileFetcher.get('discarded').then(function (d) {
101494             _discardTags = d;
101495           })["catch"](function () {
101496             /* ignore */
101497           });
101498           var section = uiSection('changes-list', context).label(function () {
101499             var history = context.history();
101500             var summary = history.difference().summary();
101501             return _t.html('inspector.title_count', {
101502               title: {
101503                 html: _t.html('commit.changes')
101504               },
101505               count: summary.length
101506             });
101507           }).disclosureContent(renderDisclosureContent);
101508
101509           function renderDisclosureContent(selection) {
101510             var history = context.history();
101511             var summary = history.difference().summary();
101512             var container = selection.selectAll('.commit-section').data([0]);
101513             var containerEnter = container.enter().append('div').attr('class', 'commit-section');
101514             containerEnter.append('ul').attr('class', 'changeset-list');
101515             container = containerEnter.merge(container);
101516             var items = container.select('ul').selectAll('li').data(summary);
101517             var itemsEnter = items.enter().append('li').attr('class', 'change-item');
101518             var buttons = itemsEnter.append('button').on('mouseover', mouseover).on('mouseout', mouseout).on('click', click);
101519             buttons.each(function (d) {
101520               select(this).call(svgIcon('#iD-icon-' + d.entity.geometry(d.graph), 'pre-text ' + d.changeType));
101521             });
101522             buttons.append('span').attr('class', 'change-type').html(function (d) {
101523               return _t.html('commit.' + d.changeType) + ' ';
101524             });
101525             buttons.append('strong').attr('class', 'entity-type').text(function (d) {
101526               var matched = _mainPresetIndex.match(d.entity, d.graph);
101527               return matched && matched.name() || utilDisplayType(d.entity.id);
101528             });
101529             buttons.append('span').attr('class', 'entity-name').text(function (d) {
101530               var name = utilDisplayName(d.entity) || '',
101531                   string = '';
101532
101533               if (name !== '') {
101534                 string += ':';
101535               }
101536
101537               return string += ' ' + name;
101538             });
101539             items = itemsEnter.merge(items); // Download changeset link
101540
101541             var changeset = new osmChangeset().update({
101542               id: undefined
101543             });
101544             var changes = history.changes(actionDiscardTags(history.difference(), _discardTags));
101545             delete changeset.id; // Export without chnageset_id
101546
101547             var data = JXON.stringify(changeset.osmChangeJXON(changes));
101548             var blob = new Blob([data], {
101549               type: 'text/xml;charset=utf-8;'
101550             });
101551             var fileName = 'changes.osc';
101552             var linkEnter = container.selectAll('.download-changes').data([0]).enter().append('a').attr('class', 'download-changes');
101553
101554             if (detected.download) {
101555               // All except IE11 and Edge
101556               linkEnter // download the data as a file
101557               .attr('href', window.URL.createObjectURL(blob)).attr('download', fileName);
101558             } else {
101559               // IE11 and Edge
101560               linkEnter // open data uri in a new tab
101561               .attr('target', '_blank').on('click.download', function () {
101562                 navigator.msSaveBlob(blob, fileName);
101563               });
101564             }
101565
101566             linkEnter.call(svgIcon('#iD-icon-load', 'inline')).append('span').call(_t.append('commit.download_changes'));
101567
101568             function mouseover(d) {
101569               if (d.entity) {
101570                 context.surface().selectAll(utilEntityOrMemberSelector([d.entity.id], context.graph())).classed('hover', true);
101571               }
101572             }
101573
101574             function mouseout() {
101575               context.surface().selectAll('.hover').classed('hover', false);
101576             }
101577
101578             function click(d3_event, change) {
101579               if (change.changeType !== 'deleted') {
101580                 var entity = change.entity;
101581                 context.map().zoomToEase(entity);
101582                 context.surface().selectAll(utilEntityOrMemberSelector([entity.id], context.graph())).classed('hover', true);
101583               }
101584             }
101585           }
101586
101587           return section;
101588         }
101589
101590         function uiCommitWarnings(context) {
101591           function commitWarnings(selection) {
101592             var issuesBySeverity = context.validator().getIssuesBySeverity({
101593               what: 'edited',
101594               where: 'all',
101595               includeDisabledRules: true
101596             });
101597
101598             for (var severity in issuesBySeverity) {
101599               var issues = issuesBySeverity[severity];
101600
101601               if (severity !== 'error') {
101602                 // exclude 'fixme' and similar - #8603
101603                 issues = issues.filter(function (issue) {
101604                   return issue.type !== 'help_request';
101605                 });
101606               }
101607
101608               var section = severity + '-section';
101609               var issueItem = severity + '-item';
101610               var container = selection.selectAll('.' + section).data(issues.length ? [0] : []);
101611               container.exit().remove();
101612               var containerEnter = container.enter().append('div').attr('class', 'modal-section ' + section + ' fillL2');
101613               containerEnter.append('h3').html(severity === 'warning' ? _t.html('commit.warnings') : _t.html('commit.errors'));
101614               containerEnter.append('ul').attr('class', 'changeset-list');
101615               container = containerEnter.merge(container);
101616               var items = container.select('ul').selectAll('li').data(issues, function (d) {
101617                 return d.key;
101618               });
101619               items.exit().remove();
101620               var itemsEnter = items.enter().append('li').attr('class', issueItem);
101621               var buttons = itemsEnter.append('button').on('mouseover', function (d3_event, d) {
101622                 if (d.entityIds) {
101623                   context.surface().selectAll(utilEntityOrMemberSelector(d.entityIds, context.graph())).classed('hover', true);
101624                 }
101625               }).on('mouseout', function () {
101626                 context.surface().selectAll('.hover').classed('hover', false);
101627               }).on('click', function (d3_event, d) {
101628                 context.validator().focusIssue(d);
101629               });
101630               buttons.call(svgIcon('#iD-icon-alert', 'pre-text'));
101631               buttons.append('strong').attr('class', 'issue-message');
101632               buttons.filter(function (d) {
101633                 return d.tooltip;
101634               }).call(uiTooltip().title(function (d) {
101635                 return d.tooltip;
101636               }).placement('top'));
101637               items = itemsEnter.merge(items);
101638               items.selectAll('.issue-message').html(function (d) {
101639                 return d.message(context);
101640               });
101641             }
101642           }
101643
101644           return commitWarnings;
101645         }
101646
101647         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
101648         // from https://stackoverflow.com/a/25575009
101649
101650         var hashtagRegex = /(#[^\u2000-\u206F\u2E00-\u2E7F\s\\'!"#$%()*,.\/:;<=>?@\[\]^`{|}~]+)/g;
101651         function uiCommit(context) {
101652           var dispatch = dispatch$8('cancel');
101653
101654           var _userDetails;
101655
101656           var _selection;
101657
101658           var changesetEditor = uiChangesetEditor(context).on('change', changeTags);
101659           var rawTagEditor = uiSectionRawTagEditor('changeset-tag-editor', context).on('change', changeTags).readOnlyTags(readOnlyTags);
101660           var commitChanges = uiSectionChanges(context);
101661           var commitWarnings = uiCommitWarnings(context);
101662
101663           function commit(selection) {
101664             _selection = selection; // Initialize changeset if one does not exist yet.
101665
101666             if (!context.changeset) initChangeset();
101667             loadDerivedChangesetTags();
101668             selection.call(render);
101669           }
101670
101671           function initChangeset() {
101672             // expire stored comment, hashtags, source after cutoff datetime - #3947 #4899
101673             var commentDate = +corePreferences('commentDate') || 0;
101674             var currDate = Date.now();
101675             var cutoff = 2 * 86400 * 1000; // 2 days
101676
101677             if (commentDate > currDate || currDate - commentDate > cutoff) {
101678               corePreferences('comment', null);
101679               corePreferences('hashtags', null);
101680               corePreferences('source', null);
101681             } // load in explicitly-set values, if any
101682
101683
101684             if (context.defaultChangesetComment()) {
101685               corePreferences('comment', context.defaultChangesetComment());
101686               corePreferences('commentDate', Date.now());
101687             }
101688
101689             if (context.defaultChangesetSource()) {
101690               corePreferences('source', context.defaultChangesetSource());
101691               corePreferences('commentDate', Date.now());
101692             }
101693
101694             if (context.defaultChangesetHashtags()) {
101695               corePreferences('hashtags', context.defaultChangesetHashtags());
101696               corePreferences('commentDate', Date.now());
101697             }
101698
101699             var detected = utilDetect();
101700             var tags = {
101701               comment: corePreferences('comment') || '',
101702               created_by: context.cleanTagValue('iD ' + context.version),
101703               host: context.cleanTagValue(detected.host),
101704               locale: context.cleanTagValue(_mainLocalizer.localeCode())
101705             }; // call findHashtags initially - this will remove stored
101706             // hashtags if any hashtags are found in the comment - #4304
101707
101708             findHashtags(tags, true);
101709             var hashtags = corePreferences('hashtags');
101710
101711             if (hashtags) {
101712               tags.hashtags = hashtags;
101713             }
101714
101715             var source = corePreferences('source');
101716
101717             if (source) {
101718               tags.source = source;
101719             }
101720
101721             var photoOverlaysUsed = context.history().photoOverlaysUsed();
101722
101723             if (photoOverlaysUsed.length) {
101724               var sources = (tags.source || '').split(';'); // include this tag for any photo layer
101725
101726               if (sources.indexOf('streetlevel imagery') === -1) {
101727                 sources.push('streetlevel imagery');
101728               } // add the photo overlays used during editing as sources
101729
101730
101731               photoOverlaysUsed.forEach(function (photoOverlay) {
101732                 if (sources.indexOf(photoOverlay) === -1) {
101733                   sources.push(photoOverlay);
101734                 }
101735               });
101736               tags.source = context.cleanTagValue(sources.join(';'));
101737             }
101738
101739             context.changeset = new osmChangeset({
101740               tags: tags
101741             });
101742           } // Calculates read-only metadata tags based on the user's editing session and applies
101743           // them to the changeset.
101744
101745
101746           function loadDerivedChangesetTags() {
101747             var osm = context.connection();
101748             if (!osm) return;
101749             var tags = Object.assign({}, context.changeset.tags); // shallow copy
101750             // assign tags for imagery used
101751
101752             var imageryUsed = context.cleanTagValue(context.history().imageryUsed().join(';'));
101753             tags.imagery_used = imageryUsed || 'None'; // assign tags for closed issues and notes
101754
101755             var osmClosed = osm.getClosedIDs();
101756             var itemType;
101757
101758             if (osmClosed.length) {
101759               tags['closed:note'] = context.cleanTagValue(osmClosed.join(';'));
101760             }
101761
101762             if (services.keepRight) {
101763               var krClosed = services.keepRight.getClosedIDs();
101764
101765               if (krClosed.length) {
101766                 tags['closed:keepright'] = context.cleanTagValue(krClosed.join(';'));
101767               }
101768             }
101769
101770             if (services.improveOSM) {
101771               var iOsmClosed = services.improveOSM.getClosedCounts();
101772
101773               for (itemType in iOsmClosed) {
101774                 tags['closed:improveosm:' + itemType] = context.cleanTagValue(iOsmClosed[itemType].toString());
101775               }
101776             }
101777
101778             if (services.osmose) {
101779               var osmoseClosed = services.osmose.getClosedCounts();
101780
101781               for (itemType in osmoseClosed) {
101782                 tags['closed:osmose:' + itemType] = context.cleanTagValue(osmoseClosed[itemType].toString());
101783               }
101784             } // remove existing issue counts
101785
101786
101787             for (var key in tags) {
101788               if (key.match(/(^warnings:)|(^resolved:)/)) {
101789                 delete tags[key];
101790               }
101791             }
101792
101793             function addIssueCounts(issues, prefix) {
101794               var issuesByType = utilArrayGroupBy(issues, 'type');
101795
101796               for (var issueType in issuesByType) {
101797                 var issuesOfType = issuesByType[issueType];
101798
101799                 if (issuesOfType[0].subtype) {
101800                   var issuesBySubtype = utilArrayGroupBy(issuesOfType, 'subtype');
101801
101802                   for (var issueSubtype in issuesBySubtype) {
101803                     var issuesOfSubtype = issuesBySubtype[issueSubtype];
101804                     tags[prefix + ':' + issueType + ':' + issueSubtype] = context.cleanTagValue(issuesOfSubtype.length.toString());
101805                   }
101806                 } else {
101807                   tags[prefix + ':' + issueType] = context.cleanTagValue(issuesOfType.length.toString());
101808                 }
101809               }
101810             } // add counts of warnings generated by the user's edits
101811
101812
101813             var warnings = context.validator().getIssuesBySeverity({
101814               what: 'edited',
101815               where: 'all',
101816               includeIgnored: true,
101817               includeDisabledRules: true
101818             }).warning.filter(function (issue) {
101819               return issue.type !== 'help_request';
101820             }); // exclude 'fixme' and similar - #8603
101821
101822             addIssueCounts(warnings, 'warnings'); // add counts of issues resolved by the user's edits
101823
101824             var resolvedIssues = context.validator().getResolvedIssues();
101825             addIssueCounts(resolvedIssues, 'resolved');
101826             context.changeset = context.changeset.update({
101827               tags: tags
101828             });
101829           }
101830
101831           function render(selection) {
101832             var osm = context.connection();
101833             if (!osm) return;
101834             var header = selection.selectAll('.header').data([0]);
101835             var headerTitle = header.enter().append('div').attr('class', 'header fillL');
101836             headerTitle.append('div').append('h2').call(_t.append('commit.title'));
101837             headerTitle.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
101838               dispatch.call('cancel', this);
101839             }).call(svgIcon('#iD-icon-close'));
101840             var body = selection.selectAll('.body').data([0]);
101841             body = body.enter().append('div').attr('class', 'body').merge(body); // Changeset Section
101842
101843             var changesetSection = body.selectAll('.changeset-editor').data([0]);
101844             changesetSection = changesetSection.enter().append('div').attr('class', 'modal-section changeset-editor').merge(changesetSection);
101845             changesetSection.call(changesetEditor.changesetID(context.changeset.id).tags(context.changeset.tags)); // Warnings
101846
101847             body.call(commitWarnings); // Upload Explanation
101848
101849             var saveSection = body.selectAll('.save-section').data([0]);
101850             saveSection = saveSection.enter().append('div').attr('class', 'modal-section save-section fillL').merge(saveSection);
101851             var prose = saveSection.selectAll('.commit-info').data([0]);
101852
101853             if (prose.enter().size()) {
101854               // first time, make sure to update user details in prose
101855               _userDetails = null;
101856             }
101857
101858             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()
101859             // if needed, because it can trigger a style recalculation
101860
101861             osm.userDetails(function (err, user) {
101862               if (err) return;
101863               if (_userDetails === user) return; // no change
101864
101865               _userDetails = user;
101866               var userLink = select(document.createElement('div'));
101867
101868               if (user.image_url) {
101869                 userLink.append('img').attr('src', user.image_url).attr('class', 'icon pre-text user-icon');
101870               }
101871
101872               userLink.append('a').attr('class', 'user-info').text(user.display_name).attr('href', osm.userURL(user.display_name)).attr('target', '_blank');
101873               prose.html(_t.html('commit.upload_explanation_with_user', {
101874                 user: {
101875                   html: userLink.html()
101876                 }
101877               }));
101878             }); // Request Review
101879
101880             var requestReview = saveSection.selectAll('.request-review').data([0]); // Enter
101881
101882             var requestReviewEnter = requestReview.enter().append('div').attr('class', 'request-review');
101883             var requestReviewDomId = utilUniqueDomId('commit-input-request-review');
101884             var labelEnter = requestReviewEnter.append('label').attr('for', requestReviewDomId);
101885
101886             if (!labelEnter.empty()) {
101887               labelEnter.call(uiTooltip().title(_t.html('commit.request_review_info')).placement('top'));
101888             }
101889
101890             labelEnter.append('input').attr('type', 'checkbox').attr('id', requestReviewDomId);
101891             labelEnter.append('span').call(_t.append('commit.request_review')); // Update
101892
101893             requestReview = requestReview.merge(requestReviewEnter);
101894             var requestReviewInput = requestReview.selectAll('input').property('checked', isReviewRequested(context.changeset.tags)).on('change', toggleRequestReview); // Buttons
101895
101896             var buttonSection = saveSection.selectAll('.buttons').data([0]); // enter
101897
101898             var buttonEnter = buttonSection.enter().append('div').attr('class', 'buttons fillL');
101899             buttonEnter.append('button').attr('class', 'secondary-action button cancel-button').append('span').attr('class', 'label').call(_t.append('commit.cancel'));
101900             var uploadButton = buttonEnter.append('button').attr('class', 'action button save-button');
101901             uploadButton.append('span').attr('class', 'label').call(_t.append('commit.save'));
101902             var uploadBlockerTooltipText = getUploadBlockerMessage(); // update
101903
101904             buttonSection = buttonSection.merge(buttonEnter);
101905             buttonSection.selectAll('.cancel-button').on('click.cancel', function () {
101906               dispatch.call('cancel', this);
101907             });
101908             buttonSection.selectAll('.save-button').classed('disabled', uploadBlockerTooltipText !== null).on('click.save', function () {
101909               if (!select(this).classed('disabled')) {
101910                 this.blur(); // avoid keeping focus on the button - #4641
101911
101912                 for (var key in context.changeset.tags) {
101913                   // remove any empty keys before upload
101914                   if (!key) delete context.changeset.tags[key];
101915                 }
101916
101917                 context.uploader().save(context.changeset);
101918               }
101919             }); // remove any existing tooltip
101920
101921             uiTooltip().destroyAny(buttonSection.selectAll('.save-button'));
101922
101923             if (uploadBlockerTooltipText) {
101924               buttonSection.selectAll('.save-button').call(uiTooltip().title(uploadBlockerTooltipText).placement('top'));
101925             } // Raw Tag Editor
101926
101927
101928             var tagSection = body.selectAll('.tag-section.raw-tag-editor').data([0]);
101929             tagSection = tagSection.enter().append('div').attr('class', 'modal-section tag-section raw-tag-editor').merge(tagSection);
101930             tagSection.call(rawTagEditor.tags(Object.assign({}, context.changeset.tags)) // shallow copy
101931             .render);
101932             var changesSection = body.selectAll('.commit-changes-section').data([0]);
101933             changesSection = changesSection.enter().append('div').attr('class', 'modal-section commit-changes-section').merge(changesSection); // Change summary
101934
101935             changesSection.call(commitChanges.render);
101936
101937             function toggleRequestReview() {
101938               var rr = requestReviewInput.property('checked');
101939               updateChangeset({
101940                 review_requested: rr ? 'yes' : undefined
101941               });
101942               tagSection.call(rawTagEditor.tags(Object.assign({}, context.changeset.tags)) // shallow copy
101943               .render);
101944             }
101945           }
101946
101947           function getUploadBlockerMessage() {
101948             var errors = context.validator().getIssuesBySeverity({
101949               what: 'edited',
101950               where: 'all'
101951             }).error;
101952
101953             if (errors.length) {
101954               return _t('commit.outstanding_errors_message', {
101955                 count: errors.length
101956               });
101957             } else {
101958               var hasChangesetComment = context.changeset && context.changeset.tags.comment && context.changeset.tags.comment.trim().length;
101959
101960               if (!hasChangesetComment) {
101961                 return _t('commit.comment_needed_message');
101962               }
101963             }
101964
101965             return null;
101966           }
101967
101968           function changeTags(_, changed, onInput) {
101969             if (changed.hasOwnProperty('comment')) {
101970               if (changed.comment === undefined) {
101971                 changed.comment = '';
101972               }
101973
101974               if (!onInput) {
101975                 corePreferences('comment', changed.comment);
101976                 corePreferences('commentDate', Date.now());
101977               }
101978             }
101979
101980             if (changed.hasOwnProperty('source')) {
101981               if (changed.source === undefined) {
101982                 corePreferences('source', null);
101983               } else if (!onInput) {
101984                 corePreferences('source', changed.source);
101985                 corePreferences('commentDate', Date.now());
101986               }
101987             } // no need to update `prefs` for `hashtags` here since it's done in `updateChangeset`
101988
101989
101990             updateChangeset(changed, onInput);
101991
101992             if (_selection) {
101993               _selection.call(render);
101994             }
101995           }
101996
101997           function findHashtags(tags, commentOnly) {
101998             var detectedHashtags = commentHashtags();
101999
102000             if (detectedHashtags.length) {
102001               // always remove stored hashtags if there are hashtags in the comment - #4304
102002               corePreferences('hashtags', null);
102003             }
102004
102005             if (!detectedHashtags.length || !commentOnly) {
102006               detectedHashtags = detectedHashtags.concat(hashtagHashtags());
102007             }
102008
102009             var allLowerCase = new Set();
102010             return detectedHashtags.filter(function (hashtag) {
102011               // Compare tags as lowercase strings, but keep original case tags
102012               var lowerCase = hashtag.toLowerCase();
102013
102014               if (!allLowerCase.has(lowerCase)) {
102015                 allLowerCase.add(lowerCase);
102016                 return true;
102017               }
102018
102019               return false;
102020             }); // Extract hashtags from `comment`
102021
102022             function commentHashtags() {
102023               var matches = (tags.comment || '').replace(/http\S*/g, '') // drop anything that looks like a URL - #4289
102024               .match(hashtagRegex);
102025               return matches || [];
102026             } // Extract and clean hashtags from `hashtags`
102027
102028
102029             function hashtagHashtags() {
102030               var matches = (tags.hashtags || '').split(/[,;\s]+/).map(function (s) {
102031                 if (s[0] !== '#') {
102032                   s = '#' + s;
102033                 } // prepend '#'
102034
102035
102036                 var matched = s.match(hashtagRegex);
102037                 return matched && matched[0];
102038               }).filter(Boolean); // exclude falsy
102039
102040               return matches || [];
102041             }
102042           }
102043
102044           function isReviewRequested(tags) {
102045             var rr = tags.review_requested;
102046             if (rr === undefined) return false;
102047             rr = rr.trim().toLowerCase();
102048             return !(rr === '' || rr === 'no');
102049           }
102050
102051           function updateChangeset(changed, onInput) {
102052             var tags = Object.assign({}, context.changeset.tags); // shallow copy
102053
102054             Object.keys(changed).forEach(function (k) {
102055               var v = changed[k];
102056               k = context.cleanTagKey(k);
102057               if (readOnlyTags.indexOf(k) !== -1) return;
102058
102059               if (v === undefined) {
102060                 delete tags[k];
102061               } else if (onInput) {
102062                 tags[k] = v;
102063               } else {
102064                 tags[k] = context.cleanTagValue(v);
102065               }
102066             });
102067
102068             if (!onInput) {
102069               // when changing the comment, override hashtags with any found in comment.
102070               var commentOnly = changed.hasOwnProperty('comment') && changed.comment !== '';
102071               var arr = findHashtags(tags, commentOnly);
102072
102073               if (arr.length) {
102074                 tags.hashtags = context.cleanTagValue(arr.join(';'));
102075                 corePreferences('hashtags', tags.hashtags);
102076               } else {
102077                 delete tags.hashtags;
102078                 corePreferences('hashtags', null);
102079               }
102080             } // always update userdetails, just in case user reauthenticates as someone else
102081
102082
102083             if (_userDetails && _userDetails.changesets_count !== undefined) {
102084               var changesetsCount = parseInt(_userDetails.changesets_count, 10) + 1; // #4283
102085
102086               tags.changesets_count = String(changesetsCount); // first 100 edits - new user
102087
102088               if (changesetsCount <= 100) {
102089                 var s;
102090                 s = corePreferences('walkthrough_completed');
102091
102092                 if (s) {
102093                   tags['ideditor:walkthrough_completed'] = s;
102094                 }
102095
102096                 s = corePreferences('walkthrough_progress');
102097
102098                 if (s) {
102099                   tags['ideditor:walkthrough_progress'] = s;
102100                 }
102101
102102                 s = corePreferences('walkthrough_started');
102103
102104                 if (s) {
102105                   tags['ideditor:walkthrough_started'] = s;
102106                 }
102107               }
102108             } else {
102109               delete tags.changesets_count;
102110             }
102111
102112             if (!fastDeepEqual(context.changeset.tags, tags)) {
102113               context.changeset = context.changeset.update({
102114                 tags: tags
102115               });
102116             }
102117           }
102118
102119           commit.reset = function () {
102120             context.changeset = null;
102121           };
102122
102123           return utilRebind(commit, dispatch, 'on');
102124         }
102125
102126         function uiConfirm(selection) {
102127           var modalSelection = uiModal(selection);
102128           modalSelection.select('.modal').classed('modal-alert', true);
102129           var section = modalSelection.select('.content');
102130           section.append('div').attr('class', 'modal-section header');
102131           section.append('div').attr('class', 'modal-section message-text');
102132           var buttons = section.append('div').attr('class', 'modal-section buttons cf');
102133
102134           modalSelection.okButton = function () {
102135             buttons.append('button').attr('class', 'button ok-button action').on('click.confirm', function () {
102136               modalSelection.remove();
102137             }).call(_t.append('confirm.okay')).node().focus();
102138             return modalSelection;
102139           };
102140
102141           return modalSelection;
102142         }
102143
102144         function uiConflicts(context) {
102145           var dispatch = dispatch$8('cancel', 'save');
102146           var keybinding = utilKeybinding('conflicts');
102147
102148           var _origChanges;
102149
102150           var _conflictList;
102151
102152           var _shownConflictIndex;
102153
102154           function keybindingOn() {
102155             select(document).call(keybinding.on('⎋', cancel, true));
102156           }
102157
102158           function keybindingOff() {
102159             select(document).call(keybinding.unbind);
102160           }
102161
102162           function tryAgain() {
102163             keybindingOff();
102164             dispatch.call('save');
102165           }
102166
102167           function cancel() {
102168             keybindingOff();
102169             dispatch.call('cancel');
102170           }
102171
102172           function conflicts(selection) {
102173             keybindingOn();
102174             var headerEnter = selection.selectAll('.header').data([0]).enter().append('div').attr('class', 'header fillL');
102175             headerEnter.append('button').attr('class', 'fr').attr('title', _t('icons.close')).on('click', cancel).call(svgIcon('#iD-icon-close'));
102176             headerEnter.append('h2').call(_t.append('save.conflict.header'));
102177             var bodyEnter = selection.selectAll('.body').data([0]).enter().append('div').attr('class', 'body fillL');
102178             var conflictsHelpEnter = bodyEnter.append('div').attr('class', 'conflicts-help').call(_t.append('save.conflict.help')); // Download changes link
102179
102180             var detected = utilDetect();
102181             var changeset = new osmChangeset();
102182             delete changeset.id; // Export without changeset_id
102183
102184             var data = JXON.stringify(changeset.osmChangeJXON(_origChanges));
102185             var blob = new Blob([data], {
102186               type: 'text/xml;charset=utf-8;'
102187             });
102188             var fileName = 'changes.osc';
102189             var linkEnter = conflictsHelpEnter.selectAll('.download-changes').append('a').attr('class', 'download-changes');
102190
102191             if (detected.download) {
102192               // All except IE11 and Edge
102193               linkEnter // download the data as a file
102194               .attr('href', window.URL.createObjectURL(blob)).attr('download', fileName);
102195             } else {
102196               // IE11 and Edge
102197               linkEnter // open data uri in a new tab
102198               .attr('target', '_blank').on('click.download', function () {
102199                 navigator.msSaveBlob(blob, fileName);
102200               });
102201             }
102202
102203             linkEnter.call(svgIcon('#iD-icon-load', 'inline')).append('span').call(_t.append('save.conflict.download_changes'));
102204             bodyEnter.append('div').attr('class', 'conflict-container fillL3').call(showConflict, 0);
102205             bodyEnter.append('div').attr('class', 'conflicts-done').attr('opacity', 0).style('display', 'none').call(_t.append('save.conflict.done'));
102206             var buttonsEnter = bodyEnter.append('div').attr('class', 'buttons col12 joined conflicts-buttons');
102207             buttonsEnter.append('button').attr('disabled', _conflictList.length > 1).attr('class', 'action conflicts-button col6').call(_t.append('save.title')).on('click.try_again', tryAgain);
102208             buttonsEnter.append('button').attr('class', 'secondary-action conflicts-button col6').call(_t.append('confirm.cancel')).on('click.cancel', cancel);
102209           }
102210
102211           function showConflict(selection, index) {
102212             index = utilWrap(index, _conflictList.length);
102213             _shownConflictIndex = index;
102214             var parent = select(selection.node().parentNode); // enable save button if this is the last conflict being reviewed..
102215
102216             if (index === _conflictList.length - 1) {
102217               window.setTimeout(function () {
102218                 parent.select('.conflicts-button').attr('disabled', null);
102219                 parent.select('.conflicts-done').transition().attr('opacity', 1).style('display', 'block');
102220               }, 250);
102221             }
102222
102223             var conflict = selection.selectAll('.conflict').data([_conflictList[index]]);
102224             conflict.exit().remove();
102225             var conflictEnter = conflict.enter().append('div').attr('class', 'conflict');
102226             conflictEnter.append('h4').attr('class', 'conflict-count').call(_t.append('save.conflict.count', {
102227               num: index + 1,
102228               total: _conflictList.length
102229             }));
102230             conflictEnter.append('a').attr('class', 'conflict-description').attr('href', '#').text(function (d) {
102231               return d.name;
102232             }).on('click', function (d3_event, d) {
102233               d3_event.preventDefault();
102234               zoomToEntity(d.id);
102235             });
102236             var details = conflictEnter.append('div').attr('class', 'conflict-detail-container');
102237             details.append('ul').attr('class', 'conflict-detail-list').selectAll('li').data(function (d) {
102238               return d.details || [];
102239             }).enter().append('li').attr('class', 'conflict-detail-item').html(function (d) {
102240               return d;
102241             });
102242             details.append('div').attr('class', 'conflict-choices').call(addChoices);
102243             details.append('div').attr('class', 'conflict-nav-buttons joined cf').selectAll('button').data(['previous', 'next']).enter().append('button').html(function (d) {
102244               return _t.html('save.conflict.' + d);
102245             }).attr('class', 'conflict-nav-button action col6').attr('disabled', function (d, i) {
102246               return i === 0 && index === 0 || i === 1 && index === _conflictList.length - 1 || null;
102247             }).on('click', function (d3_event, d) {
102248               d3_event.preventDefault();
102249               var container = parent.selectAll('.conflict-container');
102250               var sign = d === 'previous' ? -1 : 1;
102251               container.selectAll('.conflict').remove();
102252               container.call(showConflict, index + sign);
102253             });
102254           }
102255
102256           function addChoices(selection) {
102257             var choices = selection.append('ul').attr('class', 'layer-list').selectAll('li').data(function (d) {
102258               return d.choices || [];
102259             }); // enter
102260
102261             var choicesEnter = choices.enter().append('li').attr('class', 'layer');
102262             var labelEnter = choicesEnter.append('label');
102263             labelEnter.append('input').attr('type', 'radio').attr('name', function (d) {
102264               return d.id;
102265             }).on('change', function (d3_event, d) {
102266               var ul = this.parentNode.parentNode.parentNode;
102267               ul.__data__.chosen = d.id;
102268               choose(d3_event, ul, d);
102269             });
102270             labelEnter.append('span').text(function (d) {
102271               return d.text;
102272             }); // update
102273
102274             choicesEnter.merge(choices).each(function (d) {
102275               var ul = this.parentNode;
102276
102277               if (ul.__data__.chosen === d.id) {
102278                 choose(null, ul, d);
102279               }
102280             });
102281           }
102282
102283           function choose(d3_event, ul, datum) {
102284             if (d3_event) d3_event.preventDefault();
102285             select(ul).selectAll('li').classed('active', function (d) {
102286               return d === datum;
102287             }).selectAll('input').property('checked', function (d) {
102288               return d === datum;
102289             });
102290             var extent = geoExtent();
102291             var entity;
102292             entity = context.graph().hasEntity(datum.id);
102293             if (entity) extent._extend(entity.extent(context.graph()));
102294             datum.action();
102295             entity = context.graph().hasEntity(datum.id);
102296             if (entity) extent._extend(entity.extent(context.graph()));
102297             zoomToEntity(datum.id, extent);
102298           }
102299
102300           function zoomToEntity(id, extent) {
102301             context.surface().selectAll('.hover').classed('hover', false);
102302             var entity = context.graph().hasEntity(id);
102303
102304             if (entity) {
102305               if (extent) {
102306                 context.map().trimmedExtent(extent);
102307               } else {
102308                 context.map().zoomToEase(entity);
102309               }
102310
102311               context.surface().selectAll(utilEntityOrMemberSelector([entity.id], context.graph())).classed('hover', true);
102312             }
102313           } // The conflict list should be an array of objects like:
102314           // {
102315           //     id: id,
102316           //     name: entityName(local),
102317           //     details: merge.conflicts(),
102318           //     chosen: 1,
102319           //     choices: [
102320           //         choice(id, keepMine, forceLocal),
102321           //         choice(id, keepTheirs, forceRemote)
102322           //     ]
102323           // }
102324
102325
102326           conflicts.conflictList = function (_) {
102327             if (!arguments.length) return _conflictList;
102328             _conflictList = _;
102329             return conflicts;
102330           };
102331
102332           conflicts.origChanges = function (_) {
102333             if (!arguments.length) return _origChanges;
102334             _origChanges = _;
102335             return conflicts;
102336           };
102337
102338           conflicts.shownEntityIds = function () {
102339             if (_conflictList && typeof _shownConflictIndex === 'number') {
102340               return [_conflictList[_shownConflictIndex].id];
102341             }
102342
102343             return [];
102344           };
102345
102346           return utilRebind(conflicts, dispatch, 'on');
102347         }
102348
102349         function uiSectionEntityIssues(context) {
102350           // Does the user prefer to expand the active issue?  Useful for viewing tag diff.
102351           // Expand by default so first timers see it - #6408, #8143
102352           var preference = corePreferences('entity-issues.reference.expanded');
102353
102354           var _expanded = preference === null ? true : preference === 'true';
102355
102356           var _entityIDs = [];
102357           var _issues = [];
102358
102359           var _activeIssueID;
102360
102361           var section = uiSection('entity-issues', context).shouldDisplay(function () {
102362             return _issues.length > 0;
102363           }).label(function () {
102364             return _t.html('inspector.title_count', {
102365               title: {
102366                 html: _t.html('issues.list_title')
102367               },
102368               count: _issues.length
102369             });
102370           }).disclosureContent(renderDisclosureContent);
102371           context.validator().on('validated.entity_issues', function () {
102372             // Refresh on validated events
102373             reloadIssues();
102374             section.reRender();
102375           }).on('focusedIssue.entity_issues', function (issue) {
102376             makeActiveIssue(issue.id);
102377           });
102378
102379           function reloadIssues() {
102380             _issues = context.validator().getSharedEntityIssues(_entityIDs, {
102381               includeDisabledRules: true
102382             });
102383           }
102384
102385           function makeActiveIssue(issueID) {
102386             _activeIssueID = issueID;
102387             section.selection().selectAll('.issue-container').classed('active', function (d) {
102388               return d.id === _activeIssueID;
102389             });
102390           }
102391
102392           function renderDisclosureContent(selection) {
102393             selection.classed('grouped-items-area', true);
102394             _activeIssueID = _issues.length > 0 ? _issues[0].id : null;
102395             var containers = selection.selectAll('.issue-container').data(_issues, function (d) {
102396               return d.key;
102397             }); // Exit
102398
102399             containers.exit().remove(); // Enter
102400
102401             var containersEnter = containers.enter().append('div').attr('class', 'issue-container');
102402             var itemsEnter = containersEnter.append('div').attr('class', function (d) {
102403               return 'issue severity-' + d.severity;
102404             }).on('mouseover.highlight', function (d3_event, d) {
102405               // don't hover-highlight the selected entity
102406               var ids = d.entityIds.filter(function (e) {
102407                 return _entityIDs.indexOf(e) === -1;
102408               });
102409               utilHighlightEntities(ids, true, context);
102410             }).on('mouseout.highlight', function (d3_event, d) {
102411               var ids = d.entityIds.filter(function (e) {
102412                 return _entityIDs.indexOf(e) === -1;
102413               });
102414               utilHighlightEntities(ids, false, context);
102415             });
102416             var labelsEnter = itemsEnter.append('div').attr('class', 'issue-label');
102417             var textEnter = labelsEnter.append('button').attr('class', 'issue-text').on('click', function (d3_event, d) {
102418               makeActiveIssue(d.id); // expand only the clicked item
102419
102420               var extent = d.extent(context.graph());
102421
102422               if (extent) {
102423                 var setZoom = Math.max(context.map().zoom(), 19);
102424                 context.map().unobscuredCenterZoomEase(extent.center(), setZoom);
102425               }
102426             });
102427             textEnter.each(function (d) {
102428               var iconName = '#iD-icon-' + (d.severity === 'warning' ? 'alert' : 'error');
102429               select(this).call(svgIcon(iconName, 'issue-icon'));
102430             });
102431             textEnter.append('span').attr('class', 'issue-message');
102432             var infoButton = labelsEnter.append('button').attr('class', 'issue-info-button').attr('title', _t('icons.information')).call(svgIcon('#iD-icon-inspect'));
102433             infoButton.on('click', function (d3_event) {
102434               d3_event.stopPropagation();
102435               d3_event.preventDefault();
102436               this.blur(); // avoid keeping focus on the button - #4641
102437
102438               var container = select(this.parentNode.parentNode.parentNode);
102439               var info = container.selectAll('.issue-info');
102440               var isExpanded = info.classed('expanded');
102441               _expanded = !isExpanded;
102442               corePreferences('entity-issues.reference.expanded', _expanded); // update preference
102443
102444               if (isExpanded) {
102445                 info.transition().duration(200).style('max-height', '0px').style('opacity', '0').on('end', function () {
102446                   info.classed('expanded', false);
102447                 });
102448               } else {
102449                 info.classed('expanded', true).transition().duration(200).style('max-height', '200px').style('opacity', '1').on('end', function () {
102450                   info.style('max-height', null);
102451                 });
102452               }
102453             });
102454             itemsEnter.append('ul').attr('class', 'issue-fix-list');
102455             containersEnter.append('div').attr('class', 'issue-info' + (_expanded ? ' expanded' : '')).style('max-height', _expanded ? null : '0').style('opacity', _expanded ? '1' : '0').each(function (d) {
102456               if (typeof d.reference === 'function') {
102457                 select(this).call(d.reference);
102458               } else {
102459                 select(this).call(_t.append('inspector.no_documentation_key'));
102460               }
102461             }); // Update
102462
102463             containers = containers.merge(containersEnter).classed('active', function (d) {
102464               return d.id === _activeIssueID;
102465             });
102466             containers.selectAll('.issue-message').html(function (d) {
102467               return d.message(context);
102468             }); // fixes
102469
102470             var fixLists = containers.selectAll('.issue-fix-list');
102471             var fixes = fixLists.selectAll('.issue-fix-item').data(function (d) {
102472               return d.fixes ? d.fixes(context) : [];
102473             }, function (fix) {
102474               return fix.id;
102475             });
102476             fixes.exit().remove();
102477             var fixesEnter = fixes.enter().append('li').attr('class', 'issue-fix-item');
102478             var buttons = fixesEnter.append('button').on('click', function (d3_event, d) {
102479               // not all fixes are actionable
102480               if (select(this).attr('disabled') || !d.onClick) return; // Don't run another fix for this issue within a second of running one
102481               // (Necessary for "Select a feature type" fix. Most fixes should only ever run once)
102482
102483               if (d.issue.dateLastRanFix && new Date() - d.issue.dateLastRanFix < 1000) return;
102484               d.issue.dateLastRanFix = new Date(); // remove hover-highlighting
102485
102486               utilHighlightEntities(d.issue.entityIds.concat(d.entityIds), false, context);
102487               new Promise(function (resolve, reject) {
102488                 d.onClick(context, resolve, reject);
102489
102490                 if (d.onClick.length <= 1) {
102491                   // if the fix doesn't take any completion parameters then consider it resolved
102492                   resolve();
102493                 }
102494               }).then(function () {
102495                 // revalidate whenever the fix has finished running successfully
102496                 context.validator().validate();
102497               });
102498             }).on('mouseover.highlight', function (d3_event, d) {
102499               utilHighlightEntities(d.entityIds, true, context);
102500             }).on('mouseout.highlight', function (d3_event, d) {
102501               utilHighlightEntities(d.entityIds, false, context);
102502             });
102503             buttons.each(function (d) {
102504               var iconName = d.icon || 'iD-icon-wrench';
102505
102506               if (iconName.startsWith('maki')) {
102507                 iconName += '-15';
102508               }
102509
102510               select(this).call(svgIcon('#' + iconName, 'fix-icon'));
102511             });
102512             buttons.append('span').attr('class', 'fix-message').html(function (d) {
102513               return d.title;
102514             });
102515             fixesEnter.merge(fixes).selectAll('button').classed('actionable', function (d) {
102516               return d.onClick;
102517             }).attr('disabled', function (d) {
102518               return d.onClick ? null : 'true';
102519             }).attr('title', function (d) {
102520               if (d.disabledReason) {
102521                 return d.disabledReason;
102522               }
102523
102524               return null;
102525             });
102526           }
102527
102528           section.entityIDs = function (val) {
102529             if (!arguments.length) return _entityIDs;
102530
102531             if (!_entityIDs || !val || !utilArrayIdentical(_entityIDs, val)) {
102532               _entityIDs = val;
102533               _activeIssueID = null;
102534               reloadIssues();
102535             }
102536
102537             return section;
102538           };
102539
102540           return section;
102541         }
102542
102543         function uiPresetIcon() {
102544           var _preset;
102545
102546           var _geometry;
102547
102548           var _sizeClass = 'medium';
102549
102550           function isSmall() {
102551             return _sizeClass === 'small';
102552           }
102553
102554           function presetIcon(selection) {
102555             selection.each(render);
102556           }
102557
102558           function getIcon(p, geom) {
102559             if (isSmall() && p.isFallback && p.isFallback()) return 'iD-icon-' + p.id;
102560             if (p.icon) return p.icon;
102561             if (geom === 'line') return 'iD-other-line';
102562             if (geom === 'vertex') return p.isFallback() ? '' : 'temaki-vertex';
102563             if (isSmall() && geom === 'point') return '';
102564             return 'maki-marker-stroked';
102565           }
102566
102567           function renderPointBorder(container, drawPoint) {
102568             var pointBorder = container.selectAll('.preset-icon-point-border').data(drawPoint ? [0] : []);
102569             pointBorder.exit().remove();
102570             var pointBorderEnter = pointBorder.enter();
102571             var w = 40;
102572             var h = 40;
102573             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');
102574             pointBorder = pointBorderEnter.merge(pointBorder);
102575           }
102576
102577           function renderCategoryBorder(container, category) {
102578             var categoryBorder = container.selectAll('.preset-icon-category-border').data(category ? [0] : []);
102579             categoryBorder.exit().remove();
102580             var categoryBorderEnter = categoryBorder.enter();
102581             var d = 60;
102582             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));
102583             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');
102584             categoryBorder = categoryBorderEnter.merge(categoryBorder);
102585
102586             if (category) {
102587               categoryBorder.selectAll('path').attr('class', "area ".concat(category.id));
102588             }
102589           }
102590
102591           function renderCircleFill(container, drawVertex) {
102592             var vertexFill = container.selectAll('.preset-icon-fill-vertex').data(drawVertex ? [0] : []);
102593             vertexFill.exit().remove();
102594             var vertexFillEnter = vertexFill.enter();
102595             var w = 60;
102596             var h = 60;
102597             var d = 40;
102598             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);
102599             vertexFill = vertexFillEnter.merge(vertexFill);
102600           }
102601
102602           function renderSquareFill(container, drawArea, tagClasses) {
102603             var fill = container.selectAll('.preset-icon-fill-area').data(drawArea ? [0] : []);
102604             fill.exit().remove();
102605             var fillEnter = fill.enter();
102606             var d = isSmall() ? 40 : 60;
102607             var w = d;
102608             var h = d;
102609             var l = d * 2 / 3;
102610             var c1 = (w - l) / 2;
102611             var c2 = c1 + l;
102612             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));
102613             ['fill', 'stroke'].forEach(function (klass) {
102614               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));
102615             });
102616             var rVertex = 2.5;
102617             [[c1, c1], [c1, c2], [c2, c2], [c2, c1]].forEach(function (point) {
102618               fillEnter.append('circle').attr('class', 'vertex').attr('cx', point[0]).attr('cy', point[1]).attr('r', rVertex);
102619             });
102620
102621             if (!isSmall()) {
102622               var rMidpoint = 1.25;
102623               [[c1, w / 2], [c2, w / 2], [h / 2, c1], [h / 2, c2]].forEach(function (point) {
102624                 fillEnter.append('circle').attr('class', 'midpoint').attr('cx', point[0]).attr('cy', point[1]).attr('r', rMidpoint);
102625               });
102626             }
102627
102628             fill = fillEnter.merge(fill);
102629             fill.selectAll('path.stroke').attr('class', "area stroke ".concat(tagClasses));
102630             fill.selectAll('path.fill').attr('class', "area fill ".concat(tagClasses));
102631           }
102632
102633           function renderLine(container, drawLine, tagClasses) {
102634             var line = container.selectAll('.preset-icon-line').data(drawLine ? [0] : []);
102635             line.exit().remove();
102636             var lineEnter = line.enter();
102637             var d = isSmall() ? 40 : 60; // draw the line parametrically
102638
102639             var w = d;
102640             var h = d;
102641             var y = Math.round(d * 0.72);
102642             var l = Math.round(d * 0.6);
102643             var r = 2.5;
102644             var x1 = (w - l) / 2;
102645             var x2 = x1 + l;
102646             lineEnter = lineEnter.append('svg').attr('class', 'preset-icon-line').attr('width', w).attr('height', h).attr('viewBox', "0 0 ".concat(w, " ").concat(h));
102647             ['casing', 'stroke'].forEach(function (klass) {
102648               lineEnter.append('path').attr('d', "M".concat(x1, " ").concat(y, " L").concat(x2, " ").concat(y)).attr('class', "line ".concat(klass));
102649             });
102650             [[x1 - 1, y], [x2 + 1, y]].forEach(function (point) {
102651               lineEnter.append('circle').attr('class', 'vertex').attr('cx', point[0]).attr('cy', point[1]).attr('r', r);
102652             });
102653             line = lineEnter.merge(line);
102654             line.selectAll('path.stroke').attr('class', "line stroke ".concat(tagClasses));
102655             line.selectAll('path.casing').attr('class', "line casing ".concat(tagClasses));
102656           }
102657
102658           function renderRoute(container, drawRoute, p) {
102659             var route = container.selectAll('.preset-icon-route').data(drawRoute ? [0] : []);
102660             route.exit().remove();
102661             var routeEnter = route.enter();
102662             var d = isSmall() ? 40 : 60; // draw the route parametrically
102663
102664             var w = d;
102665             var h = d;
102666             var y1 = Math.round(d * 0.80);
102667             var y2 = Math.round(d * 0.68);
102668             var l = Math.round(d * 0.6);
102669             var r = 2;
102670             var x1 = (w - l) / 2;
102671             var x2 = x1 + l / 3;
102672             var x3 = x2 + l / 3;
102673             var x4 = x3 + l / 3;
102674             routeEnter = routeEnter.append('svg').attr('class', 'preset-icon-route').attr('width', w).attr('height', h).attr('viewBox', "0 0 ".concat(w, " ").concat(h));
102675             ['casing', 'stroke'].forEach(function (klass) {
102676               routeEnter.append('path').attr('d', "M".concat(x1, " ").concat(y1, " L").concat(x2, " ").concat(y2)).attr('class', "segment0 line ".concat(klass));
102677               routeEnter.append('path').attr('d', "M".concat(x2, " ").concat(y2, " L").concat(x3, " ").concat(y1)).attr('class', "segment1 line ".concat(klass));
102678               routeEnter.append('path').attr('d', "M".concat(x3, " ").concat(y1, " L").concat(x4, " ").concat(y2)).attr('class', "segment2 line ".concat(klass));
102679             });
102680             [[x1, y1], [x2, y2], [x3, y1], [x4, y2]].forEach(function (point) {
102681               routeEnter.append('circle').attr('class', 'vertex').attr('cx', point[0]).attr('cy', point[1]).attr('r', r);
102682             });
102683             route = routeEnter.merge(route);
102684
102685             if (drawRoute) {
102686               var routeType = p.tags.type === 'waterway' ? 'waterway' : p.tags.route;
102687               var segmentPresetIDs = routeSegments[routeType];
102688
102689               for (var i in segmentPresetIDs) {
102690                 var segmentPreset = _mainPresetIndex.item(segmentPresetIDs[i]);
102691                 var segmentTagClasses = svgTagClasses().getClassesString(segmentPreset.tags, '');
102692                 route.selectAll("path.stroke.segment".concat(i)).attr('class', "segment".concat(i, " line stroke ").concat(segmentTagClasses));
102693                 route.selectAll("path.casing.segment".concat(i)).attr('class', "segment".concat(i, " line casing ").concat(segmentTagClasses));
102694               }
102695             }
102696           }
102697
102698           function renderSvgIcon(container, picon, geom, isFramed, category, tagClasses) {
102699             var isMaki = picon && /^maki-/.test(picon);
102700             var isTemaki = picon && /^temaki-/.test(picon);
102701             var isFa = picon && /^fa[srb]-/.test(picon);
102702             var isiDIcon = picon && !(isMaki || isTemaki || isFa);
102703             var icon = container.selectAll('.preset-icon').data(picon ? [0] : []);
102704             icon.exit().remove();
102705             icon = icon.enter().append('div').attr('class', 'preset-icon').call(svgIcon('')).merge(icon);
102706             icon.attr('class', 'preset-icon ' + (geom ? geom + '-geom' : '')).classed('category', category).classed('framed', isFramed).classed('preset-icon-iD', isiDIcon);
102707             icon.selectAll('svg').attr('class', 'icon ' + picon + ' ' + (!isiDIcon && geom !== 'line' ? '' : tagClasses));
102708             var suffix = '';
102709
102710             if (isMaki) {
102711               suffix = isSmall() && geom === 'point' ? '-11' : '-15';
102712             }
102713
102714             icon.selectAll('use').attr('href', '#' + picon + suffix);
102715           }
102716
102717           function renderImageIcon(container, imageURL) {
102718             var imageIcon = container.selectAll('img.image-icon').data(imageURL ? [0] : []);
102719             imageIcon.exit().remove();
102720             imageIcon = imageIcon.enter().append('img').attr('class', 'image-icon').on('load', function () {
102721               return container.classed('showing-img', true);
102722             }).on('error', function () {
102723               return container.classed('showing-img', false);
102724             }).merge(imageIcon);
102725             imageIcon.attr('src', imageURL);
102726           } // Route icons are drawn with a zigzag annotation underneath:
102727           //     o   o
102728           //    / \ /
102729           //   o   o
102730           // This dataset defines the styles that are used to draw the zigzag segments.
102731
102732
102733           var routeSegments = {
102734             bicycle: ['highway/cycleway', 'highway/cycleway', 'highway/cycleway'],
102735             bus: ['highway/unclassified', 'highway/secondary', 'highway/primary'],
102736             trolleybus: ['highway/unclassified', 'highway/secondary', 'highway/primary'],
102737             detour: ['highway/tertiary', 'highway/residential', 'highway/unclassified'],
102738             ferry: ['route/ferry', 'route/ferry', 'route/ferry'],
102739             foot: ['highway/footway', 'highway/footway', 'highway/footway'],
102740             hiking: ['highway/path', 'highway/path', 'highway/path'],
102741             horse: ['highway/bridleway', 'highway/bridleway', 'highway/bridleway'],
102742             light_rail: ['railway/light_rail', 'railway/light_rail', 'railway/light_rail'],
102743             monorail: ['railway/monorail', 'railway/monorail', 'railway/monorail'],
102744             mtb: ['highway/path', 'highway/track', 'highway/bridleway'],
102745             pipeline: ['man_made/pipeline', 'man_made/pipeline', 'man_made/pipeline'],
102746             piste: ['piste/downhill', 'piste/hike', 'piste/nordic'],
102747             power: ['power/line', 'power/line', 'power/line'],
102748             road: ['highway/secondary', 'highway/primary', 'highway/trunk'],
102749             subway: ['railway/subway', 'railway/subway', 'railway/subway'],
102750             train: ['railway/rail', 'railway/rail', 'railway/rail'],
102751             tram: ['railway/tram', 'railway/tram', 'railway/tram'],
102752             waterway: ['waterway/stream', 'waterway/stream', 'waterway/stream']
102753           };
102754
102755           function render() {
102756             var p = _preset.apply(this, arguments);
102757
102758             var geom = _geometry ? _geometry.apply(this, arguments) : null;
102759
102760             if (geom === 'relation' && p.tags && (p.tags.type === 'route' && p.tags.route && routeSegments[p.tags.route] || p.tags.type === 'waterway')) {
102761               geom = 'route';
102762             }
102763
102764             var showThirdPartyIcons = corePreferences('preferences.privacy.thirdpartyicons') || 'true';
102765             var isFallback = isSmall() && p.isFallback && p.isFallback();
102766             var imageURL = showThirdPartyIcons === 'true' && p.imageURL;
102767             var picon = getIcon(p, geom);
102768             var isCategory = !p.setTags;
102769             var drawPoint = picon && geom === 'point' && isSmall() && !isFallback;
102770             var drawVertex = picon !== null && geom === 'vertex' && (!isSmall() || !isFallback);
102771             var drawLine = picon && geom === 'line' && !isFallback && !isCategory;
102772             var drawArea = picon && geom === 'area' && !isFallback && !isCategory;
102773             var drawRoute = picon && geom === 'route';
102774             var isFramed = drawVertex || drawArea || drawLine || drawRoute || isCategory;
102775             var tags = !isCategory ? p.setTags({}, geom) : {};
102776
102777             for (var k in tags) {
102778               if (tags[k] === '*') {
102779                 tags[k] = 'yes';
102780               }
102781             }
102782
102783             var tagClasses = svgTagClasses().getClassesString(tags, '');
102784             var selection = select(this);
102785             var container = selection.selectAll('.preset-icon-container').data([0]);
102786             container = container.enter().append('div').attr('class', "preset-icon-container ".concat(_sizeClass)).merge(container);
102787             container.classed('showing-img', !!imageURL).classed('fallback', isFallback);
102788             renderCategoryBorder(container, isCategory && p);
102789             renderPointBorder(container, drawPoint);
102790             renderCircleFill(container, drawVertex);
102791             renderSquareFill(container, drawArea, tagClasses);
102792             renderLine(container, drawLine, tagClasses);
102793             renderRoute(container, drawRoute, p);
102794             renderSvgIcon(container, picon, geom, isFramed, isCategory, tagClasses);
102795             renderImageIcon(container, imageURL);
102796           }
102797
102798           presetIcon.preset = function (val) {
102799             if (!arguments.length) return _preset;
102800             _preset = utilFunctor(val);
102801             return presetIcon;
102802           };
102803
102804           presetIcon.geometry = function (val) {
102805             if (!arguments.length) return _geometry;
102806             _geometry = utilFunctor(val);
102807             return presetIcon;
102808           };
102809
102810           presetIcon.sizeClass = function (val) {
102811             if (!arguments.length) return _sizeClass;
102812             _sizeClass = val;
102813             return presetIcon;
102814           };
102815
102816           return presetIcon;
102817         }
102818
102819         function uiSectionFeatureType(context) {
102820           var dispatch = dispatch$8('choose');
102821           var _entityIDs = [];
102822           var _presets = [];
102823
102824           var _tagReference;
102825
102826           var section = uiSection('feature-type', context).label(_t.html('inspector.feature_type')).disclosureContent(renderDisclosureContent);
102827
102828           function renderDisclosureContent(selection) {
102829             selection.classed('preset-list-item', true);
102830             selection.classed('mixed-types', _presets.length > 1);
102831             var presetButtonWrap = selection.selectAll('.preset-list-button-wrap').data([0]).enter().append('div').attr('class', 'preset-list-button-wrap');
102832             var presetButton = presetButtonWrap.append('button').attr('class', 'preset-list-button preset-reset').call(uiTooltip().title(_t.html('inspector.back_tooltip')).placement('bottom'));
102833             presetButton.append('div').attr('class', 'preset-icon-container');
102834             presetButton.append('div').attr('class', 'label').append('div').attr('class', 'label-inner');
102835             presetButtonWrap.append('div').attr('class', 'accessory-buttons');
102836             var tagReferenceBodyWrap = selection.selectAll('.tag-reference-body-wrap').data([0]);
102837             tagReferenceBodyWrap = tagReferenceBodyWrap.enter().append('div').attr('class', 'tag-reference-body-wrap').merge(tagReferenceBodyWrap); // update header
102838
102839             if (_tagReference) {
102840               selection.selectAll('.preset-list-button-wrap .accessory-buttons').style('display', _presets.length === 1 ? null : 'none').call(_tagReference.button);
102841               tagReferenceBodyWrap.style('display', _presets.length === 1 ? null : 'none').call(_tagReference.body);
102842             }
102843
102844             selection.selectAll('.preset-reset').on('click', function () {
102845               dispatch.call('choose', this, _presets);
102846             }).on('pointerdown pointerup mousedown mouseup', function (d3_event) {
102847               d3_event.preventDefault();
102848               d3_event.stopPropagation();
102849             });
102850             var geometries = entityGeometries();
102851             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')));
102852             var names = _presets.length === 1 ? [_presets[0].nameLabel(), _presets[0].subtitleLabel()].filter(Boolean) : [_t('inspector.multiple_types')];
102853             var label = selection.select('.label-inner');
102854             var nameparts = label.selectAll('.namepart').data(names, function (d) {
102855               return d;
102856             });
102857             nameparts.exit().remove();
102858             nameparts.enter().append('div').attr('class', 'namepart').html(function (d) {
102859               return d;
102860             });
102861           }
102862
102863           section.entityIDs = function (val) {
102864             if (!arguments.length) return _entityIDs;
102865             _entityIDs = val;
102866             return section;
102867           };
102868
102869           section.presets = function (val) {
102870             if (!arguments.length) return _presets; // don't reload the same preset
102871
102872             if (!utilArrayIdentical(val, _presets)) {
102873               _presets = val;
102874
102875               if (_presets.length === 1) {
102876                 _tagReference = uiTagReference(_presets[0].reference()).showing(false);
102877               }
102878             }
102879
102880             return section;
102881           };
102882
102883           function entityGeometries() {
102884             var counts = {};
102885
102886             for (var i in _entityIDs) {
102887               var geometry = context.graph().geometry(_entityIDs[i]);
102888               if (!counts[geometry]) counts[geometry] = 0;
102889               counts[geometry] += 1;
102890             }
102891
102892             return Object.keys(counts).sort(function (geom1, geom2) {
102893               return counts[geom2] - counts[geom1];
102894             });
102895           }
102896
102897           return utilRebind(section, dispatch, 'on');
102898         }
102899
102900         function uiSectionPresetFields(context) {
102901           var section = uiSection('preset-fields', context).label(_t.html('inspector.fields')).disclosureContent(renderDisclosureContent);
102902           var dispatch = dispatch$8('change', 'revert');
102903           var formFields = uiFormFields(context);
102904
102905           var _state;
102906
102907           var _fieldsArr;
102908
102909           var _presets = [];
102910
102911           var _tags;
102912
102913           var _entityIDs;
102914
102915           function renderDisclosureContent(selection) {
102916             if (!_fieldsArr) {
102917               var graph = context.graph();
102918               var geometries = Object.keys(_entityIDs.reduce(function (geoms, entityID) {
102919                 geoms[graph.entity(entityID).geometry(graph)] = true;
102920                 return geoms;
102921               }, {}));
102922               var presetsManager = _mainPresetIndex;
102923               var allFields = [];
102924               var allMoreFields = [];
102925               var sharedTotalFields;
102926
102927               _presets.forEach(function (preset) {
102928                 var fields = preset.fields();
102929                 var moreFields = preset.moreFields();
102930                 allFields = utilArrayUnion(allFields, fields);
102931                 allMoreFields = utilArrayUnion(allMoreFields, moreFields);
102932
102933                 if (!sharedTotalFields) {
102934                   sharedTotalFields = utilArrayUnion(fields, moreFields);
102935                 } else {
102936                   sharedTotalFields = sharedTotalFields.filter(function (field) {
102937                     return fields.indexOf(field) !== -1 || moreFields.indexOf(field) !== -1;
102938                   });
102939                 }
102940               });
102941
102942               var sharedFields = allFields.filter(function (field) {
102943                 return sharedTotalFields.indexOf(field) !== -1;
102944               });
102945               var sharedMoreFields = allMoreFields.filter(function (field) {
102946                 return sharedTotalFields.indexOf(field) !== -1;
102947               });
102948               _fieldsArr = [];
102949               sharedFields.forEach(function (field) {
102950                 if (field.matchAllGeometry(geometries)) {
102951                   _fieldsArr.push(uiField(context, field, _entityIDs));
102952                 }
102953               });
102954               var singularEntity = _entityIDs.length === 1 && graph.hasEntity(_entityIDs[0]);
102955
102956               if (singularEntity && singularEntity.isHighwayIntersection(graph) && presetsManager.field('restrictions')) {
102957                 _fieldsArr.push(uiField(context, presetsManager.field('restrictions'), _entityIDs));
102958               }
102959
102960               var additionalFields = utilArrayUnion(sharedMoreFields, presetsManager.universal());
102961               additionalFields.sort(function (field1, field2) {
102962                 return field1.label().localeCompare(field2.label(), _mainLocalizer.localeCode());
102963               });
102964               additionalFields.forEach(function (field) {
102965                 if (sharedFields.indexOf(field) === -1 && field.matchAllGeometry(geometries)) {
102966                   _fieldsArr.push(uiField(context, field, _entityIDs, {
102967                     show: false
102968                   }));
102969                 }
102970               });
102971
102972               _fieldsArr.forEach(function (field) {
102973                 field.on('change', function (t, onInput) {
102974                   dispatch.call('change', field, _entityIDs, t, onInput);
102975                 }).on('revert', function (keys) {
102976                   dispatch.call('revert', field, keys);
102977                 });
102978               });
102979             }
102980
102981             _fieldsArr.forEach(function (field) {
102982               field.state(_state).tags(_tags);
102983             });
102984
102985             selection.call(formFields.fieldsArr(_fieldsArr).state(_state).klass('grouped-items-area'));
102986             selection.selectAll('.wrap-form-field input').on('keydown', function (d3_event) {
102987               // if user presses enter, and combobox is not active, accept edits..
102988               if (d3_event.keyCode === 13 && // ↩ Return
102989               context.container().select('.combobox').empty()) {
102990                 context.enter(modeBrowse(context));
102991               }
102992             });
102993           }
102994
102995           section.presets = function (val) {
102996             if (!arguments.length) return _presets;
102997
102998             if (!_presets || !val || !utilArrayIdentical(_presets, val)) {
102999               _presets = val;
103000               _fieldsArr = null;
103001             }
103002
103003             return section;
103004           };
103005
103006           section.state = function (val) {
103007             if (!arguments.length) return _state;
103008             _state = val;
103009             return section;
103010           };
103011
103012           section.tags = function (val) {
103013             if (!arguments.length) return _tags;
103014             _tags = val; // Don't reset _fieldsArr here.
103015
103016             return section;
103017           };
103018
103019           section.entityIDs = function (val) {
103020             if (!arguments.length) return _entityIDs;
103021
103022             if (!val || !_entityIDs || !utilArrayIdentical(_entityIDs, val)) {
103023               _entityIDs = val;
103024               _fieldsArr = null;
103025             }
103026
103027             return section;
103028           };
103029
103030           return utilRebind(section, dispatch, 'on');
103031         }
103032
103033         function uiSectionRawMemberEditor(context) {
103034           var section = uiSection('raw-member-editor', context).shouldDisplay(function () {
103035             if (!_entityIDs || _entityIDs.length !== 1) return false;
103036             var entity = context.hasEntity(_entityIDs[0]);
103037             return entity && entity.type === 'relation';
103038           }).label(function () {
103039             var entity = context.hasEntity(_entityIDs[0]);
103040             if (!entity) return '';
103041             var gt = entity.members.length > _maxMembers ? '>' : '';
103042             var count = gt + entity.members.slice(0, _maxMembers).length;
103043             return _t.html('inspector.title_count', {
103044               title: {
103045                 html: _t.html('inspector.members')
103046               },
103047               count: count
103048             });
103049           }).disclosureContent(renderDisclosureContent);
103050           var taginfo = services.taginfo;
103051
103052           var _entityIDs;
103053
103054           var _maxMembers = 1000;
103055
103056           function downloadMember(d3_event, d) {
103057             d3_event.preventDefault(); // display the loading indicator
103058
103059             select(this.parentNode).classed('tag-reference-loading', true);
103060             context.loadEntity(d.id, function () {
103061               section.reRender();
103062             });
103063           }
103064
103065           function zoomToMember(d3_event, d) {
103066             d3_event.preventDefault();
103067             var entity = context.entity(d.id);
103068             context.map().zoomToEase(entity); // highlight the feature in case it wasn't previously on-screen
103069
103070             utilHighlightEntities([d.id], true, context);
103071           }
103072
103073           function selectMember(d3_event, d) {
103074             d3_event.preventDefault(); // remove the hover-highlight styling
103075
103076             utilHighlightEntities([d.id], false, context);
103077             var entity = context.entity(d.id);
103078             var mapExtent = context.map().extent();
103079
103080             if (!entity.intersects(mapExtent, context.graph())) {
103081               // zoom to the entity if its extent is not visible now
103082               context.map().zoomToEase(entity);
103083             }
103084
103085             context.enter(modeSelect(context, [d.id]));
103086           }
103087
103088           function changeRole(d3_event, d) {
103089             var oldRole = d.role;
103090             var newRole = context.cleanRelationRole(select(this).property('value'));
103091
103092             if (oldRole !== newRole) {
103093               var member = {
103094                 id: d.id,
103095                 type: d.type,
103096                 role: newRole
103097               };
103098               context.perform(actionChangeMember(d.relation.id, member, d.index), _t('operations.change_role.annotation', {
103099                 n: 1
103100               }));
103101               context.validator().validate();
103102             }
103103           }
103104
103105           function deleteMember(d3_event, d) {
103106             // remove the hover-highlight styling
103107             utilHighlightEntities([d.id], false, context);
103108             context.perform(actionDeleteMember(d.relation.id, d.index), _t('operations.delete_member.annotation', {
103109               n: 1
103110             }));
103111
103112             if (!context.hasEntity(d.relation.id)) {
103113               // Removing the last member will also delete the relation.
103114               // If this happens we need to exit the selection mode
103115               context.enter(modeBrowse(context));
103116             } else {
103117               // Changing the mode also runs `validate`, but otherwise we need to
103118               // rerun it manually
103119               context.validator().validate();
103120             }
103121           }
103122
103123           function renderDisclosureContent(selection) {
103124             var entityID = _entityIDs[0];
103125             var memberships = [];
103126             var entity = context.entity(entityID);
103127             entity.members.slice(0, _maxMembers).forEach(function (member, index) {
103128               memberships.push({
103129                 index: index,
103130                 id: member.id,
103131                 type: member.type,
103132                 role: member.role,
103133                 relation: entity,
103134                 member: context.hasEntity(member.id),
103135                 domId: utilUniqueDomId(entityID + '-member-' + index)
103136               });
103137             });
103138             var list = selection.selectAll('.member-list').data([0]);
103139             list = list.enter().append('ul').attr('class', 'member-list').merge(list);
103140             var items = list.selectAll('li').data(memberships, function (d) {
103141               return osmEntity.key(d.relation) + ',' + d.index + ',' + (d.member ? osmEntity.key(d.member) : 'incomplete');
103142             });
103143             items.exit().each(unbind).remove();
103144             var itemsEnter = items.enter().append('li').attr('class', 'member-row form-field').classed('member-incomplete', function (d) {
103145               return !d.member;
103146             });
103147             itemsEnter.each(function (d) {
103148               var item = select(this);
103149               var label = item.append('label').attr('class', 'field-label').attr('for', d.domId);
103150
103151               if (d.member) {
103152                 // highlight the member feature in the map while hovering on the list item
103153                 item.on('mouseover', function () {
103154                   utilHighlightEntities([d.id], true, context);
103155                 }).on('mouseout', function () {
103156                   utilHighlightEntities([d.id], false, context);
103157                 });
103158                 var labelLink = label.append('span').attr('class', 'label-text').append('a').attr('href', '#').on('click', selectMember);
103159                 labelLink.append('span').attr('class', 'member-entity-type').text(function (d) {
103160                   var matched = _mainPresetIndex.match(d.member, context.graph());
103161                   return matched && matched.name() || utilDisplayType(d.member.id);
103162                 });
103163                 labelLink.append('span').attr('class', 'member-entity-name').text(function (d) {
103164                   return utilDisplayName(d.member);
103165                 });
103166                 label.append('button').attr('title', _t('icons.remove')).attr('class', 'remove member-delete').call(svgIcon('#iD-operation-delete'));
103167                 label.append('button').attr('class', 'member-zoom').attr('title', _t('icons.zoom_to')).call(svgIcon('#iD-icon-framed-dot', 'monochrome')).on('click', zoomToMember);
103168               } else {
103169                 var labelText = label.append('span').attr('class', 'label-text');
103170                 labelText.append('span').attr('class', 'member-entity-type').call(_t.append('inspector.' + d.type, {
103171                   id: d.id
103172                 }));
103173                 labelText.append('span').attr('class', 'member-entity-name').call(_t.append('inspector.incomplete', {
103174                   id: d.id
103175                 }));
103176                 label.append('button').attr('class', 'member-download').attr('title', _t('icons.download')).call(svgIcon('#iD-icon-load')).on('click', downloadMember);
103177               }
103178             });
103179             var wrapEnter = itemsEnter.append('div').attr('class', 'form-field-input-wrap form-field-input-member');
103180             wrapEnter.append('input').attr('class', 'member-role').attr('id', function (d) {
103181               return d.domId;
103182             }).property('type', 'text').attr('placeholder', _t('inspector.role')).call(utilNoAuto);
103183
103184             if (taginfo) {
103185               wrapEnter.each(bindTypeahead);
103186             } // update
103187
103188
103189             items = items.merge(itemsEnter).order();
103190             items.select('input.member-role').property('value', function (d) {
103191               return d.role;
103192             }).on('blur', changeRole).on('change', changeRole);
103193             items.select('button.member-delete').on('click', deleteMember);
103194             var dragOrigin, targetIndex;
103195             items.call(d3_drag().on('start', function (d3_event) {
103196               dragOrigin = {
103197                 x: d3_event.x,
103198                 y: d3_event.y
103199               };
103200               targetIndex = null;
103201             }).on('drag', function (d3_event) {
103202               var x = d3_event.x - dragOrigin.x,
103203                   y = d3_event.y - dragOrigin.y;
103204               if (!select(this).classed('dragging') && // don't display drag until dragging beyond a distance threshold
103205               Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)) <= 5) return;
103206               var index = items.nodes().indexOf(this);
103207               select(this).classed('dragging', true);
103208               targetIndex = null;
103209               selection.selectAll('li.member-row').style('transform', function (d2, index2) {
103210                 var node = select(this).node();
103211
103212                 if (index === index2) {
103213                   return 'translate(' + x + 'px, ' + y + 'px)';
103214                 } else if (index2 > index && d3_event.y > node.offsetTop) {
103215                   if (targetIndex === null || index2 > targetIndex) {
103216                     targetIndex = index2;
103217                   }
103218
103219                   return 'translateY(-100%)';
103220                 } else if (index2 < index && d3_event.y < node.offsetTop + node.offsetHeight) {
103221                   if (targetIndex === null || index2 < targetIndex) {
103222                     targetIndex = index2;
103223                   }
103224
103225                   return 'translateY(100%)';
103226                 }
103227
103228                 return null;
103229               });
103230             }).on('end', function (d3_event, d) {
103231               if (!select(this).classed('dragging')) return;
103232               var index = items.nodes().indexOf(this);
103233               select(this).classed('dragging', false);
103234               selection.selectAll('li.member-row').style('transform', null);
103235
103236               if (targetIndex !== null) {
103237                 // dragged to a new position, reorder
103238                 context.perform(actionMoveMember(d.relation.id, index, targetIndex), _t('operations.reorder_members.annotation'));
103239                 context.validator().validate();
103240               }
103241             }));
103242
103243             function bindTypeahead(d) {
103244               var row = select(this);
103245               var role = row.selectAll('input.member-role');
103246               var origValue = role.property('value');
103247
103248               function sort(value, data) {
103249                 var sameletter = [];
103250                 var other = [];
103251
103252                 for (var i = 0; i < data.length; i++) {
103253                   if (data[i].value.substring(0, value.length) === value) {
103254                     sameletter.push(data[i]);
103255                   } else {
103256                     other.push(data[i]);
103257                   }
103258                 }
103259
103260                 return sameletter.concat(other);
103261               }
103262
103263               role.call(uiCombobox(context, 'member-role').fetcher(function (role, callback) {
103264                 // The `geometry` param is used in the `taginfo.js` interface for
103265                 // filtering results, as a key into the `tag_members_fractions`
103266                 // object.  If we don't know the geometry because the member is
103267                 // not yet downloaded, it's ok to guess based on type.
103268                 var geometry;
103269
103270                 if (d.member) {
103271                   geometry = context.graph().geometry(d.member.id);
103272                 } else if (d.type === 'relation') {
103273                   geometry = 'relation';
103274                 } else if (d.type === 'way') {
103275                   geometry = 'line';
103276                 } else {
103277                   geometry = 'point';
103278                 }
103279
103280                 var rtype = entity.tags.type;
103281                 taginfo.roles({
103282                   debounce: true,
103283                   rtype: rtype || '',
103284                   geometry: geometry,
103285                   query: role
103286                 }, function (err, data) {
103287                   if (!err) callback(sort(role, data));
103288                 });
103289               }).on('cancel', function () {
103290                 role.property('value', origValue);
103291               }));
103292             }
103293
103294             function unbind() {
103295               var row = select(this);
103296               row.selectAll('input.member-role').call(uiCombobox.off, context);
103297             }
103298           }
103299
103300           section.entityIDs = function (val) {
103301             if (!arguments.length) return _entityIDs;
103302             _entityIDs = val;
103303             return section;
103304           };
103305
103306           return section;
103307         }
103308
103309         function actionDeleteMembers(relationId, memberIndexes) {
103310           return function (graph) {
103311             // Remove the members in descending order so removals won't shift what members
103312             // are at the remaining indexes
103313             memberIndexes.sort(function (a, b) {
103314               return b - a;
103315             });
103316
103317             for (var i in memberIndexes) {
103318               graph = actionDeleteMember(relationId, memberIndexes[i])(graph);
103319             }
103320
103321             return graph;
103322           };
103323         }
103324
103325         function uiSectionRawMembershipEditor(context) {
103326           var section = uiSection('raw-membership-editor', context).shouldDisplay(function () {
103327             return _entityIDs && _entityIDs.length;
103328           }).label(function () {
103329             var parents = getSharedParentRelations();
103330             var gt = parents.length > _maxMemberships ? '>' : '';
103331             var count = gt + parents.slice(0, _maxMemberships).length;
103332             return _t.html('inspector.title_count', {
103333               title: {
103334                 html: _t.html('inspector.relations')
103335               },
103336               count: count
103337             });
103338           }).disclosureContent(renderDisclosureContent);
103339           var taginfo = services.taginfo;
103340           var nearbyCombo = uiCombobox(context, 'parent-relation').minItems(1).fetcher(fetchNearbyRelations).itemsMouseEnter(function (d3_event, d) {
103341             if (d.relation) utilHighlightEntities([d.relation.id], true, context);
103342           }).itemsMouseLeave(function (d3_event, d) {
103343             if (d.relation) utilHighlightEntities([d.relation.id], false, context);
103344           });
103345           var _inChange = false;
103346           var _entityIDs = [];
103347
103348           var _showBlank;
103349
103350           var _maxMemberships = 1000;
103351
103352           function getSharedParentRelations() {
103353             var parents = [];
103354
103355             for (var i = 0; i < _entityIDs.length; i++) {
103356               var entity = context.graph().hasEntity(_entityIDs[i]);
103357               if (!entity) continue;
103358
103359               if (i === 0) {
103360                 parents = context.graph().parentRelations(entity);
103361               } else {
103362                 parents = utilArrayIntersection(parents, context.graph().parentRelations(entity));
103363               }
103364
103365               if (!parents.length) break;
103366             }
103367
103368             return parents;
103369           }
103370
103371           function getMemberships() {
103372             var memberships = [];
103373             var relations = getSharedParentRelations().slice(0, _maxMemberships);
103374             var isMultiselect = _entityIDs.length > 1;
103375             var i, relation, membership, index, member, indexedMember;
103376
103377             for (i = 0; i < relations.length; i++) {
103378               relation = relations[i];
103379               membership = {
103380                 relation: relation,
103381                 members: [],
103382                 hash: osmEntity.key(relation)
103383               };
103384
103385               for (index = 0; index < relation.members.length; index++) {
103386                 member = relation.members[index];
103387
103388                 if (_entityIDs.indexOf(member.id) !== -1) {
103389                   indexedMember = Object.assign({}, member, {
103390                     index: index
103391                   });
103392                   membership.members.push(indexedMember);
103393                   membership.hash += ',' + index.toString();
103394
103395                   if (!isMultiselect) {
103396                     // For single selections, list one entry per membership per relation.
103397                     // For multiselections, list one entry per relation.
103398                     memberships.push(membership);
103399                     membership = {
103400                       relation: relation,
103401                       members: [],
103402                       hash: osmEntity.key(relation)
103403                     };
103404                   }
103405                 }
103406               }
103407
103408               if (membership.members.length) memberships.push(membership);
103409             }
103410
103411             memberships.forEach(function (membership) {
103412               membership.domId = utilUniqueDomId('membership-' + membership.relation.id);
103413               var roles = [];
103414               membership.members.forEach(function (member) {
103415                 if (roles.indexOf(member.role) === -1) roles.push(member.role);
103416               });
103417               membership.role = roles.length === 1 ? roles[0] : roles;
103418             });
103419             return memberships;
103420           }
103421
103422           function selectRelation(d3_event, d) {
103423             d3_event.preventDefault(); // remove the hover-highlight styling
103424
103425             utilHighlightEntities([d.relation.id], false, context);
103426             context.enter(modeSelect(context, [d.relation.id]));
103427           }
103428
103429           function zoomToRelation(d3_event, d) {
103430             d3_event.preventDefault();
103431             var entity = context.entity(d.relation.id);
103432             context.map().zoomToEase(entity); // highlight the relation in case it wasn't previously on-screen
103433
103434             utilHighlightEntities([d.relation.id], true, context);
103435           }
103436
103437           function changeRole(d3_event, d) {
103438             if (d === 0) return; // called on newrow (shouldn't happen)
103439
103440             if (_inChange) return; // avoid accidental recursive call #5731
103441
103442             var newRole = context.cleanRelationRole(select(this).property('value'));
103443             if (!newRole.trim() && typeof d.role !== 'string') return;
103444             var membersToUpdate = d.members.filter(function (member) {
103445               return member.role !== newRole;
103446             });
103447
103448             if (membersToUpdate.length) {
103449               _inChange = true;
103450               context.perform(function actionChangeMemberRoles(graph) {
103451                 membersToUpdate.forEach(function (member) {
103452                   var newMember = Object.assign({}, member, {
103453                     role: newRole
103454                   });
103455                   delete newMember.index;
103456                   graph = actionChangeMember(d.relation.id, newMember, member.index)(graph);
103457                 });
103458                 return graph;
103459               }, _t('operations.change_role.annotation', {
103460                 n: membersToUpdate.length
103461               }));
103462               context.validator().validate();
103463             }
103464
103465             _inChange = false;
103466           }
103467
103468           function addMembership(d, role) {
103469             this.blur(); // avoid keeping focus on the button
103470
103471             _showBlank = false;
103472
103473             function actionAddMembers(relationId, ids, role) {
103474               return function (graph) {
103475                 for (var i in ids) {
103476                   var member = {
103477                     id: ids[i],
103478                     type: graph.entity(ids[i]).type,
103479                     role: role
103480                   };
103481                   graph = actionAddMember(relationId, member)(graph);
103482                 }
103483
103484                 return graph;
103485               };
103486             }
103487
103488             if (d.relation) {
103489               context.perform(actionAddMembers(d.relation.id, _entityIDs, role), _t('operations.add_member.annotation', {
103490                 n: _entityIDs.length
103491               }));
103492               context.validator().validate();
103493             } else {
103494               var relation = osmRelation();
103495               context.perform(actionAddEntity(relation), actionAddMembers(relation.id, _entityIDs, role), _t('operations.add.annotation.relation')); // changing the mode also runs `validate`
103496
103497               context.enter(modeSelect(context, [relation.id]).newFeature(true));
103498             }
103499           }
103500
103501           function deleteMembership(d3_event, d) {
103502             this.blur(); // avoid keeping focus on the button
103503
103504             if (d === 0) return; // called on newrow (shouldn't happen)
103505             // remove the hover-highlight styling
103506
103507             utilHighlightEntities([d.relation.id], false, context);
103508             var indexes = d.members.map(function (member) {
103509               return member.index;
103510             });
103511             context.perform(actionDeleteMembers(d.relation.id, indexes), _t('operations.delete_member.annotation', {
103512               n: _entityIDs.length
103513             }));
103514             context.validator().validate();
103515           }
103516
103517           function fetchNearbyRelations(q, callback) {
103518             var newRelation = {
103519               relation: null,
103520               value: _t('inspector.new_relation'),
103521               display: _t.html('inspector.new_relation')
103522             };
103523             var entityID = _entityIDs[0];
103524             var result = [];
103525             var graph = context.graph();
103526
103527             function baseDisplayLabel(entity) {
103528               var matched = _mainPresetIndex.match(entity, graph);
103529               var presetName = matched && matched.name() || _t('inspector.relation');
103530               var entityName = utilDisplayName(entity) || '';
103531               return presetName + ' ' + entityName;
103532             }
103533
103534             var explicitRelation = q && context.hasEntity(q.toLowerCase());
103535
103536             if (explicitRelation && explicitRelation.type === 'relation' && explicitRelation.id !== entityID) {
103537               // loaded relation is specified explicitly, only show that
103538               result.push({
103539                 relation: explicitRelation,
103540                 value: baseDisplayLabel(explicitRelation) + ' ' + explicitRelation.id
103541               });
103542             } else {
103543               context.history().intersects(context.map().extent()).forEach(function (entity) {
103544                 if (entity.type !== 'relation' || entity.id === entityID) return;
103545                 var value = baseDisplayLabel(entity);
103546                 if (q && (value + ' ' + entity.id).toLowerCase().indexOf(q.toLowerCase()) === -1) return;
103547                 result.push({
103548                   relation: entity,
103549                   value: value
103550                 });
103551               });
103552               result.sort(function (a, b) {
103553                 return osmRelation.creationOrder(a.relation, b.relation);
103554               }); // Dedupe identical names by appending relation id - see #2891
103555
103556               var dupeGroups = Object.values(utilArrayGroupBy(result, 'value')).filter(function (v) {
103557                 return v.length > 1;
103558               });
103559               dupeGroups.forEach(function (group) {
103560                 group.forEach(function (obj) {
103561                   obj.value += ' ' + obj.relation.id;
103562                 });
103563               });
103564             }
103565
103566             result.forEach(function (obj) {
103567               obj.title = obj.value;
103568             });
103569             result.unshift(newRelation);
103570             callback(result);
103571           }
103572
103573           function renderDisclosureContent(selection) {
103574             var memberships = getMemberships();
103575             var list = selection.selectAll('.member-list').data([0]);
103576             list = list.enter().append('ul').attr('class', 'member-list').merge(list);
103577             var items = list.selectAll('li.member-row-normal').data(memberships, function (d) {
103578               return d.hash;
103579             });
103580             items.exit().each(unbind).remove(); // Enter
103581
103582             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
103583
103584             itemsEnter.on('mouseover', function (d3_event, d) {
103585               utilHighlightEntities([d.relation.id], true, context);
103586             }).on('mouseout', function (d3_event, d) {
103587               utilHighlightEntities([d.relation.id], false, context);
103588             });
103589             var labelEnter = itemsEnter.append('label').attr('class', 'field-label').attr('for', function (d) {
103590               return d.domId;
103591             });
103592             var labelLink = labelEnter.append('span').attr('class', 'label-text').append('a').attr('href', '#').on('click', selectRelation);
103593             labelLink.append('span').attr('class', 'member-entity-type').text(function (d) {
103594               var matched = _mainPresetIndex.match(d.relation, context.graph());
103595               return matched && matched.name() || _t.html('inspector.relation');
103596             });
103597             labelLink.append('span').attr('class', 'member-entity-name').text(function (d) {
103598               return utilDisplayName(d.relation);
103599             });
103600             labelEnter.append('button').attr('class', 'remove member-delete').attr('title', _t('icons.remove')).call(svgIcon('#iD-operation-delete')).on('click', deleteMembership);
103601             labelEnter.append('button').attr('class', 'member-zoom').attr('title', _t('icons.zoom_to')).call(svgIcon('#iD-icon-framed-dot', 'monochrome')).on('click', zoomToRelation);
103602             var wrapEnter = itemsEnter.append('div').attr('class', 'form-field-input-wrap form-field-input-member');
103603             wrapEnter.append('input').attr('class', 'member-role').attr('id', function (d) {
103604               return d.domId;
103605             }).property('type', 'text').property('value', function (d) {
103606               return typeof d.role === 'string' ? d.role : '';
103607             }).attr('title', function (d) {
103608               return Array.isArray(d.role) ? d.role.filter(Boolean).join('\n') : d.role;
103609             }).attr('placeholder', function (d) {
103610               return Array.isArray(d.role) ? _t('inspector.multiple_roles') : _t('inspector.role');
103611             }).classed('mixed', function (d) {
103612               return Array.isArray(d.role);
103613             }).call(utilNoAuto).on('blur', changeRole).on('change', changeRole);
103614
103615             if (taginfo) {
103616               wrapEnter.each(bindTypeahead);
103617             }
103618
103619             var newMembership = list.selectAll('.member-row-new').data(_showBlank ? [0] : []); // Exit
103620
103621             newMembership.exit().remove(); // Enter
103622
103623             var newMembershipEnter = newMembership.enter().append('li').attr('class', 'member-row member-row-new form-field');
103624             var newLabelEnter = newMembershipEnter.append('label').attr('class', 'field-label');
103625             newLabelEnter.append('input').attr('placeholder', _t('inspector.choose_relation')).attr('type', 'text').attr('class', 'member-entity-input').call(utilNoAuto);
103626             newLabelEnter.append('button').attr('class', 'remove member-delete').attr('title', _t('icons.remove')).call(svgIcon('#iD-operation-delete')).on('click', function () {
103627               list.selectAll('.member-row-new').remove();
103628             });
103629             var newWrapEnter = newMembershipEnter.append('div').attr('class', 'form-field-input-wrap form-field-input-member');
103630             newWrapEnter.append('input').attr('class', 'member-role').property('type', 'text').attr('placeholder', _t('inspector.role')).call(utilNoAuto); // Update
103631
103632             newMembership = newMembership.merge(newMembershipEnter);
103633             newMembership.selectAll('.member-entity-input').on('blur', cancelEntity) // if it wasn't accepted normally, cancel it
103634             .call(nearbyCombo.on('accept', acceptEntity).on('cancel', cancelEntity)); // Container for the Add button
103635
103636             var addRow = selection.selectAll('.add-row').data([0]); // enter
103637
103638             var addRowEnter = addRow.enter().append('div').attr('class', 'add-row');
103639             var addRelationButton = addRowEnter.append('button').attr('class', 'add-relation').attr('aria-label', _t('inspector.add_to_relation'));
103640             addRelationButton.call(svgIcon('#iD-icon-plus', 'light'));
103641             addRelationButton.call(uiTooltip().title(_t.html('inspector.add_to_relation')).placement(_mainLocalizer.textDirection() === 'ltr' ? 'right' : 'left'));
103642             addRowEnter.append('div').attr('class', 'space-value'); // preserve space
103643
103644             addRowEnter.append('div').attr('class', 'space-buttons'); // preserve space
103645             // update
103646
103647             addRow = addRow.merge(addRowEnter);
103648             addRow.select('.add-relation').on('click', function () {
103649               _showBlank = true;
103650               section.reRender();
103651               list.selectAll('.member-entity-input').node().focus();
103652             });
103653
103654             function acceptEntity(d) {
103655               if (!d) {
103656                 cancelEntity();
103657                 return;
103658               } // remove hover-higlighting
103659
103660
103661               if (d.relation) utilHighlightEntities([d.relation.id], false, context);
103662               var role = context.cleanRelationRole(list.selectAll('.member-row-new .member-role').property('value'));
103663               addMembership(d, role);
103664             }
103665
103666             function cancelEntity() {
103667               var input = newMembership.selectAll('.member-entity-input');
103668               input.property('value', ''); // remove hover-higlighting
103669
103670               context.surface().selectAll('.highlighted').classed('highlighted', false);
103671             }
103672
103673             function bindTypeahead(d) {
103674               var row = select(this);
103675               var role = row.selectAll('input.member-role');
103676               var origValue = role.property('value');
103677
103678               function sort(value, data) {
103679                 var sameletter = [];
103680                 var other = [];
103681
103682                 for (var i = 0; i < data.length; i++) {
103683                   if (data[i].value.substring(0, value.length) === value) {
103684                     sameletter.push(data[i]);
103685                   } else {
103686                     other.push(data[i]);
103687                   }
103688                 }
103689
103690                 return sameletter.concat(other);
103691               }
103692
103693               role.call(uiCombobox(context, 'member-role').fetcher(function (role, callback) {
103694                 var rtype = d.relation.tags.type;
103695                 taginfo.roles({
103696                   debounce: true,
103697                   rtype: rtype || '',
103698                   geometry: context.graph().geometry(_entityIDs[0]),
103699                   query: role
103700                 }, function (err, data) {
103701                   if (!err) callback(sort(role, data));
103702                 });
103703               }).on('cancel', function () {
103704                 role.property('value', origValue);
103705               }));
103706             }
103707
103708             function unbind() {
103709               var row = select(this);
103710               row.selectAll('input.member-role').call(uiCombobox.off, context);
103711             }
103712           }
103713
103714           section.entityIDs = function (val) {
103715             if (!arguments.length) return _entityIDs;
103716             _entityIDs = val;
103717             _showBlank = false;
103718             return section;
103719           };
103720
103721           return section;
103722         }
103723
103724         function uiSectionSelectionList(context) {
103725           var _selectedIDs = [];
103726           var section = uiSection('selected-features', context).shouldDisplay(function () {
103727             return _selectedIDs.length > 1;
103728           }).label(function () {
103729             return _t.html('inspector.title_count', {
103730               title: {
103731                 html: _t.html('inspector.features')
103732               },
103733               count: _selectedIDs.length
103734             });
103735           }).disclosureContent(renderDisclosureContent);
103736           context.history().on('change.selectionList', function (difference) {
103737             if (difference) {
103738               section.reRender();
103739             }
103740           });
103741
103742           section.entityIDs = function (val) {
103743             if (!arguments.length) return _selectedIDs;
103744             _selectedIDs = val;
103745             return section;
103746           };
103747
103748           function selectEntity(d3_event, entity) {
103749             context.enter(modeSelect(context, [entity.id]));
103750           }
103751
103752           function deselectEntity(d3_event, entity) {
103753             var selectedIDs = _selectedIDs.slice();
103754
103755             var index = selectedIDs.indexOf(entity.id);
103756
103757             if (index > -1) {
103758               selectedIDs.splice(index, 1);
103759               context.enter(modeSelect(context, selectedIDs));
103760             }
103761           }
103762
103763           function renderDisclosureContent(selection) {
103764             var list = selection.selectAll('.feature-list').data([0]);
103765             list = list.enter().append('ul').attr('class', 'feature-list').merge(list);
103766
103767             var entities = _selectedIDs.map(function (id) {
103768               return context.hasEntity(id);
103769             }).filter(Boolean);
103770
103771             var items = list.selectAll('.feature-list-item').data(entities, osmEntity.key);
103772             items.exit().remove(); // Enter
103773
103774             var enter = items.enter().append('li').attr('class', 'feature-list-item').each(function (d) {
103775               select(this).on('mouseover', function () {
103776                 utilHighlightEntities([d.id], true, context);
103777               }).on('mouseout', function () {
103778                 utilHighlightEntities([d.id], false, context);
103779               });
103780             });
103781             var label = enter.append('button').attr('class', 'label').on('click', selectEntity);
103782             label.append('span').attr('class', 'entity-geom-icon').call(svgIcon('', 'pre-text'));
103783             label.append('span').attr('class', 'entity-type');
103784             label.append('span').attr('class', 'entity-name');
103785             enter.append('button').attr('class', 'close').attr('title', _t('icons.deselect')).on('click', deselectEntity).call(svgIcon('#iD-icon-close')); // Update
103786
103787             items = items.merge(enter);
103788             items.selectAll('.entity-geom-icon use').attr('href', function () {
103789               var entity = this.parentNode.parentNode.__data__;
103790               return '#iD-icon-' + entity.geometry(context.graph());
103791             });
103792             items.selectAll('.entity-type').text(function (entity) {
103793               return _mainPresetIndex.match(entity, context.graph()).name();
103794             });
103795             items.selectAll('.entity-name').text(function (d) {
103796               // fetch latest entity
103797               var entity = context.entity(d.id);
103798               return utilDisplayName(entity);
103799             });
103800           }
103801
103802           return section;
103803         }
103804
103805         function uiEntityEditor(context) {
103806           var dispatch = dispatch$8('choose');
103807           var _state = 'select';
103808           var _coalesceChanges = false;
103809           var _modified = false;
103810
103811           var _base;
103812
103813           var _entityIDs;
103814
103815           var _activePresets = [];
103816
103817           var _newFeature;
103818
103819           var _sections;
103820
103821           function entityEditor(selection) {
103822             var combinedTags = utilCombinedTags(_entityIDs, context.graph()); // Header
103823
103824             var header = selection.selectAll('.header').data([0]); // Enter
103825
103826             var headerEnter = header.enter().append('div').attr('class', 'header fillL');
103827             var direction = _mainLocalizer.textDirection() === 'rtl' ? 'forward' : 'backward';
103828             headerEnter.append('button').attr('class', 'preset-reset preset-choose').attr('title', _t("icons.".concat(direction))).call(svgIcon("#iD-icon-".concat(direction)));
103829             headerEnter.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
103830               context.enter(modeBrowse(context));
103831             }).call(svgIcon(_modified ? '#iD-icon-apply' : '#iD-icon-close'));
103832             headerEnter.append('h2'); // Update
103833
103834             header = header.merge(headerEnter);
103835             header.selectAll('h2').html(_entityIDs.length === 1 ? _t.html('inspector.edit') : _t.html('inspector.edit_features'));
103836             header.selectAll('.preset-reset').on('click', function () {
103837               dispatch.call('choose', this, _activePresets);
103838             }); // Body
103839
103840             var body = selection.selectAll('.inspector-body').data([0]); // Enter
103841
103842             var bodyEnter = body.enter().append('div').attr('class', 'entity-editor inspector-body sep-top'); // Update
103843
103844             body = body.merge(bodyEnter);
103845
103846             if (!_sections) {
103847               _sections = [uiSectionSelectionList(context), uiSectionFeatureType(context).on('choose', function (presets) {
103848                 dispatch.call('choose', this, presets);
103849               }), uiSectionEntityIssues(context), uiSectionPresetFields(context).on('change', changeTags).on('revert', revertTags), uiSectionRawTagEditor('raw-tag-editor', context).on('change', changeTags), uiSectionRawMemberEditor(context), uiSectionRawMembershipEditor(context)];
103850             }
103851
103852             _sections.forEach(function (section) {
103853               if (section.entityIDs) {
103854                 section.entityIDs(_entityIDs);
103855               }
103856
103857               if (section.presets) {
103858                 section.presets(_activePresets);
103859               }
103860
103861               if (section.tags) {
103862                 section.tags(combinedTags);
103863               }
103864
103865               if (section.state) {
103866                 section.state(_state);
103867               }
103868
103869               body.call(section.render);
103870             });
103871
103872             context.history().on('change.entity-editor', historyChanged);
103873
103874             function historyChanged(difference) {
103875               if (selection.selectAll('.entity-editor').empty()) return;
103876               if (_state === 'hide') return;
103877               var significant = !difference || difference.didChange.properties || difference.didChange.addition || difference.didChange.deletion;
103878               if (!significant) return;
103879               _entityIDs = _entityIDs.filter(context.hasEntity);
103880               if (!_entityIDs.length) return;
103881               var priorActivePreset = _activePresets.length === 1 && _activePresets[0];
103882               loadActivePresets();
103883               var graph = context.graph();
103884               entityEditor.modified(_base !== graph);
103885               entityEditor(selection);
103886
103887               if (priorActivePreset && _activePresets.length === 1 && priorActivePreset !== _activePresets[0]) {
103888                 // flash the button to indicate the preset changed
103889                 context.container().selectAll('.entity-editor button.preset-reset .label').style('background-color', '#fff').transition().duration(750).style('background-color', null);
103890               }
103891             }
103892           } // Tag changes that fire on input can all get coalesced into a single
103893           // history operation when the user leaves the field.  #2342
103894           // Use explicit entityIDs in case the selection changes before the event is fired.
103895
103896
103897           function changeTags(entityIDs, changed, onInput) {
103898             var actions = [];
103899
103900             for (var i in entityIDs) {
103901               var entityID = entityIDs[i];
103902               var entity = context.entity(entityID);
103903               var tags = Object.assign({}, entity.tags); // shallow copy
103904
103905               for (var k in changed) {
103906                 if (!k) continue;
103907                 var v = changed[k];
103908
103909                 if (_typeof(v) === 'object') {
103910                   // a "key only" tag change
103911                   tags[k] = tags[v.oldKey];
103912                 } else if (v !== undefined || tags.hasOwnProperty(k)) {
103913                   tags[k] = v;
103914                 }
103915               }
103916
103917               if (!onInput) {
103918                 tags = utilCleanTags(tags);
103919               }
103920
103921               if (!fastDeepEqual(entity.tags, tags)) {
103922                 actions.push(actionChangeTags(entityID, tags));
103923               }
103924             }
103925
103926             if (actions.length) {
103927               var combinedAction = function combinedAction(graph) {
103928                 actions.forEach(function (action) {
103929                   graph = action(graph);
103930                 });
103931                 return graph;
103932               };
103933
103934               var annotation = _t('operations.change_tags.annotation');
103935
103936               if (_coalesceChanges) {
103937                 context.overwrite(combinedAction, annotation);
103938               } else {
103939                 context.perform(combinedAction, annotation);
103940                 _coalesceChanges = !!onInput;
103941               }
103942             } // if leaving field (blur event), rerun validation
103943
103944
103945             if (!onInput) {
103946               context.validator().validate();
103947             }
103948           }
103949
103950           function revertTags(keys) {
103951             var actions = [];
103952
103953             for (var i in _entityIDs) {
103954               var entityID = _entityIDs[i];
103955               var original = context.graph().base().entities[entityID];
103956               var changed = {};
103957
103958               for (var j in keys) {
103959                 var key = keys[j];
103960                 changed[key] = original ? original.tags[key] : undefined;
103961               }
103962
103963               var entity = context.entity(entityID);
103964               var tags = Object.assign({}, entity.tags); // shallow copy
103965
103966               for (var k in changed) {
103967                 if (!k) continue;
103968                 var v = changed[k];
103969
103970                 if (v !== undefined || tags.hasOwnProperty(k)) {
103971                   tags[k] = v;
103972                 }
103973               }
103974
103975               tags = utilCleanTags(tags);
103976
103977               if (!fastDeepEqual(entity.tags, tags)) {
103978                 actions.push(actionChangeTags(entityID, tags));
103979               }
103980             }
103981
103982             if (actions.length) {
103983               var combinedAction = function combinedAction(graph) {
103984                 actions.forEach(function (action) {
103985                   graph = action(graph);
103986                 });
103987                 return graph;
103988               };
103989
103990               var annotation = _t('operations.change_tags.annotation');
103991
103992               if (_coalesceChanges) {
103993                 context.overwrite(combinedAction, annotation);
103994               } else {
103995                 context.perform(combinedAction, annotation);
103996                 _coalesceChanges = false;
103997               }
103998             }
103999
104000             context.validator().validate();
104001           }
104002
104003           entityEditor.modified = function (val) {
104004             if (!arguments.length) return _modified;
104005             _modified = val;
104006             return entityEditor;
104007           };
104008
104009           entityEditor.state = function (val) {
104010             if (!arguments.length) return _state;
104011             _state = val;
104012             return entityEditor;
104013           };
104014
104015           entityEditor.entityIDs = function (val) {
104016             if (!arguments.length) return _entityIDs; // always reload these even if the entityIDs are unchanged, since we
104017             // could be reselecting after something like dragging a node
104018
104019             _base = context.graph();
104020             _coalesceChanges = false;
104021             if (val && _entityIDs && utilArrayIdentical(_entityIDs, val)) return entityEditor; // exit early if no change
104022
104023             _entityIDs = val;
104024             loadActivePresets(true);
104025             return entityEditor.modified(false);
104026           };
104027
104028           entityEditor.newFeature = function (val) {
104029             if (!arguments.length) return _newFeature;
104030             _newFeature = val;
104031             return entityEditor;
104032           };
104033
104034           function loadActivePresets(isForNewSelection) {
104035             var graph = context.graph();
104036             var counts = {};
104037
104038             for (var i in _entityIDs) {
104039               var entity = graph.hasEntity(_entityIDs[i]);
104040               if (!entity) return;
104041               var match = _mainPresetIndex.match(entity, graph);
104042               if (!counts[match.id]) counts[match.id] = 0;
104043               counts[match.id] += 1;
104044             }
104045
104046             var matches = Object.keys(counts).sort(function (p1, p2) {
104047               return counts[p2] - counts[p1];
104048             }).map(function (pID) {
104049               return _mainPresetIndex.item(pID);
104050             });
104051
104052             if (!isForNewSelection) {
104053               // A "weak" preset doesn't set any tags. (e.g. "Address")
104054               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")
104055
104056               if (weakPreset && matches.length === 1 && matches[0].isFallback()) return;
104057             }
104058
104059             entityEditor.presets(matches);
104060           }
104061
104062           entityEditor.presets = function (val) {
104063             if (!arguments.length) return _activePresets; // don't reload the same preset
104064
104065             if (!utilArrayIdentical(val, _activePresets)) {
104066               _activePresets = val;
104067             }
104068
104069             return entityEditor;
104070           };
104071
104072           return utilRebind(entityEditor, dispatch, 'on');
104073         }
104074
104075         var sexagesimal = {exports: {}};
104076
104077         sexagesimal.exports = element;
104078         var pair_1 = sexagesimal.exports.pair = pair;
104079         sexagesimal.exports.format = format;
104080         sexagesimal.exports.formatPair = formatPair;
104081         sexagesimal.exports.coordToDMS = coordToDMS;
104082
104083         function element(input, dims) {
104084           var result = search(input, dims);
104085           return result === null ? null : result.val;
104086         }
104087
104088         function formatPair(input) {
104089           return format(input.lat, 'lat') + ' ' + format(input.lon, 'lon');
104090         } // Is 0 North or South?
104091
104092
104093         function format(input, dim) {
104094           var dms = coordToDMS(input, dim);
104095           return dms.whole + '° ' + (dms.minutes ? dms.minutes + '\' ' : '') + (dms.seconds ? dms.seconds + '" ' : '') + dms.dir;
104096         }
104097
104098         function coordToDMS(input, dim) {
104099           var dirs = {
104100             lat: ['N', 'S'],
104101             lon: ['E', 'W']
104102           }[dim] || '';
104103           var dir = dirs[input >= 0 ? 0 : 1];
104104           var abs = Math.abs(input);
104105           var whole = Math.floor(abs);
104106           var fraction = abs - whole;
104107           var fractionMinutes = fraction * 60;
104108           var minutes = Math.floor(fractionMinutes);
104109           var seconds = Math.floor((fractionMinutes - minutes) * 60);
104110           return {
104111             whole: whole,
104112             minutes: minutes,
104113             seconds: seconds,
104114             dir: dir
104115           };
104116         }
104117
104118         function search(input, dims) {
104119           if (!dims) dims = 'NSEW';
104120           if (typeof input !== 'string') return null;
104121           input = input.toUpperCase();
104122           var regex = /^[\s\,]*([NSEW])?\s*([\-|\—|\―]?[0-9.]+)[°º˚]?\s*(?:([0-9.]+)['’′‘]\s*)?(?:([0-9.]+)(?:''|"|”|″)\s*)?([NSEW])?/;
104123           var m = input.match(regex);
104124           if (!m) return null; // no match
104125
104126           var matched = m[0]; // extract dimension.. m[1] = leading, m[5] = trailing
104127
104128           var dim;
104129
104130           if (m[1] && m[5]) {
104131             // if matched both..
104132             dim = m[1]; // keep leading
104133
104134             matched = matched.slice(0, -1); // remove trailing dimension from match
104135           } else {
104136             dim = m[1] || m[5];
104137           } // if unrecognized dimension
104138
104139
104140           if (dim && dims.indexOf(dim) === -1) return null; // extract DMS
104141
104142           var deg = m[2] ? parseFloat(m[2]) : 0;
104143           var min = m[3] ? parseFloat(m[3]) / 60 : 0;
104144           var sec = m[4] ? parseFloat(m[4]) / 3600 : 0;
104145           var sign = deg < 0 ? -1 : 1;
104146           if (dim === 'S' || dim === 'W') sign *= -1;
104147           return {
104148             val: (Math.abs(deg) + min + sec) * sign,
104149             dim: dim,
104150             matched: matched,
104151             remain: input.slice(matched.length)
104152           };
104153         }
104154
104155         function pair(input, dims) {
104156           input = input.trim();
104157           var one = search(input, dims);
104158           if (!one) return null;
104159           input = one.remain.trim();
104160           var two = search(input, dims);
104161           if (!two || two.remain) return null;
104162
104163           if (one.dim) {
104164             return swapdim(one.val, two.val, one.dim);
104165           } else {
104166             return [one.val, two.val];
104167           }
104168         }
104169
104170         function swapdim(a, b, dim) {
104171           if (dim === 'N' || dim === 'S') return [a, b];
104172           if (dim === 'W' || dim === 'E') return [b, a];
104173         }
104174
104175         function uiFeatureList(context) {
104176           var _geocodeResults;
104177
104178           function featureList(selection) {
104179             var header = selection.append('div').attr('class', 'header fillL');
104180             header.append('h2').call(_t.append('inspector.feature_list'));
104181             var searchWrap = selection.append('div').attr('class', 'search-header');
104182             searchWrap.call(svgIcon('#iD-icon-search', 'pre-text'));
104183             var search = searchWrap.append('input').attr('placeholder', _t('inspector.search')).attr('type', 'search').call(utilNoAuto).on('keypress', keypress).on('keydown', keydown).on('input', inputevent);
104184             var listWrap = selection.append('div').attr('class', 'inspector-body');
104185             var list = listWrap.append('div').attr('class', 'feature-list');
104186             context.on('exit.feature-list', clearSearch);
104187             context.map().on('drawn.feature-list', mapDrawn);
104188             context.keybinding().on(uiCmd('⌘F'), focusSearch);
104189
104190             function focusSearch(d3_event) {
104191               var mode = context.mode() && context.mode().id;
104192               if (mode !== 'browse') return;
104193               d3_event.preventDefault();
104194               search.node().focus();
104195             }
104196
104197             function keydown(d3_event) {
104198               if (d3_event.keyCode === 27) {
104199                 // escape
104200                 search.node().blur();
104201               }
104202             }
104203
104204             function keypress(d3_event) {
104205               var q = search.property('value'),
104206                   items = list.selectAll('.feature-list-item');
104207
104208               if (d3_event.keyCode === 13 && // ↩ Return
104209               q.length && items.size()) {
104210                 click(d3_event, items.datum());
104211               }
104212             }
104213
104214             function inputevent() {
104215               _geocodeResults = undefined;
104216               drawList();
104217             }
104218
104219             function clearSearch() {
104220               search.property('value', '');
104221               drawList();
104222             }
104223
104224             function mapDrawn(e) {
104225               if (e.full) {
104226                 drawList();
104227               }
104228             }
104229
104230             function features() {
104231               var result = [];
104232               var graph = context.graph();
104233               var visibleCenter = context.map().extent().center();
104234               var q = search.property('value').toLowerCase();
104235               if (!q) return result;
104236               var locationMatch = pair_1(q.toUpperCase()) || q.match(/^(-?\d+\.?\d*)\s+(-?\d+\.?\d*)$/);
104237
104238               if (locationMatch) {
104239                 var loc = [parseFloat(locationMatch[0]), parseFloat(locationMatch[1])];
104240                 result.push({
104241                   id: -1,
104242                   geometry: 'point',
104243                   type: _t('inspector.location'),
104244                   name: dmsCoordinatePair([loc[1], loc[0]]),
104245                   location: loc
104246                 });
104247               } // A location search takes priority over an ID search
104248
104249
104250               var idMatch = !locationMatch && q.match(/(?:^|\W)(node|way|relation|[nwr])\W?0*([1-9]\d*)(?:\W|$)/i);
104251
104252               if (idMatch) {
104253                 var elemType = idMatch[1].charAt(0);
104254                 var elemId = idMatch[2];
104255                 result.push({
104256                   id: elemType + elemId,
104257                   geometry: elemType === 'n' ? 'point' : elemType === 'w' ? 'line' : 'relation',
104258                   type: elemType === 'n' ? _t('inspector.node') : elemType === 'w' ? _t('inspector.way') : _t('inspector.relation'),
104259                   name: elemId
104260                 });
104261               }
104262
104263               var allEntities = graph.entities;
104264               var localResults = [];
104265
104266               for (var id in allEntities) {
104267                 var entity = allEntities[id];
104268                 if (!entity) continue;
104269                 var name = utilDisplayName(entity) || '';
104270                 if (name.toLowerCase().indexOf(q) < 0) continue;
104271                 var matched = _mainPresetIndex.match(entity, graph);
104272                 var type = matched && matched.name() || utilDisplayType(entity.id);
104273                 var extent = entity.extent(graph);
104274                 var distance = extent ? geoSphericalDistance(visibleCenter, extent.center()) : 0;
104275                 localResults.push({
104276                   id: entity.id,
104277                   entity: entity,
104278                   geometry: entity.geometry(graph),
104279                   type: type,
104280                   name: name,
104281                   distance: distance
104282                 });
104283                 if (localResults.length > 100) break;
104284               }
104285
104286               localResults = localResults.sort(function byDistance(a, b) {
104287                 return a.distance - b.distance;
104288               });
104289               result = result.concat(localResults);
104290
104291               (_geocodeResults || []).forEach(function (d) {
104292                 if (d.osm_type && d.osm_id) {
104293                   // some results may be missing these - #1890
104294                   // Make a temporary osmEntity so we can preset match
104295                   // and better localize the search result - #4725
104296                   var id = osmEntity.id.fromOSM(d.osm_type, d.osm_id);
104297                   var tags = {};
104298                   tags[d["class"]] = d.type;
104299                   var attrs = {
104300                     id: id,
104301                     type: d.osm_type,
104302                     tags: tags
104303                   };
104304
104305                   if (d.osm_type === 'way') {
104306                     // for ways, add some fake closed nodes
104307                     attrs.nodes = ['a', 'a']; // so that geometry area is possible
104308                   }
104309
104310                   var tempEntity = osmEntity(attrs);
104311                   var tempGraph = coreGraph([tempEntity]);
104312                   var matched = _mainPresetIndex.match(tempEntity, tempGraph);
104313                   var type = matched && matched.name() || utilDisplayType(id);
104314                   result.push({
104315                     id: tempEntity.id,
104316                     geometry: tempEntity.geometry(tempGraph),
104317                     type: type,
104318                     name: d.display_name,
104319                     extent: new geoExtent([parseFloat(d.boundingbox[3]), parseFloat(d.boundingbox[0])], [parseFloat(d.boundingbox[2]), parseFloat(d.boundingbox[1])])
104320                   });
104321                 }
104322               });
104323
104324               if (q.match(/^[0-9]+$/)) {
104325                 // if query is just a number, possibly an OSM ID without a prefix
104326                 result.push({
104327                   id: 'n' + q,
104328                   geometry: 'point',
104329                   type: _t('inspector.node'),
104330                   name: q
104331                 });
104332                 result.push({
104333                   id: 'w' + q,
104334                   geometry: 'line',
104335                   type: _t('inspector.way'),
104336                   name: q
104337                 });
104338                 result.push({
104339                   id: 'r' + q,
104340                   geometry: 'relation',
104341                   type: _t('inspector.relation'),
104342                   name: q
104343                 });
104344               }
104345
104346               return result;
104347             }
104348
104349             function drawList() {
104350               var value = search.property('value');
104351               var results = features();
104352               list.classed('filtered', value.length);
104353               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'));
104354               resultsIndicator.append('span').attr('class', 'entity-name');
104355               list.selectAll('.no-results-item .entity-name').html('').call(_t.append('geocoder.no_results_worldwide'));
104356
104357               if (services.geocoder) {
104358                 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'));
104359               }
104360
104361               list.selectAll('.no-results-item').style('display', value.length && !results.length ? 'block' : 'none');
104362               list.selectAll('.geocode-item').style('display', value && _geocodeResults === undefined ? 'block' : 'none');
104363               list.selectAll('.feature-list-item').data([-1]).remove();
104364               var items = list.selectAll('.feature-list-item').data(results, function (d) {
104365                 return d.id;
104366               });
104367               var enter = items.enter().insert('button', '.geocode-item').attr('class', 'feature-list-item').on('mouseover', mouseover).on('mouseout', mouseout).on('click', click);
104368               var label = enter.append('div').attr('class', 'label');
104369               label.each(function (d) {
104370                 select(this).call(svgIcon('#iD-icon-' + d.geometry, 'pre-text'));
104371               });
104372               label.append('span').attr('class', 'entity-type').text(function (d) {
104373                 return d.type;
104374               });
104375               label.append('span').attr('class', 'entity-name').text(function (d) {
104376                 return d.name;
104377               });
104378               enter.style('opacity', 0).transition().style('opacity', 1);
104379               items.order();
104380               items.exit().remove();
104381             }
104382
104383             function mouseover(d3_event, d) {
104384               if (d.id === -1) return;
104385               utilHighlightEntities([d.id], true, context);
104386             }
104387
104388             function mouseout(d3_event, d) {
104389               if (d.id === -1) return;
104390               utilHighlightEntities([d.id], false, context);
104391             }
104392
104393             function click(d3_event, d) {
104394               d3_event.preventDefault();
104395
104396               if (d.location) {
104397                 context.map().centerZoomEase([d.location[1], d.location[0]], 19);
104398               } else if (d.entity) {
104399                 utilHighlightEntities([d.id], false, context);
104400                 context.enter(modeSelect(context, [d.entity.id]));
104401                 context.map().zoomToEase(d.entity);
104402               } else {
104403                 // download, zoom to, and select the entity with the given ID
104404                 context.zoomToEntity(d.id);
104405               }
104406             }
104407
104408             function geocoderSearch() {
104409               services.geocoder.search(search.property('value'), function (err, resp) {
104410                 _geocodeResults = resp || [];
104411                 drawList();
104412               });
104413             }
104414           }
104415
104416           return featureList;
104417         }
104418
104419         function uiImproveOsmComments() {
104420           var _qaItem;
104421
104422           function issueComments(selection) {
104423             // make the div immediately so it appears above the buttons
104424             var comments = selection.selectAll('.comments-container').data([0]);
104425             comments = comments.enter().append('div').attr('class', 'comments-container').merge(comments); // must retrieve comments from API before they can be displayed
104426
104427             services.improveOSM.getComments(_qaItem).then(function (d) {
104428               if (!d.comments) return; // nothing to do here
104429
104430               var commentEnter = comments.selectAll('.comment').data(d.comments).enter().append('div').attr('class', 'comment');
104431               commentEnter.append('div').attr('class', 'comment-avatar').call(svgIcon('#iD-icon-avatar', 'comment-avatar-icon'));
104432               var mainEnter = commentEnter.append('div').attr('class', 'comment-main');
104433               var metadataEnter = mainEnter.append('div').attr('class', 'comment-metadata');
104434               metadataEnter.append('div').attr('class', 'comment-author').each(function (d) {
104435                 var osm = services.osm;
104436                 var selection = select(this);
104437
104438                 if (osm && d.username) {
104439                   selection = selection.append('a').attr('class', 'comment-author-link').attr('href', osm.userURL(d.username)).attr('target', '_blank');
104440                 }
104441
104442                 selection.text(function (d) {
104443                   return d.username;
104444                 });
104445               });
104446               metadataEnter.append('div').attr('class', 'comment-date').html(function (d) {
104447                 return _t.html('note.status.commented', {
104448                   when: localeDateString(d.timestamp)
104449                 });
104450               });
104451               mainEnter.append('div').attr('class', 'comment-text').append('p').text(function (d) {
104452                 return d.text;
104453               });
104454             })["catch"](function (err) {
104455               console.log(err); // eslint-disable-line no-console
104456             });
104457           }
104458
104459           function localeDateString(s) {
104460             if (!s) return null;
104461             var options = {
104462               day: 'numeric',
104463               month: 'short',
104464               year: 'numeric'
104465             };
104466             var d = new Date(s * 1000); // timestamp is served in seconds, date takes ms
104467
104468             if (isNaN(d.getTime())) return null;
104469             return d.toLocaleDateString(_mainLocalizer.localeCode(), options);
104470           }
104471
104472           issueComments.issue = function (val) {
104473             if (!arguments.length) return _qaItem;
104474             _qaItem = val;
104475             return issueComments;
104476           };
104477
104478           return issueComments;
104479         }
104480
104481         function uiImproveOsmDetails(context) {
104482           var _qaItem;
104483
104484           function issueDetail(d) {
104485             if (d.desc) return d.desc;
104486             var issueKey = d.issueKey;
104487             d.replacements = d.replacements || {};
104488             d.replacements["default"] = _t.html('inspector.unknown'); // special key `default` works as a fallback string
104489
104490             return _t.html("QA.improveOSM.error_types.".concat(issueKey, ".description"), d.replacements);
104491           }
104492
104493           function improveOsmDetails(selection) {
104494             var details = selection.selectAll('.error-details').data(_qaItem ? [_qaItem] : [], function (d) {
104495               return "".concat(d.id, "-").concat(d.status || 0);
104496             });
104497             details.exit().remove();
104498             var detailsEnter = details.enter().append('div').attr('class', 'error-details qa-details-container'); // description
104499
104500             var descriptionEnter = detailsEnter.append('div').attr('class', 'qa-details-subsection');
104501             descriptionEnter.append('h4').call(_t.append('QA.keepRight.detail_description'));
104502             descriptionEnter.append('div').attr('class', 'qa-details-description-text').text(issueDetail); // If there are entity links in the error message..
104503
104504             var relatedEntities = [];
104505             descriptionEnter.selectAll('.error_entity_link, .error_object_link').attr('href', '#').each(function () {
104506               var link = select(this);
104507               var isObjectLink = link.classed('error_object_link');
104508               var entityID = isObjectLink ? utilEntityRoot(_qaItem.objectType) + _qaItem.objectId : this.textContent;
104509               var entity = context.hasEntity(entityID);
104510               relatedEntities.push(entityID); // Add click handler
104511
104512               link.on('mouseenter', function () {
104513                 utilHighlightEntities([entityID], true, context);
104514               }).on('mouseleave', function () {
104515                 utilHighlightEntities([entityID], false, context);
104516               }).on('click', function (d3_event) {
104517                 d3_event.preventDefault();
104518                 utilHighlightEntities([entityID], false, context);
104519                 var osmlayer = context.layers().layer('osm');
104520
104521                 if (!osmlayer.enabled()) {
104522                   osmlayer.enabled(true);
104523                 }
104524
104525                 context.map().centerZoom(_qaItem.loc, 20);
104526
104527                 if (entity) {
104528                   context.enter(modeSelect(context, [entityID]));
104529                 } else {
104530                   context.loadEntity(entityID, function (err, result) {
104531                     if (err) return;
104532                     var entity = result.data.find(function (e) {
104533                       return e.id === entityID;
104534                     });
104535                     if (entity) context.enter(modeSelect(context, [entityID]));
104536                   });
104537                 }
104538               }); // Replace with friendly name if possible
104539               // (The entity may not yet be loaded into the graph)
104540
104541               if (entity) {
104542                 var name = utilDisplayName(entity); // try to use common name
104543
104544                 if (!name && !isObjectLink) {
104545                   var preset = _mainPresetIndex.match(entity, context.graph());
104546                   name = preset && !preset.isFallback() && preset.name(); // fallback to preset name
104547                 }
104548
104549                 if (name) {
104550                   this.innerText = name;
104551                 }
104552               }
104553             }); // Don't hide entities related to this error - #5880
104554
104555             context.features().forceVisible(relatedEntities);
104556             context.map().pan([0, 0]); // trigger a redraw
104557           }
104558
104559           improveOsmDetails.issue = function (val) {
104560             if (!arguments.length) return _qaItem;
104561             _qaItem = val;
104562             return improveOsmDetails;
104563           };
104564
104565           return improveOsmDetails;
104566         }
104567
104568         function uiImproveOsmHeader() {
104569           var _qaItem;
104570
104571           function issueTitle(d) {
104572             var issueKey = d.issueKey;
104573             d.replacements = d.replacements || {};
104574             d.replacements["default"] = _t.html('inspector.unknown'); // special key `default` works as a fallback string
104575
104576             return _t.html("QA.improveOSM.error_types.".concat(issueKey, ".title"), d.replacements);
104577           }
104578
104579           function improveOsmHeader(selection) {
104580             var header = selection.selectAll('.qa-header').data(_qaItem ? [_qaItem] : [], function (d) {
104581               return "".concat(d.id, "-").concat(d.status || 0);
104582             });
104583             header.exit().remove();
104584             var headerEnter = header.enter().append('div').attr('class', 'qa-header');
104585             var svgEnter = headerEnter.append('div').attr('class', 'qa-header-icon').classed('new', function (d) {
104586               return d.id < 0;
104587             }).append('svg').attr('width', '20px').attr('height', '30px').attr('viewbox', '0 0 20 30').attr('class', function (d) {
104588               return "preset-icon-28 qaItem ".concat(d.service, " itemId-").concat(d.id, " itemType-").concat(d.itemType);
104589             });
104590             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');
104591             svgEnter.append('use').attr('class', 'icon-annotation').attr('width', '13px').attr('height', '13px').attr('transform', 'translate(3.5, 5)').attr('xlink:href', function (d) {
104592               var picon = d.icon;
104593
104594               if (!picon) {
104595                 return '';
104596               } else {
104597                 var isMaki = /^maki-/.test(picon);
104598                 return "#".concat(picon).concat(isMaki ? '-11' : '');
104599               }
104600             });
104601             headerEnter.append('div').attr('class', 'qa-header-label').text(issueTitle);
104602           }
104603
104604           improveOsmHeader.issue = function (val) {
104605             if (!arguments.length) return _qaItem;
104606             _qaItem = val;
104607             return improveOsmHeader;
104608           };
104609
104610           return improveOsmHeader;
104611         }
104612
104613         function uiImproveOsmEditor(context) {
104614           var dispatch = dispatch$8('change');
104615           var qaDetails = uiImproveOsmDetails(context);
104616           var qaComments = uiImproveOsmComments();
104617           var qaHeader = uiImproveOsmHeader();
104618
104619           var _qaItem;
104620
104621           function improveOsmEditor(selection) {
104622             var headerEnter = selection.selectAll('.header').data([0]).enter().append('div').attr('class', 'header fillL');
104623             headerEnter.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
104624               return context.enter(modeBrowse(context));
104625             }).call(svgIcon('#iD-icon-close'));
104626             headerEnter.append('h2').call(_t.append('QA.improveOSM.title'));
104627             var body = selection.selectAll('.body').data([0]);
104628             body = body.enter().append('div').attr('class', 'body').merge(body);
104629             var editor = body.selectAll('.qa-editor').data([0]);
104630             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);
104631           }
104632
104633           function improveOsmSaveSection(selection) {
104634             var isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
104635
104636             var isShown = _qaItem && (isSelected || _qaItem.newComment || _qaItem.comment);
104637             var saveSection = selection.selectAll('.qa-save').data(isShown ? [_qaItem] : [], function (d) {
104638               return "".concat(d.id, "-").concat(d.status || 0);
104639             }); // exit
104640
104641             saveSection.exit().remove(); // enter
104642
104643             var saveSectionEnter = saveSection.enter().append('div').attr('class', 'qa-save save-section cf');
104644             saveSectionEnter.append('h4').attr('class', '.qa-save-header').call(_t.append('note.newComment'));
104645             saveSectionEnter.append('textarea').attr('class', 'new-comment-input').attr('placeholder', _t('QA.keepRight.comment_placeholder')).attr('maxlength', 1000).property('value', function (d) {
104646               return d.newComment;
104647             }).call(utilNoAuto).on('input', changeInput).on('blur', changeInput); // update
104648
104649             saveSection = saveSectionEnter.merge(saveSection).call(qaSaveButtons);
104650
104651             function changeInput() {
104652               var input = select(this);
104653               var val = input.property('value').trim();
104654
104655               if (val === '') {
104656                 val = undefined;
104657               } // store the unsaved comment with the issue itself
104658
104659
104660               _qaItem = _qaItem.update({
104661                 newComment: val
104662               });
104663               var qaService = services.improveOSM;
104664
104665               if (qaService) {
104666                 qaService.replaceItem(_qaItem);
104667               }
104668
104669               saveSection.call(qaSaveButtons);
104670             }
104671           }
104672
104673           function qaSaveButtons(selection) {
104674             var isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
104675
104676             var buttonSection = selection.selectAll('.buttons').data(isSelected ? [_qaItem] : [], function (d) {
104677               return d.status + d.id;
104678             }); // exit
104679
104680             buttonSection.exit().remove(); // enter
104681
104682             var buttonEnter = buttonSection.enter().append('div').attr('class', 'buttons');
104683             buttonEnter.append('button').attr('class', 'button comment-button action').call(_t.append('QA.keepRight.save_comment'));
104684             buttonEnter.append('button').attr('class', 'button close-button action');
104685             buttonEnter.append('button').attr('class', 'button ignore-button action'); // update
104686
104687             buttonSection = buttonSection.merge(buttonEnter);
104688             buttonSection.select('.comment-button').attr('disabled', function (d) {
104689               return d.newComment ? null : true;
104690             }).on('click.comment', function (d3_event, d) {
104691               this.blur(); // avoid keeping focus on the button - #4641
104692
104693               var qaService = services.improveOSM;
104694
104695               if (qaService) {
104696                 qaService.postUpdate(d, function (err, item) {
104697                   return dispatch.call('change', item);
104698                 });
104699               }
104700             });
104701             buttonSection.select('.close-button').html(function (d) {
104702               var andComment = d.newComment ? '_comment' : '';
104703               return _t.html("QA.keepRight.close".concat(andComment));
104704             }).on('click.close', function (d3_event, d) {
104705               this.blur(); // avoid keeping focus on the button - #4641
104706
104707               var qaService = services.improveOSM;
104708
104709               if (qaService) {
104710                 d.newStatus = 'SOLVED';
104711                 qaService.postUpdate(d, function (err, item) {
104712                   return dispatch.call('change', item);
104713                 });
104714               }
104715             });
104716             buttonSection.select('.ignore-button').html(function (d) {
104717               var andComment = d.newComment ? '_comment' : '';
104718               return _t.html("QA.keepRight.ignore".concat(andComment));
104719             }).on('click.ignore', function (d3_event, d) {
104720               this.blur(); // avoid keeping focus on the button - #4641
104721
104722               var qaService = services.improveOSM;
104723
104724               if (qaService) {
104725                 d.newStatus = 'INVALID';
104726                 qaService.postUpdate(d, function (err, item) {
104727                   return dispatch.call('change', item);
104728                 });
104729               }
104730             });
104731           } // NOTE: Don't change method name until UI v3 is merged
104732
104733
104734           improveOsmEditor.error = function (val) {
104735             if (!arguments.length) return _qaItem;
104736             _qaItem = val;
104737             return improveOsmEditor;
104738           };
104739
104740           return utilRebind(improveOsmEditor, dispatch, 'on');
104741         }
104742
104743         function uiPresetList(context) {
104744           var dispatch = dispatch$8('cancel', 'choose');
104745
104746           var _entityIDs;
104747
104748           var _currLoc;
104749
104750           var _currentPresets;
104751
104752           var _autofocus = false;
104753
104754           function presetList(selection) {
104755             if (!_entityIDs) return;
104756             var presets = _mainPresetIndex.matchAllGeometry(entityGeometries());
104757             selection.html('');
104758             var messagewrap = selection.append('div').attr('class', 'header fillL');
104759             var message = messagewrap.append('h2').call(_t.append('inspector.choose'));
104760             var direction = _mainLocalizer.textDirection() === 'rtl' ? 'backward' : 'forward';
104761             messagewrap.append('button').attr('class', 'preset-choose').attr('title', direction).on('click', function () {
104762               dispatch.call('cancel', this);
104763             }).call(svgIcon("#iD-icon-".concat(direction)));
104764
104765             function initialKeydown(d3_event) {
104766               // hack to let delete shortcut work when search is autofocused
104767               if (search.property('value').length === 0 && (d3_event.keyCode === utilKeybinding.keyCodes['⌫'] || d3_event.keyCode === utilKeybinding.keyCodes['⌦'])) {
104768                 d3_event.preventDefault();
104769                 d3_event.stopPropagation();
104770                 operationDelete(context, _entityIDs)(); // hack to let undo work when search is autofocused
104771               } else if (search.property('value').length === 0 && (d3_event.ctrlKey || d3_event.metaKey) && d3_event.keyCode === utilKeybinding.keyCodes.z) {
104772                 d3_event.preventDefault();
104773                 d3_event.stopPropagation();
104774                 context.undo();
104775               } else if (!d3_event.ctrlKey && !d3_event.metaKey) {
104776                 // don't check for delete/undo hack on future keydown events
104777                 select(this).on('keydown', keydown);
104778                 keydown.call(this, d3_event);
104779               }
104780             }
104781
104782             function keydown(d3_event) {
104783               // down arrow
104784               if (d3_event.keyCode === utilKeybinding.keyCodes['↓'] && // if insertion point is at the end of the string
104785               search.node().selectionStart === search.property('value').length) {
104786                 d3_event.preventDefault();
104787                 d3_event.stopPropagation(); // move focus to the first item in the preset list
104788
104789                 var buttons = list.selectAll('.preset-list-button');
104790                 if (!buttons.empty()) buttons.nodes()[0].focus();
104791               }
104792             }
104793
104794             function keypress(d3_event) {
104795               // enter
104796               var value = search.property('value');
104797
104798               if (d3_event.keyCode === 13 && // ↩ Return
104799               value.length) {
104800                 list.selectAll('.preset-list-item:first-child').each(function (d) {
104801                   d.choose.call(this);
104802                 });
104803               }
104804             }
104805
104806             function inputevent() {
104807               var value = search.property('value');
104808               list.classed('filtered', value.length);
104809               var results, messageText;
104810
104811               if (value.length) {
104812                 results = presets.search(value, entityGeometries()[0], _currLoc);
104813                 messageText = _t.html('inspector.results', {
104814                   n: results.collection.length,
104815                   search: value
104816                 });
104817               } else {
104818                 results = _mainPresetIndex.defaults(entityGeometries()[0], 36, !context.inIntro(), _currLoc);
104819                 messageText = _t.html('inspector.choose');
104820               }
104821
104822               list.call(drawList, results);
104823               message.html(messageText);
104824             }
104825
104826             var searchWrap = selection.append('div').attr('class', 'search-header');
104827             searchWrap.call(svgIcon('#iD-icon-search', 'pre-text'));
104828             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));
104829
104830             if (_autofocus) {
104831               search.node().focus(); // Safari 14 doesn't always like to focus immediately,
104832               // so try again on the next pass
104833
104834               setTimeout(function () {
104835                 search.node().focus();
104836               }, 0);
104837             }
104838
104839             var listWrap = selection.append('div').attr('class', 'inspector-body');
104840             var list = listWrap.append('div').attr('class', 'preset-list').call(drawList, _mainPresetIndex.defaults(entityGeometries()[0], 36, !context.inIntro(), _currLoc));
104841             context.features().on('change.preset-list', updateForFeatureHiddenState);
104842           }
104843
104844           function drawList(list, presets) {
104845             presets = presets.matchAllGeometry(entityGeometries());
104846             var collection = presets.collection.reduce(function (collection, preset) {
104847               if (!preset) return collection;
104848
104849               if (preset.members) {
104850                 if (preset.members.collection.filter(function (preset) {
104851                   return preset.addable();
104852                 }).length > 1) {
104853                   collection.push(CategoryItem(preset));
104854                 }
104855               } else if (preset.addable()) {
104856                 collection.push(PresetItem(preset));
104857               }
104858
104859               return collection;
104860             }, []);
104861             var items = list.selectAll('.preset-list-item').data(collection, function (d) {
104862               return d.preset.id;
104863             });
104864             items.order();
104865             items.exit().remove();
104866             items.enter().append('div').attr('class', function (item) {
104867               return 'preset-list-item preset-' + item.preset.id.replace('/', '-');
104868             }).classed('current', function (item) {
104869               return _currentPresets.indexOf(item.preset) !== -1;
104870             }).each(function (item) {
104871               select(this).call(item);
104872             }).style('opacity', 0).transition().style('opacity', 1);
104873             updateForFeatureHiddenState();
104874           }
104875
104876           function itemKeydown(d3_event) {
104877             // the actively focused item
104878             var item = select(this.closest('.preset-list-item'));
104879             var parentItem = select(item.node().parentNode.closest('.preset-list-item')); // arrow down, move focus to the next, lower item
104880
104881             if (d3_event.keyCode === utilKeybinding.keyCodes['↓']) {
104882               d3_event.preventDefault();
104883               d3_event.stopPropagation(); // the next item in the list at the same level
104884
104885               var nextItem = select(item.node().nextElementSibling); // if there is no next item in this list
104886
104887               if (nextItem.empty()) {
104888                 // if there is a parent item
104889                 if (!parentItem.empty()) {
104890                   // the item is the last item of a sublist,
104891                   // select the next item at the parent level
104892                   nextItem = select(parentItem.node().nextElementSibling);
104893                 } // if the focused item is expanded
104894
104895               } else if (select(this).classed('expanded')) {
104896                 // select the first subitem instead
104897                 nextItem = item.select('.subgrid .preset-list-item:first-child');
104898               }
104899
104900               if (!nextItem.empty()) {
104901                 // focus on the next item
104902                 nextItem.select('.preset-list-button').node().focus();
104903               } // arrow up, move focus to the previous, higher item
104904
104905             } else if (d3_event.keyCode === utilKeybinding.keyCodes['↑']) {
104906               d3_event.preventDefault();
104907               d3_event.stopPropagation(); // the previous item in the list at the same level
104908
104909               var previousItem = select(item.node().previousElementSibling); // if there is no previous item in this list
104910
104911               if (previousItem.empty()) {
104912                 // if there is a parent item
104913                 if (!parentItem.empty()) {
104914                   // the item is the first subitem of a sublist select the parent item
104915                   previousItem = parentItem;
104916                 } // if the previous item is expanded
104917
104918               } else if (previousItem.select('.preset-list-button').classed('expanded')) {
104919                 // select the last subitem of the sublist of the previous item
104920                 previousItem = previousItem.select('.subgrid .preset-list-item:last-child');
104921               }
104922
104923               if (!previousItem.empty()) {
104924                 // focus on the previous item
104925                 previousItem.select('.preset-list-button').node().focus();
104926               } else {
104927                 // the focus is at the top of the list, move focus back to the search field
104928                 var search = select(this.closest('.preset-list-pane')).select('.preset-search-input');
104929                 search.node().focus();
104930               } // arrow left, move focus to the parent item if there is one
104931
104932             } else if (d3_event.keyCode === utilKeybinding.keyCodes[_mainLocalizer.textDirection() === 'rtl' ? '→' : '←']) {
104933               d3_event.preventDefault();
104934               d3_event.stopPropagation(); // if there is a parent item, focus on the parent item
104935
104936               if (!parentItem.empty()) {
104937                 parentItem.select('.preset-list-button').node().focus();
104938               } // arrow right, choose this item
104939
104940             } else if (d3_event.keyCode === utilKeybinding.keyCodes[_mainLocalizer.textDirection() === 'rtl' ? '←' : '→']) {
104941               d3_event.preventDefault();
104942               d3_event.stopPropagation();
104943               item.datum().choose.call(select(this).node());
104944             }
104945           }
104946
104947           function CategoryItem(preset) {
104948             var box,
104949                 sublist,
104950                 shown = false;
104951
104952             function item(selection) {
104953               var wrap = selection.append('div').attr('class', 'preset-list-button-wrap category');
104954
104955               function click() {
104956                 var isExpanded = select(this).classed('expanded');
104957                 var iconName = isExpanded ? _mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-backward' : '#iD-icon-forward' : '#iD-icon-down';
104958                 select(this).classed('expanded', !isExpanded).attr('title', !isExpanded ? _t('icons.collapse') : _t('icons.expand'));
104959                 select(this).selectAll('div.label-inner svg.icon use').attr('href', iconName);
104960                 item.choose();
104961               }
104962
104963               var geometries = entityGeometries();
104964               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) {
104965                 // right arrow, expand the focused item
104966                 if (d3_event.keyCode === utilKeybinding.keyCodes[_mainLocalizer.textDirection() === 'rtl' ? '←' : '→']) {
104967                   d3_event.preventDefault();
104968                   d3_event.stopPropagation(); // if the item isn't expanded
104969
104970                   if (!select(this).classed('expanded')) {
104971                     // toggle expansion (expand the item)
104972                     click.call(this, d3_event);
104973                   } // left arrow, collapse the focused item
104974
104975                 } else if (d3_event.keyCode === utilKeybinding.keyCodes[_mainLocalizer.textDirection() === 'rtl' ? '→' : '←']) {
104976                   d3_event.preventDefault();
104977                   d3_event.stopPropagation(); // if the item is expanded
104978
104979                   if (select(this).classed('expanded')) {
104980                     // toggle expansion (collapse the item)
104981                     click.call(this, d3_event);
104982                   }
104983                 } else {
104984                   itemKeydown.call(this, d3_event);
104985                 }
104986               });
104987               var label = button.append('div').attr('class', 'label').append('div').attr('class', 'label-inner');
104988               label.append('div').attr('class', 'namepart').call(svgIcon(_mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-backward' : '#iD-icon-forward', 'inline')).append('span').html(function () {
104989                 return preset.nameLabel() + '&hellip;';
104990               });
104991               box = selection.append('div').attr('class', 'subgrid').style('max-height', '0px').style('opacity', 0);
104992               box.append('div').attr('class', 'arrow');
104993               sublist = box.append('div').attr('class', 'preset-list fillL3');
104994             }
104995
104996             item.choose = function () {
104997               if (!box || !sublist) return;
104998
104999               if (shown) {
105000                 shown = false;
105001                 box.transition().duration(200).style('opacity', '0').style('max-height', '0px').style('padding-bottom', '0px');
105002               } else {
105003                 shown = true;
105004                 var members = preset.members.matchAllGeometry(entityGeometries());
105005                 sublist.call(drawList, members);
105006                 box.transition().duration(200).style('opacity', '1').style('max-height', 200 + members.collection.length * 190 + 'px').style('padding-bottom', '10px');
105007               }
105008             };
105009
105010             item.preset = preset;
105011             return item;
105012           }
105013
105014           function PresetItem(preset) {
105015             function item(selection) {
105016               var wrap = selection.append('div').attr('class', 'preset-list-button-wrap');
105017               var geometries = entityGeometries();
105018               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);
105019               var label = button.append('div').attr('class', 'label').append('div').attr('class', 'label-inner');
105020               var nameparts = [preset.nameLabel(), preset.subtitleLabel()].filter(Boolean);
105021               label.selectAll('.namepart').data(nameparts).enter().append('div').attr('class', 'namepart').html(function (d) {
105022                 return d;
105023               });
105024               wrap.call(item.reference.button);
105025               selection.call(item.reference.body);
105026             }
105027
105028             item.choose = function () {
105029               if (select(this).classed('disabled')) return;
105030
105031               if (!context.inIntro()) {
105032                 _mainPresetIndex.setMostRecent(preset, entityGeometries()[0]);
105033               }
105034
105035               context.perform(function (graph) {
105036                 for (var i in _entityIDs) {
105037                   var entityID = _entityIDs[i];
105038                   var oldPreset = _mainPresetIndex.match(graph.entity(entityID), graph);
105039                   graph = actionChangePreset(entityID, oldPreset, preset)(graph);
105040                 }
105041
105042                 return graph;
105043               }, _t('operations.change_tags.annotation'));
105044               context.validator().validate(); // rerun validation
105045
105046               dispatch.call('choose', this, preset);
105047             };
105048
105049             item.help = function (d3_event) {
105050               d3_event.stopPropagation();
105051               item.reference.toggle();
105052             };
105053
105054             item.preset = preset;
105055             item.reference = uiTagReference(preset.reference());
105056             return item;
105057           }
105058
105059           function updateForFeatureHiddenState() {
105060             if (!_entityIDs.every(context.hasEntity)) return;
105061             var geometries = entityGeometries();
105062             var button = context.container().selectAll('.preset-list .preset-list-button'); // remove existing tooltips
105063
105064             button.call(uiTooltip().destroyAny);
105065             button.each(function (item, index) {
105066               var hiddenPresetFeaturesId;
105067
105068               for (var i in geometries) {
105069                 hiddenPresetFeaturesId = context.features().isHiddenPreset(item.preset, geometries[i]);
105070                 if (hiddenPresetFeaturesId) break;
105071               }
105072
105073               var isHiddenPreset = !context.inIntro() && !!hiddenPresetFeaturesId && (_currentPresets.length !== 1 || item.preset !== _currentPresets[0]);
105074               select(this).classed('disabled', isHiddenPreset);
105075
105076               if (isHiddenPreset) {
105077                 var isAutoHidden = context.features().autoHidden(hiddenPresetFeaturesId);
105078                 select(this).call(uiTooltip().title(_t.html('inspector.hidden_preset.' + (isAutoHidden ? 'zoom' : 'manual'), {
105079                   features: {
105080                     html: _t.html('feature.' + hiddenPresetFeaturesId + '.description')
105081                   }
105082                 })).placement(index < 2 ? 'bottom' : 'top'));
105083               }
105084             });
105085           }
105086
105087           presetList.autofocus = function (val) {
105088             if (!arguments.length) return _autofocus;
105089             _autofocus = val;
105090             return presetList;
105091           };
105092
105093           presetList.entityIDs = function (val) {
105094             if (!arguments.length) return _entityIDs;
105095             _entityIDs = val;
105096             _currLoc = null;
105097
105098             if (_entityIDs && _entityIDs.length) {
105099               // calculate current location
105100               var extent = _entityIDs.reduce(function (extent, entityID) {
105101                 var entity = context.graph().entity(entityID);
105102                 return extent.extend(entity.extent(context.graph()));
105103               }, geoExtent());
105104
105105               _currLoc = extent.center(); // match presets
105106
105107               var presets = _entityIDs.map(function (entityID) {
105108                 return _mainPresetIndex.match(context.entity(entityID), context.graph());
105109               });
105110
105111               presetList.presets(presets);
105112             }
105113
105114             return presetList;
105115           };
105116
105117           presetList.presets = function (val) {
105118             if (!arguments.length) return _currentPresets;
105119             _currentPresets = val;
105120             return presetList;
105121           };
105122
105123           function entityGeometries() {
105124             var counts = {};
105125
105126             for (var i in _entityIDs) {
105127               var entityID = _entityIDs[i];
105128               var entity = context.entity(entityID);
105129               var geometry = entity.geometry(context.graph()); // Treat entities on addr:interpolation lines as points, not vertices (#3241)
105130
105131               if (geometry === 'vertex' && entity.isOnAddressLine(context.graph())) {
105132                 geometry = 'point';
105133               }
105134
105135               if (!counts[geometry]) counts[geometry] = 0;
105136               counts[geometry] += 1;
105137             }
105138
105139             return Object.keys(counts).sort(function (geom1, geom2) {
105140               return counts[geom2] - counts[geom1];
105141             });
105142           }
105143
105144           return utilRebind(presetList, dispatch, 'on');
105145         }
105146
105147         function uiViewOnOSM(context) {
105148           var _what; // an osmEntity or osmNote
105149
105150
105151           function viewOnOSM(selection) {
105152             var url;
105153
105154             if (_what instanceof osmEntity) {
105155               url = context.connection().entityURL(_what);
105156             } else if (_what instanceof osmNote) {
105157               url = context.connection().noteURL(_what);
105158             }
105159
105160             var data = !_what || _what.isNew() ? [] : [_what];
105161             var link = selection.selectAll('.view-on-osm').data(data, function (d) {
105162               return d.id;
105163             }); // exit
105164
105165             link.exit().remove(); // enter
105166
105167             var linkEnter = link.enter().append('a').attr('class', 'view-on-osm').attr('target', '_blank').attr('href', url).call(svgIcon('#iD-icon-out-link', 'inline'));
105168             linkEnter.append('span').call(_t.append('inspector.view_on_osm'));
105169           }
105170
105171           viewOnOSM.what = function (_) {
105172             if (!arguments.length) return _what;
105173             _what = _;
105174             return viewOnOSM;
105175           };
105176
105177           return viewOnOSM;
105178         }
105179
105180         function uiInspector(context) {
105181           var presetList = uiPresetList(context);
105182           var entityEditor = uiEntityEditor(context);
105183           var wrap = select(null),
105184               presetPane = select(null),
105185               editorPane = select(null);
105186           var _state = 'select';
105187
105188           var _entityIDs;
105189
105190           var _newFeature = false;
105191
105192           function inspector(selection) {
105193             presetList.entityIDs(_entityIDs).autofocus(_newFeature).on('choose', inspector.setPreset).on('cancel', function () {
105194               inspector.setPreset();
105195             });
105196             entityEditor.state(_state).entityIDs(_entityIDs).on('choose', inspector.showList);
105197             wrap = selection.selectAll('.panewrap').data([0]);
105198             var enter = wrap.enter().append('div').attr('class', 'panewrap');
105199             enter.append('div').attr('class', 'preset-list-pane pane');
105200             enter.append('div').attr('class', 'entity-editor-pane pane');
105201             wrap = wrap.merge(enter);
105202             presetPane = wrap.selectAll('.preset-list-pane');
105203             editorPane = wrap.selectAll('.entity-editor-pane');
105204
105205             function shouldDefaultToPresetList() {
105206               // always show the inspector on hover
105207               if (_state !== 'select') return false; // can only change preset on single selection
105208
105209               if (_entityIDs.length !== 1) return false;
105210               var entityID = _entityIDs[0];
105211               var entity = context.hasEntity(entityID);
105212               if (!entity) return false; // default to inspector if there are already tags
105213
105214               if (entity.hasNonGeometryTags()) return false; // prompt to select preset if feature is new and untagged
105215
105216               if (_newFeature) return true; // all existing features except vertices should default to inspector
105217
105218               if (entity.geometry(context.graph()) !== 'vertex') return false; // show vertex relations if any
105219
105220               if (context.graph().parentRelations(entity).length) return false; // show vertex issues if there are any
105221
105222               if (context.validator().getEntityIssues(entityID).length) return false; // show turn retriction editor for junction vertices
105223
105224               if (entity.isHighwayIntersection(context.graph())) return false; // otherwise show preset list for uninteresting vertices
105225
105226               return true;
105227             }
105228
105229             if (shouldDefaultToPresetList()) {
105230               wrap.style('right', '-100%');
105231               editorPane.classed('hide', true);
105232               presetPane.classed('hide', false).call(presetList);
105233             } else {
105234               wrap.style('right', '0%');
105235               presetPane.classed('hide', true);
105236               editorPane.classed('hide', false).call(entityEditor);
105237             }
105238
105239             var footer = selection.selectAll('.footer').data([0]);
105240             footer = footer.enter().append('div').attr('class', 'footer').merge(footer);
105241             footer.call(uiViewOnOSM(context).what(context.hasEntity(_entityIDs.length === 1 && _entityIDs[0])));
105242           }
105243
105244           inspector.showList = function (presets) {
105245             presetPane.classed('hide', false);
105246             wrap.transition().styleTween('right', function () {
105247               return interpolate$1('0%', '-100%');
105248             }).on('end', function () {
105249               editorPane.classed('hide', true);
105250             });
105251
105252             if (presets) {
105253               presetList.presets(presets);
105254             }
105255
105256             presetPane.call(presetList.autofocus(true));
105257           };
105258
105259           inspector.setPreset = function (preset) {
105260             // upon setting multipolygon, go to the area preset list instead of the editor
105261             if (preset && preset.id === 'type/multipolygon') {
105262               presetPane.call(presetList.autofocus(true));
105263             } else {
105264               editorPane.classed('hide', false);
105265               wrap.transition().styleTween('right', function () {
105266                 return interpolate$1('-100%', '0%');
105267               }).on('end', function () {
105268                 presetPane.classed('hide', true);
105269               });
105270
105271               if (preset) {
105272                 entityEditor.presets([preset]);
105273               }
105274
105275               editorPane.call(entityEditor);
105276             }
105277           };
105278
105279           inspector.state = function (val) {
105280             if (!arguments.length) return _state;
105281             _state = val;
105282             entityEditor.state(_state); // remove any old field help overlay that might have gotten attached to the inspector
105283
105284             context.container().selectAll('.field-help-body').remove();
105285             return inspector;
105286           };
105287
105288           inspector.entityIDs = function (val) {
105289             if (!arguments.length) return _entityIDs;
105290             _entityIDs = val;
105291             return inspector;
105292           };
105293
105294           inspector.newFeature = function (val) {
105295             if (!arguments.length) return _newFeature;
105296             _newFeature = val;
105297             return inspector;
105298           };
105299
105300           return inspector;
105301         }
105302
105303         function uiKeepRightDetails(context) {
105304           var _qaItem;
105305
105306           function issueDetail(d) {
105307             var itemType = d.itemType,
105308                 parentIssueType = d.parentIssueType;
105309             var unknown = _t.html('inspector.unknown');
105310             var replacements = d.replacements || {};
105311             replacements["default"] = unknown; // special key `default` works as a fallback string
105312
105313             var detail = _t.html("QA.keepRight.errorTypes.".concat(itemType, ".description"), replacements);
105314
105315             if (detail === unknown) {
105316               detail = _t.html("QA.keepRight.errorTypes.".concat(parentIssueType, ".description"), replacements);
105317             }
105318
105319             return detail;
105320           }
105321
105322           function keepRightDetails(selection) {
105323             var details = selection.selectAll('.error-details').data(_qaItem ? [_qaItem] : [], function (d) {
105324               return "".concat(d.id, "-").concat(d.status || 0);
105325             });
105326             details.exit().remove();
105327             var detailsEnter = details.enter().append('div').attr('class', 'error-details qa-details-container'); // description
105328
105329             var descriptionEnter = detailsEnter.append('div').attr('class', 'qa-details-subsection');
105330             descriptionEnter.append('h4').call(_t.append('QA.keepRight.detail_description'));
105331             descriptionEnter.append('div').attr('class', 'qa-details-description-text').html(issueDetail); // If there are entity links in the error message..
105332
105333             var relatedEntities = [];
105334             descriptionEnter.selectAll('.error_entity_link, .error_object_link').attr('href', '#').each(function () {
105335               var link = select(this);
105336               var isObjectLink = link.classed('error_object_link');
105337               var entityID = isObjectLink ? utilEntityRoot(_qaItem.objectType) + _qaItem.objectId : this.textContent;
105338               var entity = context.hasEntity(entityID);
105339               relatedEntities.push(entityID); // Add click handler
105340
105341               link.on('mouseenter', function () {
105342                 utilHighlightEntities([entityID], true, context);
105343               }).on('mouseleave', function () {
105344                 utilHighlightEntities([entityID], false, context);
105345               }).on('click', function (d3_event) {
105346                 d3_event.preventDefault();
105347                 utilHighlightEntities([entityID], false, context);
105348                 var osmlayer = context.layers().layer('osm');
105349
105350                 if (!osmlayer.enabled()) {
105351                   osmlayer.enabled(true);
105352                 }
105353
105354                 context.map().centerZoomEase(_qaItem.loc, 20);
105355
105356                 if (entity) {
105357                   context.enter(modeSelect(context, [entityID]));
105358                 } else {
105359                   context.loadEntity(entityID, function (err, result) {
105360                     if (err) return;
105361                     var entity = result.data.find(function (e) {
105362                       return e.id === entityID;
105363                     });
105364                     if (entity) context.enter(modeSelect(context, [entityID]));
105365                   });
105366                 }
105367               }); // Replace with friendly name if possible
105368               // (The entity may not yet be loaded into the graph)
105369
105370               if (entity) {
105371                 var name = utilDisplayName(entity); // try to use common name
105372
105373                 if (!name && !isObjectLink) {
105374                   var preset = _mainPresetIndex.match(entity, context.graph());
105375                   name = preset && !preset.isFallback() && preset.name(); // fallback to preset name
105376                 }
105377
105378                 if (name) {
105379                   this.innerText = name;
105380                 }
105381               }
105382             }); // Don't hide entities related to this issue - #5880
105383
105384             context.features().forceVisible(relatedEntities);
105385             context.map().pan([0, 0]); // trigger a redraw
105386           }
105387
105388           keepRightDetails.issue = function (val) {
105389             if (!arguments.length) return _qaItem;
105390             _qaItem = val;
105391             return keepRightDetails;
105392           };
105393
105394           return keepRightDetails;
105395         }
105396
105397         function uiKeepRightHeader() {
105398           var _qaItem;
105399
105400           function issueTitle(d) {
105401             var itemType = d.itemType,
105402                 parentIssueType = d.parentIssueType;
105403             var unknown = _t.html('inspector.unknown');
105404             var replacements = d.replacements || {};
105405             replacements["default"] = unknown; // special key `default` works as a fallback string
105406
105407             var title = _t.html("QA.keepRight.errorTypes.".concat(itemType, ".title"), replacements);
105408
105409             if (title === unknown) {
105410               title = _t.html("QA.keepRight.errorTypes.".concat(parentIssueType, ".title"), replacements);
105411             }
105412
105413             return title;
105414           }
105415
105416           function keepRightHeader(selection) {
105417             var header = selection.selectAll('.qa-header').data(_qaItem ? [_qaItem] : [], function (d) {
105418               return "".concat(d.id, "-").concat(d.status || 0);
105419             });
105420             header.exit().remove();
105421             var headerEnter = header.enter().append('div').attr('class', 'qa-header');
105422             var iconEnter = headerEnter.append('div').attr('class', 'qa-header-icon').classed('new', function (d) {
105423               return d.id < 0;
105424             });
105425             iconEnter.append('div').attr('class', function (d) {
105426               return "preset-icon-28 qaItem ".concat(d.service, " itemId-").concat(d.id, " itemType-").concat(d.parentIssueType);
105427             }).call(svgIcon('#iD-icon-bolt', 'qaItem-fill'));
105428             headerEnter.append('div').attr('class', 'qa-header-label').html(issueTitle);
105429           }
105430
105431           keepRightHeader.issue = function (val) {
105432             if (!arguments.length) return _qaItem;
105433             _qaItem = val;
105434             return keepRightHeader;
105435           };
105436
105437           return keepRightHeader;
105438         }
105439
105440         function uiViewOnKeepRight() {
105441           var _qaItem;
105442
105443           function viewOnKeepRight(selection) {
105444             var url;
105445
105446             if (services.keepRight && _qaItem instanceof QAItem) {
105447               url = services.keepRight.issueURL(_qaItem);
105448             }
105449
105450             var link = selection.selectAll('.view-on-keepRight').data(url ? [url] : []); // exit
105451
105452             link.exit().remove(); // enter
105453
105454             var linkEnter = link.enter().append('a').attr('class', 'view-on-keepRight').attr('target', '_blank').attr('rel', 'noopener') // security measure
105455             .attr('href', function (d) {
105456               return d;
105457             }).call(svgIcon('#iD-icon-out-link', 'inline'));
105458             linkEnter.append('span').call(_t.append('inspector.view_on_keepRight'));
105459           }
105460
105461           viewOnKeepRight.what = function (val) {
105462             if (!arguments.length) return _qaItem;
105463             _qaItem = val;
105464             return viewOnKeepRight;
105465           };
105466
105467           return viewOnKeepRight;
105468         }
105469
105470         function uiKeepRightEditor(context) {
105471           var dispatch = dispatch$8('change');
105472           var qaDetails = uiKeepRightDetails(context);
105473           var qaHeader = uiKeepRightHeader();
105474
105475           var _qaItem;
105476
105477           function keepRightEditor(selection) {
105478             var headerEnter = selection.selectAll('.header').data([0]).enter().append('div').attr('class', 'header fillL');
105479             headerEnter.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
105480               return context.enter(modeBrowse(context));
105481             }).call(svgIcon('#iD-icon-close'));
105482             headerEnter.append('h2').call(_t.append('QA.keepRight.title'));
105483             var body = selection.selectAll('.body').data([0]);
105484             body = body.enter().append('div').attr('class', 'body').merge(body);
105485             var editor = body.selectAll('.qa-editor').data([0]);
105486             editor.enter().append('div').attr('class', 'modal-section qa-editor').merge(editor).call(qaHeader.issue(_qaItem)).call(qaDetails.issue(_qaItem)).call(keepRightSaveSection);
105487             var footer = selection.selectAll('.footer').data([0]);
105488             footer.enter().append('div').attr('class', 'footer').merge(footer).call(uiViewOnKeepRight().what(_qaItem));
105489           }
105490
105491           function keepRightSaveSection(selection) {
105492             var isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
105493
105494             var isShown = _qaItem && (isSelected || _qaItem.newComment || _qaItem.comment);
105495             var saveSection = selection.selectAll('.qa-save').data(isShown ? [_qaItem] : [], function (d) {
105496               return "".concat(d.id, "-").concat(d.status || 0);
105497             }); // exit
105498
105499             saveSection.exit().remove(); // enter
105500
105501             var saveSectionEnter = saveSection.enter().append('div').attr('class', 'qa-save save-section cf');
105502             saveSectionEnter.append('h4').attr('class', '.qa-save-header').call(_t.append('QA.keepRight.comment'));
105503             saveSectionEnter.append('textarea').attr('class', 'new-comment-input').attr('placeholder', _t('QA.keepRight.comment_placeholder')).attr('maxlength', 1000).property('value', function (d) {
105504               return d.newComment || d.comment;
105505             }).call(utilNoAuto).on('input', changeInput).on('blur', changeInput); // update
105506
105507             saveSection = saveSectionEnter.merge(saveSection).call(qaSaveButtons);
105508
105509             function changeInput() {
105510               var input = select(this);
105511               var val = input.property('value').trim();
105512
105513               if (val === _qaItem.comment) {
105514                 val = undefined;
105515               } // store the unsaved comment with the issue itself
105516
105517
105518               _qaItem = _qaItem.update({
105519                 newComment: val
105520               });
105521               var qaService = services.keepRight;
105522
105523               if (qaService) {
105524                 qaService.replaceItem(_qaItem); // update keepright cache
105525               }
105526
105527               saveSection.call(qaSaveButtons);
105528             }
105529           }
105530
105531           function qaSaveButtons(selection) {
105532             var isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
105533
105534             var buttonSection = selection.selectAll('.buttons').data(isSelected ? [_qaItem] : [], function (d) {
105535               return d.status + d.id;
105536             }); // exit
105537
105538             buttonSection.exit().remove(); // enter
105539
105540             var buttonEnter = buttonSection.enter().append('div').attr('class', 'buttons');
105541             buttonEnter.append('button').attr('class', 'button comment-button action').call(_t.append('QA.keepRight.save_comment'));
105542             buttonEnter.append('button').attr('class', 'button close-button action');
105543             buttonEnter.append('button').attr('class', 'button ignore-button action'); // update
105544
105545             buttonSection = buttonSection.merge(buttonEnter);
105546             buttonSection.select('.comment-button') // select and propagate data
105547             .attr('disabled', function (d) {
105548               return d.newComment ? null : true;
105549             }).on('click.comment', function (d3_event, d) {
105550               this.blur(); // avoid keeping focus on the button - #4641
105551
105552               var qaService = services.keepRight;
105553
105554               if (qaService) {
105555                 qaService.postUpdate(d, function (err, item) {
105556                   return dispatch.call('change', item);
105557                 });
105558               }
105559             });
105560             buttonSection.select('.close-button') // select and propagate data
105561             .html(function (d) {
105562               var andComment = d.newComment ? '_comment' : '';
105563               return _t.html("QA.keepRight.close".concat(andComment));
105564             }).on('click.close', function (d3_event, d) {
105565               this.blur(); // avoid keeping focus on the button - #4641
105566
105567               var qaService = services.keepRight;
105568
105569               if (qaService) {
105570                 d.newStatus = 'ignore_t'; // ignore temporarily (item fixed)
105571
105572                 qaService.postUpdate(d, function (err, item) {
105573                   return dispatch.call('change', item);
105574                 });
105575               }
105576             });
105577             buttonSection.select('.ignore-button') // select and propagate data
105578             .html(function (d) {
105579               var andComment = d.newComment ? '_comment' : '';
105580               return _t.html("QA.keepRight.ignore".concat(andComment));
105581             }).on('click.ignore', function (d3_event, d) {
105582               this.blur(); // avoid keeping focus on the button - #4641
105583
105584               var qaService = services.keepRight;
105585
105586               if (qaService) {
105587                 d.newStatus = 'ignore'; // ignore permanently (false positive)
105588
105589                 qaService.postUpdate(d, function (err, item) {
105590                   return dispatch.call('change', item);
105591                 });
105592               }
105593             });
105594           } // NOTE: Don't change method name until UI v3 is merged
105595
105596
105597           keepRightEditor.error = function (val) {
105598             if (!arguments.length) return _qaItem;
105599             _qaItem = val;
105600             return keepRightEditor;
105601           };
105602
105603           return utilRebind(keepRightEditor, dispatch, 'on');
105604         }
105605
105606         function uiLasso(context) {
105607           var group, polygon;
105608           lasso.coordinates = [];
105609
105610           function lasso(selection) {
105611             context.container().classed('lasso', true);
105612             group = selection.append('g').attr('class', 'lasso hide');
105613             polygon = group.append('path').attr('class', 'lasso-path');
105614             group.call(uiToggle(true));
105615           }
105616
105617           function draw() {
105618             if (polygon) {
105619               polygon.data([lasso.coordinates]).attr('d', function (d) {
105620                 return 'M' + d.join(' L') + ' Z';
105621               });
105622             }
105623           }
105624
105625           lasso.extent = function () {
105626             return lasso.coordinates.reduce(function (extent, point) {
105627               return extent.extend(geoExtent(point));
105628             }, geoExtent());
105629           };
105630
105631           lasso.p = function (_) {
105632             if (!arguments.length) return lasso;
105633             lasso.coordinates.push(_);
105634             draw();
105635             return lasso;
105636           };
105637
105638           lasso.close = function () {
105639             if (group) {
105640               group.call(uiToggle(false, function () {
105641                 select(this).remove();
105642               }));
105643             }
105644
105645             context.container().classed('lasso', false);
105646           };
105647
105648           return lasso;
105649         }
105650
105651         function uiNoteComments() {
105652           var _note;
105653
105654           function noteComments(selection) {
105655             if (_note.isNew()) return; // don't draw .comments-container
105656
105657             var comments = selection.selectAll('.comments-container').data([0]);
105658             comments = comments.enter().append('div').attr('class', 'comments-container').merge(comments);
105659             var commentEnter = comments.selectAll('.comment').data(_note.comments).enter().append('div').attr('class', 'comment');
105660             commentEnter.append('div').attr('class', function (d) {
105661               return 'comment-avatar user-' + d.uid;
105662             }).call(svgIcon('#iD-icon-avatar', 'comment-avatar-icon'));
105663             var mainEnter = commentEnter.append('div').attr('class', 'comment-main');
105664             var metadataEnter = mainEnter.append('div').attr('class', 'comment-metadata');
105665             metadataEnter.append('div').attr('class', 'comment-author').each(function (d) {
105666               var selection = select(this);
105667               var osm = services.osm;
105668
105669               if (osm && d.user) {
105670                 selection = selection.append('a').attr('class', 'comment-author-link').attr('href', osm.userURL(d.user)).attr('target', '_blank');
105671               }
105672
105673               if (d.user) {
105674                 selection.text(d.user);
105675               } else {
105676                 selection.call(_t.append('note.anonymous'));
105677               }
105678             });
105679             metadataEnter.append('div').attr('class', 'comment-date').html(function (d) {
105680               return _t.html('note.status.' + d.action, {
105681                 when: localeDateString(d.date)
105682               });
105683             });
105684             mainEnter.append('div').attr('class', 'comment-text').html(function (d) {
105685               return d.html;
105686             }).selectAll('a').attr('rel', 'noopener nofollow').attr('target', '_blank');
105687             comments.call(replaceAvatars);
105688           }
105689
105690           function replaceAvatars(selection) {
105691             var showThirdPartyIcons = corePreferences('preferences.privacy.thirdpartyicons') || 'true';
105692             var osm = services.osm;
105693             if (showThirdPartyIcons !== 'true' || !osm) return;
105694             var uids = {}; // gather uids in the comment thread
105695
105696             _note.comments.forEach(function (d) {
105697               if (d.uid) uids[d.uid] = true;
105698             });
105699
105700             Object.keys(uids).forEach(function (uid) {
105701               osm.loadUser(uid, function (err, user) {
105702                 if (!user || !user.image_url) return;
105703                 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);
105704               });
105705             });
105706           }
105707
105708           function localeDateString(s) {
105709             if (!s) return null;
105710             var options = {
105711               day: 'numeric',
105712               month: 'short',
105713               year: 'numeric'
105714             };
105715             s = s.replace(/-/g, '/'); // fix browser-specific Date() issues
105716
105717             var d = new Date(s);
105718             if (isNaN(d.getTime())) return null;
105719             return d.toLocaleDateString(_mainLocalizer.localeCode(), options);
105720           }
105721
105722           noteComments.note = function (val) {
105723             if (!arguments.length) return _note;
105724             _note = val;
105725             return noteComments;
105726           };
105727
105728           return noteComments;
105729         }
105730
105731         function uiNoteHeader() {
105732           var _note;
105733
105734           function noteHeader(selection) {
105735             var header = selection.selectAll('.note-header').data(_note ? [_note] : [], function (d) {
105736               return d.status + d.id;
105737             });
105738             header.exit().remove();
105739             var headerEnter = header.enter().append('div').attr('class', 'note-header');
105740             var iconEnter = headerEnter.append('div').attr('class', function (d) {
105741               return 'note-header-icon ' + d.status;
105742             }).classed('new', function (d) {
105743               return d.id < 0;
105744             });
105745             iconEnter.append('div').attr('class', 'preset-icon-28').call(svgIcon('#iD-icon-note', 'note-fill'));
105746             iconEnter.each(function (d) {
105747               var statusIcon;
105748
105749               if (d.id < 0) {
105750                 statusIcon = '#iD-icon-plus';
105751               } else if (d.status === 'open') {
105752                 statusIcon = '#iD-icon-close';
105753               } else {
105754                 statusIcon = '#iD-icon-apply';
105755               }
105756
105757               iconEnter.append('div').attr('class', 'note-icon-annotation').attr('title', _t('icons.close')).call(svgIcon(statusIcon, 'icon-annotation'));
105758             });
105759             headerEnter.append('div').attr('class', 'note-header-label').html(function (d) {
105760               if (_note.isNew()) {
105761                 return _t.html('note.new');
105762               }
105763
105764               return _t.html('note.note') + ' ' + d.id + ' ' + (d.status === 'closed' ? _t.html('note.closed') : '');
105765             });
105766           }
105767
105768           noteHeader.note = function (val) {
105769             if (!arguments.length) return _note;
105770             _note = val;
105771             return noteHeader;
105772           };
105773
105774           return noteHeader;
105775         }
105776
105777         function uiNoteReport() {
105778           var _note;
105779
105780           function noteReport(selection) {
105781             var url;
105782
105783             if (services.osm && _note instanceof osmNote && !_note.isNew()) {
105784               url = services.osm.noteReportURL(_note);
105785             }
105786
105787             var link = selection.selectAll('.note-report').data(url ? [url] : []); // exit
105788
105789             link.exit().remove(); // enter
105790
105791             var linkEnter = link.enter().append('a').attr('class', 'note-report').attr('target', '_blank').attr('href', function (d) {
105792               return d;
105793             }).call(svgIcon('#iD-icon-out-link', 'inline'));
105794             linkEnter.append('span').call(_t.append('note.report'));
105795           }
105796
105797           noteReport.note = function (val) {
105798             if (!arguments.length) return _note;
105799             _note = val;
105800             return noteReport;
105801           };
105802
105803           return noteReport;
105804         }
105805
105806         function uiNoteEditor(context) {
105807           var dispatch = dispatch$8('change');
105808           var noteComments = uiNoteComments();
105809           var noteHeader = uiNoteHeader(); // var formFields = uiFormFields(context);
105810
105811           var _note;
105812
105813           var _newNote; // var _fieldsArr;
105814
105815
105816           function noteEditor(selection) {
105817             var header = selection.selectAll('.header').data([0]);
105818             var headerEnter = header.enter().append('div').attr('class', 'header fillL');
105819             headerEnter.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
105820               context.enter(modeBrowse(context));
105821             }).call(svgIcon('#iD-icon-close'));
105822             headerEnter.append('h2').call(_t.append('note.title'));
105823             var body = selection.selectAll('.body').data([0]);
105824             body = body.enter().append('div').attr('class', 'body').merge(body);
105825             var editor = body.selectAll('.note-editor').data([0]);
105826             editor.enter().append('div').attr('class', 'modal-section note-editor').merge(editor).call(noteHeader.note(_note)).call(noteComments.note(_note)).call(noteSaveSection);
105827             var footer = selection.selectAll('.footer').data([0]);
105828             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
105829
105830             var osm = services.osm;
105831
105832             if (osm) {
105833               osm.on('change.note-save', function () {
105834                 selection.call(noteEditor);
105835               });
105836             }
105837           }
105838
105839           function noteSaveSection(selection) {
105840             var isSelected = _note && _note.id === context.selectedNoteID();
105841
105842             var noteSave = selection.selectAll('.note-save').data(isSelected ? [_note] : [], function (d) {
105843               return d.status + d.id;
105844             }); // exit
105845
105846             noteSave.exit().remove(); // enter
105847
105848             var noteSaveEnter = noteSave.enter().append('div').attr('class', 'note-save save-section cf'); // // if new note, show categories to pick from
105849             // if (_note.isNew()) {
105850             //     var presets = presetManager;
105851             //     // NOTE: this key isn't a age and therefore there is no documentation (yet)
105852             //     _fieldsArr = [
105853             //         uiField(context, presets.field('category'), null, { show: true, revert: false }),
105854             //     ];
105855             //     _fieldsArr.forEach(function(field) {
105856             //         field
105857             //             .on('change', changeCategory);
105858             //     });
105859             //     noteSaveEnter
105860             //         .append('div')
105861             //         .attr('class', 'note-category')
105862             //         .call(formFields.fieldsArr(_fieldsArr));
105863             // }
105864             // function changeCategory() {
105865             //     // NOTE: perhaps there is a better way to get value
105866             //     var val = context.container().select('input[name=\'category\']:checked').property('__data__') || undefined;
105867             //     // store the unsaved category with the note itself
105868             //     _note = _note.update({ newCategory: val });
105869             //     var osm = services.osm;
105870             //     if (osm) {
105871             //         osm.replaceNote(_note);  // update note cache
105872             //     }
105873             //     noteSave
105874             //         .call(noteSaveButtons);
105875             // }
105876
105877             noteSaveEnter.append('h4').attr('class', '.note-save-header').html(function () {
105878               return _note.isNew() ? _t.html('note.newDescription') : _t.html('note.newComment');
105879             });
105880             var commentTextarea = noteSaveEnter.append('textarea').attr('class', 'new-comment-input').attr('placeholder', _t('note.inputPlaceholder')).attr('maxlength', 1000).property('value', function (d) {
105881               return d.newComment;
105882             }).call(utilNoAuto).on('keydown.note-input', keydown).on('input.note-input', changeInput).on('blur.note-input', changeInput);
105883
105884             if (!commentTextarea.empty() && _newNote) {
105885               // autofocus the comment field for new notes
105886               commentTextarea.node().focus();
105887             } // update
105888
105889
105890             noteSave = noteSaveEnter.merge(noteSave).call(userDetails).call(noteSaveButtons); // fast submit if user presses cmd+enter
105891
105892             function keydown(d3_event) {
105893               if (!(d3_event.keyCode === 13 && // ↩ Return
105894               d3_event.metaKey)) return;
105895               var osm = services.osm;
105896               if (!osm) return;
105897               var hasAuth = osm.authenticated();
105898               if (!hasAuth) return;
105899               if (!_note.newComment) return;
105900               d3_event.preventDefault();
105901               select(this).on('keydown.note-input', null); // focus on button and submit
105902
105903               window.setTimeout(function () {
105904                 if (_note.isNew()) {
105905                   noteSave.selectAll('.save-button').node().focus();
105906                   clickSave();
105907                 } else {
105908                   noteSave.selectAll('.comment-button').node().focus();
105909                   clickComment();
105910                 }
105911               }, 10);
105912             }
105913
105914             function changeInput() {
105915               var input = select(this);
105916               var val = input.property('value').trim() || undefined; // store the unsaved comment with the note itself
105917
105918               _note = _note.update({
105919                 newComment: val
105920               });
105921               var osm = services.osm;
105922
105923               if (osm) {
105924                 osm.replaceNote(_note); // update note cache
105925               }
105926
105927               noteSave.call(noteSaveButtons);
105928             }
105929           }
105930
105931           function userDetails(selection) {
105932             var detailSection = selection.selectAll('.detail-section').data([0]);
105933             detailSection = detailSection.enter().append('div').attr('class', 'detail-section').merge(detailSection);
105934             var osm = services.osm;
105935             if (!osm) return; // Add warning if user is not logged in
105936
105937             var hasAuth = osm.authenticated();
105938             var authWarning = detailSection.selectAll('.auth-warning').data(hasAuth ? [] : [0]);
105939             authWarning.exit().transition().duration(200).style('opacity', 0).remove();
105940             var authEnter = authWarning.enter().insert('div', '.tag-reference-body').attr('class', 'field-warning auth-warning').style('opacity', 0);
105941             authEnter.call(svgIcon('#iD-icon-alert', 'inline'));
105942             authEnter.append('span').call(_t.append('note.login'));
105943             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) {
105944               d3_event.preventDefault();
105945               osm.authenticate();
105946             });
105947             authEnter.transition().duration(200).style('opacity', 1);
105948             var prose = detailSection.selectAll('.note-save-prose').data(hasAuth ? [0] : []);
105949             prose.exit().remove();
105950             prose = prose.enter().append('p').attr('class', 'note-save-prose').call(_t.append('note.upload_explanation')).merge(prose);
105951             osm.userDetails(function (err, user) {
105952               if (err) return;
105953               var userLink = select(document.createElement('div'));
105954
105955               if (user.image_url) {
105956                 userLink.append('img').attr('src', user.image_url).attr('class', 'icon pre-text user-icon');
105957               }
105958
105959               userLink.append('a').attr('class', 'user-info').text(user.display_name).attr('href', osm.userURL(user.display_name)).attr('target', '_blank');
105960               prose.html(_t.html('note.upload_explanation_with_user', {
105961                 user: {
105962                   html: userLink.html()
105963                 }
105964               }));
105965             });
105966           }
105967
105968           function noteSaveButtons(selection) {
105969             var osm = services.osm;
105970             var hasAuth = osm && osm.authenticated();
105971
105972             var isSelected = _note && _note.id === context.selectedNoteID();
105973
105974             var buttonSection = selection.selectAll('.buttons').data(isSelected ? [_note] : [], function (d) {
105975               return d.status + d.id;
105976             }); // exit
105977
105978             buttonSection.exit().remove(); // enter
105979
105980             var buttonEnter = buttonSection.enter().append('div').attr('class', 'buttons');
105981
105982             if (_note.isNew()) {
105983               buttonEnter.append('button').attr('class', 'button cancel-button secondary-action').call(_t.append('confirm.cancel'));
105984               buttonEnter.append('button').attr('class', 'button save-button action').call(_t.append('note.save'));
105985             } else {
105986               buttonEnter.append('button').attr('class', 'button status-button action');
105987               buttonEnter.append('button').attr('class', 'button comment-button action').call(_t.append('note.comment'));
105988             } // update
105989
105990
105991             buttonSection = buttonSection.merge(buttonEnter);
105992             buttonSection.select('.cancel-button') // select and propagate data
105993             .on('click.cancel', clickCancel);
105994             buttonSection.select('.save-button') // select and propagate data
105995             .attr('disabled', isSaveDisabled).on('click.save', clickSave);
105996             buttonSection.select('.status-button') // select and propagate data
105997             .attr('disabled', hasAuth ? null : true).html(function (d) {
105998               var action = d.status === 'open' ? 'close' : 'open';
105999               var andComment = d.newComment ? '_comment' : '';
106000               return _t.html('note.' + action + andComment);
106001             }).on('click.status', clickStatus);
106002             buttonSection.select('.comment-button') // select and propagate data
106003             .attr('disabled', isSaveDisabled).on('click.comment', clickComment);
106004
106005             function isSaveDisabled(d) {
106006               return hasAuth && d.status === 'open' && d.newComment ? null : true;
106007             }
106008           }
106009
106010           function clickCancel(d3_event, d) {
106011             this.blur(); // avoid keeping focus on the button - #4641
106012
106013             var osm = services.osm;
106014
106015             if (osm) {
106016               osm.removeNote(d);
106017             }
106018
106019             context.enter(modeBrowse(context));
106020             dispatch.call('change');
106021           }
106022
106023           function clickSave(d3_event, d) {
106024             this.blur(); // avoid keeping focus on the button - #4641
106025
106026             var osm = services.osm;
106027
106028             if (osm) {
106029               osm.postNoteCreate(d, function (err, note) {
106030                 dispatch.call('change', note);
106031               });
106032             }
106033           }
106034
106035           function clickStatus(d3_event, d) {
106036             this.blur(); // avoid keeping focus on the button - #4641
106037
106038             var osm = services.osm;
106039
106040             if (osm) {
106041               var setStatus = d.status === 'open' ? 'closed' : 'open';
106042               osm.postNoteUpdate(d, setStatus, function (err, note) {
106043                 dispatch.call('change', note);
106044               });
106045             }
106046           }
106047
106048           function clickComment(d3_event, d) {
106049             this.blur(); // avoid keeping focus on the button - #4641
106050
106051             var osm = services.osm;
106052
106053             if (osm) {
106054               osm.postNoteUpdate(d, d.status, function (err, note) {
106055                 dispatch.call('change', note);
106056               });
106057             }
106058           }
106059
106060           noteEditor.note = function (val) {
106061             if (!arguments.length) return _note;
106062             _note = val;
106063             return noteEditor;
106064           };
106065
106066           noteEditor.newNote = function (val) {
106067             if (!arguments.length) return _newNote;
106068             _newNote = val;
106069             return noteEditor;
106070           };
106071
106072           return utilRebind(noteEditor, dispatch, 'on');
106073         }
106074
106075         function uiSourceSwitch(context) {
106076           var keys;
106077
106078           function click(d3_event) {
106079             d3_event.preventDefault();
106080             var osm = context.connection();
106081             if (!osm) return;
106082             if (context.inIntro()) return;
106083             if (context.history().hasChanges() && !window.confirm(_t('source_switch.lose_changes'))) return;
106084             var isLive = select(this).classed('live');
106085             isLive = !isLive;
106086             context.enter(modeBrowse(context));
106087             context.history().clearSaved(); // remove saved history
106088
106089             context.flush(); // remove stored data
106090
106091             select(this).html(isLive ? _t.html('source_switch.live') : _t.html('source_switch.dev')).classed('live', isLive).classed('chip', isLive);
106092             osm["switch"](isLive ? keys[0] : keys[1]); // switch connection (warning: dispatches 'change' event)
106093           }
106094
106095           var sourceSwitch = function sourceSwitch(selection) {
106096             selection.append('a').attr('href', '#').call(_t.append('source_switch.live')).attr('class', 'live chip').on('click', click);
106097           };
106098
106099           sourceSwitch.keys = function (_) {
106100             if (!arguments.length) return keys;
106101             keys = _;
106102             return sourceSwitch;
106103           };
106104
106105           return sourceSwitch;
106106         }
106107
106108         function uiSpinner(context) {
106109           var osm = context.connection();
106110           return function (selection) {
106111             var img = selection.append('img').attr('src', context.imagePath('loader-black.gif')).style('opacity', 0);
106112
106113             if (osm) {
106114               osm.on('loading.spinner', function () {
106115                 img.transition().style('opacity', 1);
106116               }).on('loaded.spinner', function () {
106117                 img.transition().style('opacity', 0);
106118               });
106119             }
106120           };
106121         }
106122
106123         function uiSectionPrivacy(context) {
106124           var section = uiSection('preferences-third-party', context).label(_t.html('preferences.privacy.title')).disclosureContent(renderDisclosureContent);
106125
106126           function renderDisclosureContent(selection) {
106127             // enter
106128             selection.selectAll('.privacy-options-list').data([0]).enter().append('ul').attr('class', 'layer-list privacy-options-list');
106129             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'));
106130             thirdPartyIconsEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event, d) {
106131               d3_event.preventDefault();
106132               corePreferences('preferences.privacy.thirdpartyicons', d === 'true' ? 'false' : 'true');
106133             });
106134             thirdPartyIconsEnter.append('span').call(_t.append('preferences.privacy.third_party_icons.description')); // update
106135
106136             selection.selectAll('.privacy-third-party-icons-item').classed('active', function (d) {
106137               return d === 'true';
106138             }).select('input').property('checked', function (d) {
106139               return d === 'true';
106140             }); // Privacy Policy link
106141
106142             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'));
106143           }
106144
106145           corePreferences.onChange('preferences.privacy.thirdpartyicons', section.reRender);
106146           return section;
106147         }
106148
106149         function uiSplash(context) {
106150           return function (selection) {
106151             // Exception - if there are restorable changes, skip this splash screen.
106152             // This is because we currently only support one `uiModal` at a time
106153             //  and we need to show them `uiRestore`` instead of this one.
106154             if (context.history().hasRestorableChanges()) return; // If user has not seen this version of the privacy policy, show the splash again.
106155
106156             var updateMessage = '';
106157             var sawPrivacyVersion = corePreferences('sawPrivacyVersion');
106158             var showSplash = !corePreferences('sawSplash');
106159
106160             if (sawPrivacyVersion !== context.privacyVersion) {
106161               updateMessage = _t('splash.privacy_update');
106162               showSplash = true;
106163             }
106164
106165             if (!showSplash) return;
106166             corePreferences('sawSplash', true);
106167             corePreferences('sawPrivacyVersion', context.privacyVersion); // fetch intro graph data now, while user is looking at the splash screen
106168
106169             _mainFileFetcher.get('intro_graph');
106170             var modalSelection = uiModal(selection);
106171             modalSelection.select('.modal').attr('class', 'modal-splash modal');
106172             var introModal = modalSelection.select('.content').append('div').attr('class', 'fillL');
106173             introModal.append('div').attr('class', 'modal-section').append('h3').call(_t.append('splash.welcome'));
106174             var modalSection = introModal.append('div').attr('class', 'modal-section');
106175             modalSection.append('p').html(_t.html('splash.text', {
106176               version: context.version,
106177               website: {
106178                 html: '<a target="_blank" href="https://github.com/openstreetmap/iD/blob/develop/CHANGELOG.md#whats-new">changelog</a>'
106179               },
106180               github: {
106181                 html: '<a target="_blank" href="https://github.com/openstreetmap/iD/issues">github.com</a>'
106182               }
106183             }));
106184             modalSection.append('p').html(_t.html('splash.privacy', {
106185               updateMessage: updateMessage,
106186               privacyLink: {
106187                 html: '<a target="_blank" href="https://github.com/openstreetmap/iD/blob/release/PRIVACY.md">' + _t('splash.privacy_policy') + '</a>'
106188               }
106189             }));
106190             uiSectionPrivacy(context).label(_t.html('splash.privacy_settings')).render(modalSection);
106191             var buttonWrap = introModal.append('div').attr('class', 'modal-actions');
106192             var walkthrough = buttonWrap.append('button').attr('class', 'walkthrough').on('click', function () {
106193               context.container().call(uiIntro(context));
106194               modalSelection.close();
106195             });
106196             walkthrough.append('svg').attr('class', 'logo logo-walkthrough').append('use').attr('xlink:href', '#iD-logo-walkthrough');
106197             walkthrough.append('div').call(_t.append('splash.walkthrough'));
106198             var startEditing = buttonWrap.append('button').attr('class', 'start-editing').on('click', modalSelection.close);
106199             startEditing.append('svg').attr('class', 'logo logo-features').append('use').attr('xlink:href', '#iD-logo-features');
106200             startEditing.append('div').call(_t.append('splash.start'));
106201             modalSelection.select('button.close').attr('class', 'hide');
106202           };
106203         }
106204
106205         function uiStatus(context) {
106206           var osm = context.connection();
106207           return function (selection) {
106208             if (!osm) return;
106209
106210             function update(err, apiStatus) {
106211               selection.html('');
106212
106213               if (err) {
106214                 if (apiStatus === 'connectionSwitched') {
106215                   // if the connection was just switched, we can't rely on
106216                   // the status (we're getting the status of the previous api)
106217                   return;
106218                 } else if (apiStatus === 'rateLimited') {
106219                   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) {
106220                     d3_event.preventDefault();
106221                     osm.authenticate();
106222                   });
106223                 } else {
106224                   // don't allow retrying too rapidly
106225                   var throttledRetry = throttle(function () {
106226                     // try loading the visible tiles
106227                     context.loadTiles(context.projection); // manually reload the status too in case all visible tiles were already loaded
106228
106229                     osm.reloadApiStatus();
106230                   }, 2000); // eslint-disable-next-line no-warning-comments
106231                   // TODO: nice messages for different error types
106232
106233
106234                   selection.call(_t.append('osm_api_status.message.error', {
106235                     suffix: ' '
106236                   })).append('a').attr('href', '#') // let the user manually retry their connection directly
106237                   .call(_t.append('osm_api_status.retry')).on('click.retry', function (d3_event) {
106238                     d3_event.preventDefault();
106239                     throttledRetry();
106240                   });
106241                 }
106242               } else if (apiStatus === 'readonly') {
106243                 selection.call(_t.append('osm_api_status.message.readonly'));
106244               } else if (apiStatus === 'offline') {
106245                 selection.call(_t.append('osm_api_status.message.offline'));
106246               }
106247
106248               selection.attr('class', 'api-status ' + (err ? 'error' : apiStatus));
106249             }
106250
106251             osm.on('apiStatusChange.uiStatus', update);
106252             context.history().on('storage_error', function () {
106253               selection.call(_t.append('osm_api_status.message.local_storage_full'));
106254               selection.attr('class', 'api-status error');
106255             }); // reload the status periodically regardless of other factors
106256
106257             window.setInterval(function () {
106258               osm.reloadApiStatus();
106259             }, 90000); // load the initial status in case no OSM data was loaded yet
106260
106261             osm.reloadApiStatus();
106262           };
106263         }
106264
106265         // for punction see https://stackoverflow.com/a/21224179
106266
106267         function simplify(str) {
106268           if (typeof str !== 'string') return '';
106269           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());
106270         }
106271
106272         // `resolveStrings`
106273         // Resolves the text strings for a given community index item
106274         //
106275         // Arguments
106276         //   `item`:  Object containing the community index item
106277         //   `defaults`: Object containing the community index default strings
106278         //   `localizerFn?`: optional function we will call to do the localization.
106279         //      This function should be like the iD `t()` function that
106280         //      accepts a `stringID` and returns a localized string
106281         //
106282         // Returns
106283         //   An Object containing all the resolved strings:
106284         //   {
106285         //     name:                     'talk-ru Mailing List',
106286         //     url:                      'https://lists.openstreetmap.org/listinfo/talk-ru',
106287         //     signupUrl:                'https://example.url/signup',
106288         //     description:              'A one line description',
106289         //     extendedDescription:      'Extended description',
106290         //     nameHTML:                 '<a href="the url">the name</a>',
106291         //     urlHTML:                  '<a href="the url">the url</a>',
106292         //     signupUrlHTML:            '<a href="the signupUrl">the signupUrl</a>',
106293         //     descriptionHTML:          the description, with urls and signupUrls linkified,
106294         //     extendedDescriptionHTML:  the extendedDescription with urls and signupUrls linkified
106295         //   }
106296         //
106297
106298         function resolveStrings(item, defaults, localizerFn) {
106299           var itemStrings = Object.assign({}, item.strings); // shallow clone
106300
106301           var defaultStrings = Object.assign({}, defaults[item.type]); // shallow clone
106302
106303           var anyToken = new RegExp(/(\{\w+\})/, 'gi'); // Pre-localize the item and default strings
106304
106305           if (localizerFn) {
106306             if (itemStrings.community) {
106307               var communityID = simplify(itemStrings.community);
106308               itemStrings.community = localizerFn("_communities.".concat(communityID));
106309             }
106310
106311             ['name', 'description', 'extendedDescription'].forEach(function (prop) {
106312               if (defaultStrings[prop]) defaultStrings[prop] = localizerFn("_defaults.".concat(item.type, ".").concat(prop));
106313               if (itemStrings[prop]) itemStrings[prop] = localizerFn("".concat(item.id, ".").concat(prop));
106314             });
106315           }
106316
106317           var replacements = {
106318             account: item.account,
106319             community: itemStrings.community,
106320             signupUrl: itemStrings.signupUrl,
106321             url: itemStrings.url
106322           }; // Resolve URLs first (which may refer to {account})
106323
106324           if (!replacements.signupUrl) {
106325             replacements.signupUrl = resolve(itemStrings.signupUrl || defaultStrings.signupUrl);
106326           }
106327
106328           if (!replacements.url) {
106329             replacements.url = resolve(itemStrings.url || defaultStrings.url);
106330           }
106331
106332           var resolved = {
106333             name: resolve(itemStrings.name || defaultStrings.name),
106334             url: resolve(itemStrings.url || defaultStrings.url),
106335             signupUrl: resolve(itemStrings.signupUrl || defaultStrings.signupUrl),
106336             description: resolve(itemStrings.description || defaultStrings.description),
106337             extendedDescription: resolve(itemStrings.extendedDescription || defaultStrings.extendedDescription)
106338           }; // Generate linkified strings
106339
106340           resolved.nameHTML = linkify(resolved.url, resolved.name);
106341           resolved.urlHTML = linkify(resolved.url);
106342           resolved.signupUrlHTML = linkify(resolved.signupUrl);
106343           resolved.descriptionHTML = resolve(itemStrings.description || defaultStrings.description, true);
106344           resolved.extendedDescriptionHTML = resolve(itemStrings.extendedDescription || defaultStrings.extendedDescription, true);
106345           return resolved;
106346
106347           function resolve(s, addLinks) {
106348             if (!s) return undefined;
106349             var result = s;
106350
106351             for (var key in replacements) {
106352               var token = "{".concat(key, "}");
106353               var regex = new RegExp(token, 'g');
106354
106355               if (regex.test(result)) {
106356                 var replacement = replacements[key];
106357
106358                 if (!replacement) {
106359                   throw new Error("Cannot resolve token: ".concat(token));
106360                 } else {
106361                   if (addLinks && (key === 'signupUrl' || key === 'url')) {
106362                     replacement = linkify(replacement);
106363                   }
106364
106365                   result = result.replace(regex, replacement);
106366                 }
106367               }
106368             } // There shouldn't be any leftover tokens in a resolved string
106369
106370
106371             var leftovers = result.match(anyToken);
106372
106373             if (leftovers) {
106374               throw new Error("Cannot resolve tokens: ".concat(leftovers));
106375             } // Linkify subreddits like `/r/openstreetmap`
106376             // https://github.com/osmlab/osm-community-index/issues/82
106377             // https://github.com/openstreetmap/iD/issues/4997
106378
106379
106380             if (addLinks && item.type === 'reddit') {
106381               result = result.replace(/(\/r\/\w+\/*)/i, function (match) {
106382                 return linkify(resolved.url, match);
106383               });
106384             }
106385
106386             return result;
106387           }
106388
106389           function linkify(url, text) {
106390             if (!url) return undefined;
106391             text = text || url;
106392             return "<a target=\"_blank\" href=\"".concat(url, "\">").concat(text, "</a>");
106393           }
106394         }
106395
106396         var _oci = null;
106397         function uiSuccess(context) {
106398           var MAXEVENTS = 2;
106399           var dispatch = dispatch$8('cancel');
106400
106401           var _changeset;
106402
106403           var _location;
106404
106405           ensureOSMCommunityIndex(); // start fetching the data
106406
106407           function ensureOSMCommunityIndex() {
106408             var data = _mainFileFetcher;
106409             return Promise.all([data.get('oci_features'), data.get('oci_resources'), data.get('oci_defaults')]).then(function (vals) {
106410               if (_oci) return _oci; // Merge Custom Features
106411
106412               if (vals[0] && Array.isArray(vals[0].features)) {
106413                 _mainLocations.mergeCustomGeoJSON(vals[0]);
106414               }
106415
106416               var ociResources = Object.values(vals[1].resources);
106417
106418               if (ociResources.length) {
106419                 // Resolve all locationSet features.
106420                 return _mainLocations.mergeLocationSets(ociResources).then(function () {
106421                   _oci = {
106422                     resources: ociResources,
106423                     defaults: vals[2].defaults
106424                   };
106425                   return _oci;
106426                 });
106427               } else {
106428                 _oci = {
106429                   resources: [],
106430                   // no resources?
106431                   defaults: vals[2].defaults
106432                 };
106433                 return _oci;
106434               }
106435             });
106436           } // string-to-date parsing in JavaScript is weird
106437
106438
106439           function parseEventDate(when) {
106440             if (!when) return;
106441             var raw = when.trim();
106442             if (!raw) return;
106443
106444             if (!/Z$/.test(raw)) {
106445               // if no trailing 'Z', add one
106446               raw += 'Z'; // this forces date to be parsed as a UTC date
106447             }
106448
106449             var parsed = new Date(raw);
106450             return new Date(parsed.toUTCString().substr(0, 25)); // convert to local timezone
106451           }
106452
106453           function success(selection) {
106454             var header = selection.append('div').attr('class', 'header fillL');
106455             header.append('h2').call(_t.append('success.just_edited'));
106456             header.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
106457               return dispatch.call('cancel');
106458             }).call(svgIcon('#iD-icon-close'));
106459             var body = selection.append('div').attr('class', 'body save-success fillL');
106460             var summary = body.append('div').attr('class', 'save-summary');
106461             summary.append('h3').call(_t.append('success.thank_you' + (_location ? '_location' : ''), {
106462               where: _location
106463             }));
106464             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'));
106465             var osm = context.connection();
106466             if (!osm) return;
106467             var changesetURL = osm.changesetURL(_changeset.id);
106468             var table = summary.append('table').attr('class', 'summary-table');
106469             var row = table.append('tr').attr('class', 'summary-row');
106470             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');
106471             var summaryDetail = row.append('td').attr('class', 'cell-detail summary-detail');
106472             summaryDetail.append('a').attr('class', 'cell-detail summary-view-on-osm').attr('target', '_blank').attr('href', changesetURL).call(_t.append('success.view_on_osm'));
106473             summaryDetail.append('div').html(_t.html('success.changeset_id', {
106474               changeset_id: {
106475                 html: "<a href=\"".concat(changesetURL, "\" target=\"_blank\">").concat(_changeset.id, "</a>")
106476               }
106477             })); // Get OSM community index features intersecting the map..
106478
106479             ensureOSMCommunityIndex().then(function (oci) {
106480               var loc = context.map().center();
106481               var validLocations = _mainLocations.locationsAt(loc); // Gather the communities
106482
106483               var communities = [];
106484               oci.resources.forEach(function (resource) {
106485                 var area = validLocations[resource.locationSetID];
106486                 if (!area) return; // Resolve strings
106487
106488                 var localizer = function localizer(stringID) {
106489                   return _t.html("community.".concat(stringID));
106490                 };
106491
106492                 resource.resolved = resolveStrings(resource, oci.defaults, localizer);
106493                 communities.push({
106494                   area: area,
106495                   order: resource.order || 0,
106496                   resource: resource
106497                 });
106498               }); // sort communities by feature area ascending, community order descending
106499
106500               communities.sort(function (a, b) {
106501                 return a.area - b.area || b.order - a.order;
106502               });
106503               body.call(showCommunityLinks, communities.map(function (c) {
106504                 return c.resource;
106505               }));
106506             });
106507           }
106508
106509           function showCommunityLinks(selection, resources) {
106510             var communityLinks = selection.append('div').attr('class', 'save-communityLinks');
106511             communityLinks.append('h3').call(_t.append('success.like_osm'));
106512             var table = communityLinks.append('table').attr('class', 'community-table');
106513             var row = table.selectAll('.community-row').data(resources);
106514             var rowEnter = row.enter().append('tr').attr('class', 'community-row');
106515             rowEnter.append('td').attr('class', 'cell-icon community-icon').append('a').attr('target', '_blank').attr('href', function (d) {
106516               return d.resolved.url;
106517             }).append('svg').attr('class', 'logo-small').append('use').attr('xlink:href', function (d) {
106518               return "#community-".concat(d.type);
106519             });
106520             var communityDetail = rowEnter.append('td').attr('class', 'cell-detail community-detail');
106521             communityDetail.each(showCommunityDetails);
106522             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'));
106523           }
106524
106525           function showCommunityDetails(d) {
106526             var selection = select(this);
106527             var communityID = d.id;
106528             selection.append('div').attr('class', 'community-name').html(d.resolved.nameHTML);
106529             selection.append('div').attr('class', 'community-description').html(d.resolved.descriptionHTML); // Create an expanding section if any of these are present..
106530
106531             if (d.resolved.extendedDescriptionHTML || d.languageCodes && d.languageCodes.length) {
106532               selection.append('div').call(uiDisclosure(context, "community-more-".concat(d.id), false).expanded(false).updatePreference(false).label(_t.html('success.more')).content(showMore));
106533             }
106534
106535             var nextEvents = (d.events || []).map(function (event) {
106536               event.date = parseEventDate(event.when);
106537               return event;
106538             }).filter(function (event) {
106539               // date is valid and future (or today)
106540               var t = event.date.getTime();
106541               var now = new Date().setHours(0, 0, 0, 0);
106542               return !isNaN(t) && t >= now;
106543             }).sort(function (a, b) {
106544               // sort by date ascending
106545               return a.date < b.date ? -1 : a.date > b.date ? 1 : 0;
106546             }).slice(0, MAXEVENTS); // limit number of events shown
106547
106548             if (nextEvents.length) {
106549               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);
106550             }
106551
106552             function showMore(selection) {
106553               var more = selection.selectAll('.community-more').data([0]);
106554               var moreEnter = more.enter().append('div').attr('class', 'community-more');
106555
106556               if (d.resolved.extendedDescriptionHTML) {
106557                 moreEnter.append('div').attr('class', 'community-extended-description').html(d.resolved.extendedDescriptionHTML);
106558               }
106559
106560               if (d.languageCodes && d.languageCodes.length) {
106561                 var languageList = d.languageCodes.map(function (code) {
106562                   return _mainLocalizer.languageName(code);
106563                 }).join(', ');
106564                 moreEnter.append('div').attr('class', 'community-languages').call(_t.append('success.languages', {
106565                   languages: languageList
106566                 }));
106567               }
106568             }
106569
106570             function showNextEvents(selection) {
106571               var events = selection.append('div').attr('class', 'community-events');
106572               var item = events.selectAll('.community-event').data(nextEvents);
106573               var itemEnter = item.enter().append('div').attr('class', 'community-event');
106574               itemEnter.append('div').attr('class', 'community-event-name').append('a').attr('target', '_blank').attr('href', function (d) {
106575                 return d.url;
106576               }).text(function (d) {
106577                 var name = d.name;
106578
106579                 if (d.i18n && d.id) {
106580                   name = _t("community.".concat(communityID, ".events.").concat(d.id, ".name"), {
106581                     "default": name
106582                   });
106583                 }
106584
106585                 return name;
106586               });
106587               itemEnter.append('div').attr('class', 'community-event-when').text(function (d) {
106588                 var options = {
106589                   weekday: 'short',
106590                   day: 'numeric',
106591                   month: 'short',
106592                   year: 'numeric'
106593                 };
106594
106595                 if (d.date.getHours() || d.date.getMinutes()) {
106596                   // include time if it has one
106597                   options.hour = 'numeric';
106598                   options.minute = 'numeric';
106599                 }
106600
106601                 return d.date.toLocaleString(_mainLocalizer.localeCode(), options);
106602               });
106603               itemEnter.append('div').attr('class', 'community-event-where').text(function (d) {
106604                 var where = d.where;
106605
106606                 if (d.i18n && d.id) {
106607                   where = _t("community.".concat(communityID, ".events.").concat(d.id, ".where"), {
106608                     "default": where
106609                   });
106610                 }
106611
106612                 return where;
106613               });
106614               itemEnter.append('div').attr('class', 'community-event-description').text(function (d) {
106615                 var description = d.description;
106616
106617                 if (d.i18n && d.id) {
106618                   description = _t("community.".concat(communityID, ".events.").concat(d.id, ".description"), {
106619                     "default": description
106620                   });
106621                 }
106622
106623                 return description;
106624               });
106625             }
106626           }
106627
106628           success.changeset = function (val) {
106629             if (!arguments.length) return _changeset;
106630             _changeset = val;
106631             return success;
106632           };
106633
106634           success.location = function (val) {
106635             if (!arguments.length) return _location;
106636             _location = val;
106637             return success;
106638           };
106639
106640           return utilRebind(success, dispatch, 'on');
106641         }
106642
106643         var sawVersion = null;
106644         var isNewVersion = false;
106645         var isNewUser = false;
106646         function uiVersion(context) {
106647           var currVersion = context.version;
106648           var matchedVersion = currVersion.match(/\d+\.\d+\.\d+.*/);
106649
106650           if (sawVersion === null && matchedVersion !== null) {
106651             if (corePreferences('sawVersion')) {
106652               isNewUser = false;
106653               isNewVersion = corePreferences('sawVersion') !== currVersion && currVersion.indexOf('-') === -1;
106654             } else {
106655               isNewUser = true;
106656               isNewVersion = true;
106657             }
106658
106659             corePreferences('sawVersion', currVersion);
106660             sawVersion = currVersion;
106661           }
106662
106663           return function (selection) {
106664             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
106665
106666             if (isNewVersion && !isNewUser) {
106667               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', {
106668                 version: currVersion
106669               })).placement('top').scrollContainer(context.container().select('.main-footer-wrap')));
106670             }
106671           };
106672         }
106673
106674         function uiZoom(context) {
106675           var zooms = [{
106676             id: 'zoom-in',
106677             icon: 'iD-icon-plus',
106678             title: _t.html('zoom.in'),
106679             action: zoomIn,
106680             disabled: function disabled() {
106681               return !context.map().canZoomIn();
106682             },
106683             disabledTitle: _t.html('zoom.disabled.in'),
106684             key: '+'
106685           }, {
106686             id: 'zoom-out',
106687             icon: 'iD-icon-minus',
106688             title: _t.html('zoom.out'),
106689             action: zoomOut,
106690             disabled: function disabled() {
106691               return !context.map().canZoomOut();
106692             },
106693             disabledTitle: _t.html('zoom.disabled.out'),
106694             key: '-'
106695           }];
106696
106697           function zoomIn(d3_event) {
106698             if (d3_event.shiftKey) return;
106699             d3_event.preventDefault();
106700             context.map().zoomIn();
106701           }
106702
106703           function zoomOut(d3_event) {
106704             if (d3_event.shiftKey) return;
106705             d3_event.preventDefault();
106706             context.map().zoomOut();
106707           }
106708
106709           function zoomInFurther(d3_event) {
106710             if (d3_event.shiftKey) return;
106711             d3_event.preventDefault();
106712             context.map().zoomInFurther();
106713           }
106714
106715           function zoomOutFurther(d3_event) {
106716             if (d3_event.shiftKey) return;
106717             d3_event.preventDefault();
106718             context.map().zoomOutFurther();
106719           }
106720
106721           return function (selection) {
106722             var tooltipBehavior = uiTooltip().placement(_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left').title(function (d) {
106723               if (d.disabled()) {
106724                 return d.disabledTitle;
106725               }
106726
106727               return d.title;
106728             }).keys(function (d) {
106729               return [d.key];
106730             });
106731             var lastPointerUpType;
106732             var buttons = selection.selectAll('button').data(zooms).enter().append('button').attr('class', function (d) {
106733               return d.id;
106734             }).on('pointerup.editor', function (d3_event) {
106735               lastPointerUpType = d3_event.pointerType;
106736             }).on('click.editor', function (d3_event, d) {
106737               if (!d.disabled()) {
106738                 d.action(d3_event);
106739               } else if (lastPointerUpType === 'touch' || lastPointerUpType === 'pen') {
106740                 context.ui().flash.duration(2000).iconName('#' + d.icon).iconClass('disabled').label(d.disabledTitle)();
106741               }
106742
106743               lastPointerUpType = null;
106744             }).call(tooltipBehavior);
106745             buttons.each(function (d) {
106746               select(this).call(svgIcon('#' + d.icon, 'light'));
106747             });
106748             utilKeybinding.plusKeys.forEach(function (key) {
106749               context.keybinding().on([key], zoomIn);
106750               context.keybinding().on([uiCmd('⌥' + key)], zoomInFurther);
106751             });
106752             utilKeybinding.minusKeys.forEach(function (key) {
106753               context.keybinding().on([key], zoomOut);
106754               context.keybinding().on([uiCmd('⌥' + key)], zoomOutFurther);
106755             });
106756
106757             function updateButtonStates() {
106758               buttons.classed('disabled', function (d) {
106759                 return d.disabled();
106760               }).each(function () {
106761                 var selection = select(this);
106762
106763                 if (!selection.select('.tooltip.in').empty()) {
106764                   selection.call(tooltipBehavior.updateContent);
106765                 }
106766               });
106767             }
106768
106769             updateButtonStates();
106770             context.map().on('move.uiZoom', updateButtonStates);
106771           };
106772         }
106773
106774         function uiSectionRawTagEditor(id, context) {
106775           var section = uiSection(id, context).classes('raw-tag-editor').label(function () {
106776             var count = Object.keys(_tags).filter(function (d) {
106777               return d;
106778             }).length;
106779             return _t.html('inspector.title_count', {
106780               title: {
106781                 html: _t.html('inspector.tags')
106782               },
106783               count: count
106784             });
106785           }).expandedByDefault(false).disclosureContent(renderDisclosureContent);
106786           var taginfo = services.taginfo;
106787           var dispatch = dispatch$8('change');
106788           var availableViews = [{
106789             id: 'list',
106790             icon: '#fas-th-list'
106791           }, {
106792             id: 'text',
106793             icon: '#fas-i-cursor'
106794           }];
106795
106796           var _tagView = corePreferences('raw-tag-editor-view') || 'list'; // 'list, 'text'
106797
106798
106799           var _readOnlyTags = []; // the keys in the order we want them to display
106800
106801           var _orderedKeys = [];
106802           var _showBlank = false;
106803           var _pendingChange = null;
106804
106805           var _state;
106806
106807           var _presets;
106808
106809           var _tags;
106810
106811           var _entityIDs;
106812
106813           var _didInteract = false;
106814
106815           function interacted() {
106816             _didInteract = true;
106817           }
106818
106819           function renderDisclosureContent(wrap) {
106820             // remove deleted keys
106821             _orderedKeys = _orderedKeys.filter(function (key) {
106822               return _tags[key] !== undefined;
106823             }); // When switching to a different entity or changing the state (hover/select)
106824             // reorder the keys alphabetically.
106825             // We trigger this by emptying the `_orderedKeys` array, then it will be rebuilt here.
106826             // Otherwise leave their order alone - #5857, #5927
106827
106828             var all = Object.keys(_tags).sort();
106829             var missingKeys = utilArrayDifference(all, _orderedKeys);
106830
106831             for (var i in missingKeys) {
106832               _orderedKeys.push(missingKeys[i]);
106833             } // assemble row data
106834
106835
106836             var rowData = _orderedKeys.map(function (key, i) {
106837               return {
106838                 index: i,
106839                 key: key,
106840                 value: _tags[key]
106841               };
106842             }); // append blank row last, if necessary
106843
106844
106845             if (!rowData.length || _showBlank) {
106846               _showBlank = false;
106847               rowData.push({
106848                 index: rowData.length,
106849                 key: '',
106850                 value: ''
106851               });
106852             } // View Options
106853
106854
106855             var options = wrap.selectAll('.raw-tag-options').data([0]);
106856             options.exit().remove();
106857             var optionsEnter = options.enter().insert('div', ':first-child').attr('class', 'raw-tag-options').attr('role', 'tablist');
106858             var optionEnter = optionsEnter.selectAll('.raw-tag-option').data(availableViews, function (d) {
106859               return d.id;
106860             }).enter();
106861             optionEnter.append('button').attr('class', function (d) {
106862               return 'raw-tag-option raw-tag-option-' + d.id + (_tagView === d.id ? ' selected' : '');
106863             }).attr('aria-selected', function (d) {
106864               return _tagView === d.id;
106865             }).attr('role', 'tab').attr('title', function (d) {
106866               return _t('icons.' + d.id);
106867             }).on('click', function (d3_event, d) {
106868               _tagView = d.id;
106869               corePreferences('raw-tag-editor-view', d.id);
106870               wrap.selectAll('.raw-tag-option').classed('selected', function (datum) {
106871                 return datum === d;
106872               }).attr('aria-selected', function (datum) {
106873                 return datum === d;
106874               });
106875               wrap.selectAll('.tag-text').classed('hide', d.id !== 'text').each(setTextareaHeight);
106876               wrap.selectAll('.tag-list, .add-row').classed('hide', d.id !== 'list');
106877             }).each(function (d) {
106878               select(this).call(svgIcon(d.icon));
106879             }); // View as Text
106880
106881             var textData = rowsToText(rowData);
106882             var textarea = wrap.selectAll('.tag-text').data([0]);
106883             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);
106884             textarea.call(utilGetSetValue, textData).each(setTextareaHeight).on('input', setTextareaHeight).on('focus', interacted).on('blur', textChanged).on('change', textChanged); // View as List
106885
106886             var list = wrap.selectAll('.tag-list').data([0]);
106887             list = list.enter().append('ul').attr('class', 'tag-list' + (_tagView !== 'list' ? ' hide' : '')).merge(list); // Container for the Add button
106888
106889             var addRowEnter = wrap.selectAll('.add-row').data([0]).enter().append('div').attr('class', 'add-row' + (_tagView !== 'list' ? ' hide' : ''));
106890             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);
106891             addRowEnter.append('div').attr('class', 'space-value'); // preserve space
106892
106893             addRowEnter.append('div').attr('class', 'space-buttons'); // preserve space
106894             // Tag list items
106895
106896             var items = list.selectAll('.tag-row').data(rowData, function (d) {
106897               return d.key;
106898             });
106899             items.exit().each(unbind).remove(); // Enter
106900
106901             var itemsEnter = items.enter().append('li').attr('class', 'tag-row').classed('readonly', isReadOnly);
106902             var innerWrap = itemsEnter.append('div').attr('class', 'inner-wrap');
106903             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);
106904             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);
106905             innerWrap.append('button').attr('class', 'form-field-button remove').attr('title', _t('icons.remove')).call(svgIcon('#iD-operation-delete')); // Update
106906
106907             items = items.merge(itemsEnter).sort(function (a, b) {
106908               return a.index - b.index;
106909             });
106910             items.each(function (d) {
106911               var row = select(this);
106912               var key = row.select('input.key'); // propagate bound data
106913
106914               var value = row.select('input.value'); // propagate bound data
106915
106916               if (_entityIDs && taginfo && _state !== 'hover') {
106917                 bindTypeahead(key, value);
106918               }
106919
106920               var referenceOptions = {
106921                 key: d.key
106922               };
106923
106924               if (typeof d.value === 'string') {
106925                 referenceOptions.value = d.value;
106926               }
106927
106928               var reference = uiTagReference(referenceOptions);
106929
106930               if (_state === 'hover') {
106931                 reference.showing(false);
106932               }
106933
106934               row.select('.inner-wrap') // propagate bound data
106935               .call(reference.button);
106936               row.call(reference.body);
106937               row.select('button.remove'); // propagate bound data
106938             });
106939             items.selectAll('input.key').attr('title', function (d) {
106940               return d.key;
106941             }).call(utilGetSetValue, function (d) {
106942               return d.key;
106943             }).attr('readonly', function (d) {
106944               return isReadOnly(d) || null;
106945             });
106946             items.selectAll('input.value').attr('title', function (d) {
106947               return Array.isArray(d.value) ? d.value.filter(Boolean).join('\n') : d.value;
106948             }).classed('mixed', function (d) {
106949               return Array.isArray(d.value);
106950             }).attr('placeholder', function (d) {
106951               return typeof d.value === 'string' ? null : _t('inspector.multiple_values');
106952             }).call(utilGetSetValue, function (d) {
106953               return typeof d.value === 'string' ? d.value : '';
106954             }).attr('readonly', function (d) {
106955               return isReadOnly(d) || null;
106956             });
106957             items.selectAll('button.remove').on(('PointerEvent' in window ? 'pointer' : 'mouse') + 'down', removeTag); // 'click' fires too late - #5878
106958           }
106959
106960           function isReadOnly(d) {
106961             for (var i = 0; i < _readOnlyTags.length; i++) {
106962               if (d.key.match(_readOnlyTags[i]) !== null) {
106963                 return true;
106964               }
106965             }
106966
106967             return false;
106968           }
106969
106970           function setTextareaHeight() {
106971             if (_tagView !== 'text') return;
106972             var selection = select(this);
106973             var matches = selection.node().value.match(/\n/g);
106974             var lineCount = 2 + Number(matches && matches.length);
106975             var lineHeight = 20;
106976             selection.style('height', lineCount * lineHeight + 'px');
106977           }
106978
106979           function stringify(s) {
106980             return JSON.stringify(s).slice(1, -1); // without leading/trailing "
106981           }
106982
106983           function unstringify(s) {
106984             var leading = '';
106985             var trailing = '';
106986
106987             if (s.length < 1 || s.charAt(0) !== '"') {
106988               leading = '"';
106989             }
106990
106991             if (s.length < 2 || s.charAt(s.length - 1) !== '"' || s.charAt(s.length - 1) === '"' && s.charAt(s.length - 2) === '\\') {
106992               trailing = '"';
106993             }
106994
106995             return JSON.parse(leading + s + trailing);
106996           }
106997
106998           function rowsToText(rows) {
106999             var str = rows.filter(function (row) {
107000               return row.key && row.key.trim() !== '';
107001             }).map(function (row) {
107002               var rawVal = row.value;
107003               if (typeof rawVal !== 'string') rawVal = '*';
107004               var val = rawVal ? stringify(rawVal) : '';
107005               return stringify(row.key) + '=' + val;
107006             }).join('\n');
107007
107008             if (_state !== 'hover' && str.length) {
107009               return str + '\n';
107010             }
107011
107012             return str;
107013           }
107014
107015           function textChanged() {
107016             var newText = this.value.trim();
107017             var newTags = {};
107018             newText.split('\n').forEach(function (row) {
107019               var m = row.match(/^\s*([^=]+)=(.*)$/);
107020
107021               if (m !== null) {
107022                 var k = context.cleanTagKey(unstringify(m[1].trim()));
107023                 var v = context.cleanTagValue(unstringify(m[2].trim()));
107024                 newTags[k] = v;
107025               }
107026             });
107027             var tagDiff = utilTagDiff(_tags, newTags);
107028             if (!tagDiff.length) return;
107029             _pendingChange = _pendingChange || {};
107030             tagDiff.forEach(function (change) {
107031               if (isReadOnly({
107032                 key: change.key
107033               })) return; // skip unchanged multiselection placeholders
107034
107035               if (change.newVal === '*' && typeof change.oldVal !== 'string') return;
107036
107037               if (change.type === '-') {
107038                 _pendingChange[change.key] = undefined;
107039               } else if (change.type === '+') {
107040                 _pendingChange[change.key] = change.newVal || '';
107041               }
107042             });
107043
107044             if (Object.keys(_pendingChange).length === 0) {
107045               _pendingChange = null;
107046               return;
107047             }
107048
107049             scheduleChange();
107050           }
107051
107052           function pushMore(d3_event) {
107053             // if pressing Tab on the last value field with content, add a blank row
107054             if (d3_event.keyCode === 9 && !d3_event.shiftKey && section.selection().selectAll('.tag-list li:last-child input.value').node() === this && utilGetSetValue(select(this))) {
107055               addTag();
107056             }
107057           }
107058
107059           function bindTypeahead(key, value) {
107060             if (isReadOnly(key.datum())) return;
107061
107062             if (Array.isArray(value.datum().value)) {
107063               value.call(uiCombobox(context, 'tag-value').minItems(1).fetcher(function (value, callback) {
107064                 var keyString = utilGetSetValue(key);
107065                 if (!_tags[keyString]) return;
107066
107067                 var data = _tags[keyString].filter(Boolean).map(function (tagValue) {
107068                   return {
107069                     value: tagValue,
107070                     title: tagValue
107071                   };
107072                 });
107073
107074                 callback(data);
107075               }));
107076               return;
107077             }
107078
107079             var geometry = context.graph().geometry(_entityIDs[0]);
107080             key.call(uiCombobox(context, 'tag-key').fetcher(function (value, callback) {
107081               taginfo.keys({
107082                 debounce: true,
107083                 geometry: geometry,
107084                 query: value
107085               }, function (err, data) {
107086                 if (!err) {
107087                   var filtered = data.filter(function (d) {
107088                     return _tags[d.value] === undefined;
107089                   });
107090                   callback(sort(value, filtered));
107091                 }
107092               });
107093             }));
107094             value.call(uiCombobox(context, 'tag-value').fetcher(function (value, callback) {
107095               taginfo.values({
107096                 debounce: true,
107097                 key: utilGetSetValue(key),
107098                 geometry: geometry,
107099                 query: value
107100               }, function (err, data) {
107101                 if (!err) callback(sort(value, data));
107102               });
107103             }));
107104
107105             function sort(value, data) {
107106               var sameletter = [];
107107               var other = [];
107108
107109               for (var i = 0; i < data.length; i++) {
107110                 if (data[i].value.substring(0, value.length) === value) {
107111                   sameletter.push(data[i]);
107112                 } else {
107113                   other.push(data[i]);
107114                 }
107115               }
107116
107117               return sameletter.concat(other);
107118             }
107119           }
107120
107121           function unbind() {
107122             var row = select(this);
107123             row.selectAll('input.key').call(uiCombobox.off, context);
107124             row.selectAll('input.value').call(uiCombobox.off, context);
107125           }
107126
107127           function keyChange(d3_event, d) {
107128             if (select(this).attr('readonly')) return;
107129             var kOld = d.key; // exit if we are currently about to delete this row anyway - #6366
107130
107131             if (_pendingChange && _pendingChange.hasOwnProperty(kOld) && _pendingChange[kOld] === undefined) return;
107132             var kNew = context.cleanTagKey(this.value.trim()); // allow no change if the key should be readonly
107133
107134             if (isReadOnly({
107135               key: kNew
107136             })) {
107137               this.value = kOld;
107138               return;
107139             }
107140
107141             if (kNew && kNew !== kOld && _tags[kNew] !== undefined) {
107142               // new key is already in use, switch focus to the existing row
107143               this.value = kOld; // reset the key
107144
107145               section.selection().selectAll('.tag-list input.value').each(function (d) {
107146                 if (d.key === kNew) {
107147                   // send focus to that other value combo instead
107148                   var input = select(this).node();
107149                   input.focus();
107150                   input.select();
107151                 }
107152               });
107153               return;
107154             }
107155
107156             _pendingChange = _pendingChange || {};
107157
107158             if (kOld) {
107159               if (kOld === kNew) return; // a tag key was renamed
107160
107161               _pendingChange[kNew] = _pendingChange[kOld] || {
107162                 oldKey: kOld
107163               };
107164               _pendingChange[kOld] = undefined;
107165             } else {
107166               // a new tag was added
107167               var row = this.parentNode.parentNode;
107168               var inputVal = select(row).selectAll('input.value');
107169               var vNew = context.cleanTagValue(utilGetSetValue(inputVal));
107170               _pendingChange[kNew] = vNew;
107171               utilGetSetValue(inputVal, vNew);
107172             } // update the ordered key index so this row doesn't change position
107173
107174
107175             var existingKeyIndex = _orderedKeys.indexOf(kOld);
107176
107177             if (existingKeyIndex !== -1) _orderedKeys[existingKeyIndex] = kNew;
107178             d.key = kNew; // update datum to avoid exit/enter on tag update
107179
107180             this.value = kNew;
107181             scheduleChange();
107182           }
107183
107184           function valueChange(d3_event, d) {
107185             if (isReadOnly(d)) return; // exit if this is a multiselection and no value was entered
107186
107187             if (typeof d.value !== 'string' && !this.value) return; // exit if we are currently about to delete this row anyway - #6366
107188
107189             if (_pendingChange && _pendingChange.hasOwnProperty(d.key) && _pendingChange[d.key] === undefined) return;
107190             _pendingChange = _pendingChange || {};
107191             _pendingChange[d.key] = context.cleanTagValue(this.value);
107192             scheduleChange();
107193           }
107194
107195           function removeTag(d3_event, d) {
107196             if (isReadOnly(d)) return;
107197
107198             if (d.key === '') {
107199               // removing the blank row
107200               _showBlank = false;
107201               section.reRender();
107202             } else {
107203               // remove the key from the ordered key index
107204               _orderedKeys = _orderedKeys.filter(function (key) {
107205                 return key !== d.key;
107206               });
107207               _pendingChange = _pendingChange || {};
107208               _pendingChange[d.key] = undefined;
107209               scheduleChange();
107210             }
107211           }
107212
107213           function addTag() {
107214             // Delay render in case this click is blurring an edited combo.
107215             // Without the setTimeout, the `content` render would wipe out the pending tag change.
107216             window.setTimeout(function () {
107217               _showBlank = true;
107218               section.reRender();
107219               section.selection().selectAll('.tag-list li:last-child input.key').node().focus();
107220             }, 20);
107221           }
107222
107223           function scheduleChange() {
107224             // Cache IDs in case the editor is reloaded before the change event is called. - #6028
107225             var entityIDs = _entityIDs; // Delay change in case this change is blurring an edited combo. - #5878
107226
107227             window.setTimeout(function () {
107228               if (!_pendingChange) return;
107229               dispatch.call('change', this, entityIDs, _pendingChange);
107230               _pendingChange = null;
107231             }, 10);
107232           }
107233
107234           section.state = function (val) {
107235             if (!arguments.length) return _state;
107236
107237             if (_state !== val) {
107238               _orderedKeys = [];
107239               _state = val;
107240             }
107241
107242             return section;
107243           };
107244
107245           section.presets = function (val) {
107246             if (!arguments.length) return _presets;
107247             _presets = val;
107248
107249             if (_presets && _presets.length && _presets[0].isFallback()) {
107250               section.disclosureExpanded(true); // don't collapse the disclosure if the mapper used the raw tag editor - #1881
107251             } else if (!_didInteract) {
107252               section.disclosureExpanded(null);
107253             }
107254
107255             return section;
107256           };
107257
107258           section.tags = function (val) {
107259             if (!arguments.length) return _tags;
107260             _tags = val;
107261             return section;
107262           };
107263
107264           section.entityIDs = function (val) {
107265             if (!arguments.length) return _entityIDs;
107266
107267             if (!_entityIDs || !val || !utilArrayIdentical(_entityIDs, val)) {
107268               _entityIDs = val;
107269               _orderedKeys = [];
107270             }
107271
107272             return section;
107273           }; // pass an array of regular expressions to test against the tag key
107274
107275
107276           section.readOnlyTags = function (val) {
107277             if (!arguments.length) return _readOnlyTags;
107278             _readOnlyTags = val;
107279             return section;
107280           };
107281
107282           return utilRebind(section, dispatch, 'on');
107283         }
107284
107285         function uiDataEditor(context) {
107286           var dataHeader = uiDataHeader();
107287           var rawTagEditor = uiSectionRawTagEditor('custom-data-tag-editor', context).expandedByDefault(true).readOnlyTags([/./]);
107288
107289           var _datum;
107290
107291           function dataEditor(selection) {
107292             var header = selection.selectAll('.header').data([0]);
107293             var headerEnter = header.enter().append('div').attr('class', 'header fillL');
107294             headerEnter.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
107295               context.enter(modeBrowse(context));
107296             }).call(svgIcon('#iD-icon-close'));
107297             headerEnter.append('h2').call(_t.append('map_data.title'));
107298             var body = selection.selectAll('.body').data([0]);
107299             body = body.enter().append('div').attr('class', 'body').merge(body);
107300             var editor = body.selectAll('.data-editor').data([0]); // enter/update
107301
107302             editor.enter().append('div').attr('class', 'modal-section data-editor').merge(editor).call(dataHeader.datum(_datum));
107303             var rte = body.selectAll('.raw-tag-editor').data([0]); // enter/update
107304
107305             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);
107306           }
107307
107308           dataEditor.datum = function (val) {
107309             if (!arguments.length) return _datum;
107310             _datum = val;
107311             return this;
107312           };
107313
107314           return dataEditor;
107315         }
107316
107317         function uiOsmoseDetails(context) {
107318           var _qaItem;
107319
107320           function issueString(d, type) {
107321             if (!d) return ''; // Issue strings are cached from Osmose API
107322
107323             var s = services.osmose.getStrings(d.itemType);
107324             return type in s ? s[type] : '';
107325           }
107326
107327           function osmoseDetails(selection) {
107328             var details = selection.selectAll('.error-details').data(_qaItem ? [_qaItem] : [], function (d) {
107329               return "".concat(d.id, "-").concat(d.status || 0);
107330             });
107331             details.exit().remove();
107332             var detailsEnter = details.enter().append('div').attr('class', 'error-details qa-details-container'); // Description
107333
107334             if (issueString(_qaItem, 'detail')) {
107335               var div = detailsEnter.append('div').attr('class', 'qa-details-subsection');
107336               div.append('h4').call(_t.append('QA.keepRight.detail_description'));
107337               div.append('p').attr('class', 'qa-details-description-text').html(function (d) {
107338                 return issueString(d, 'detail');
107339               }).selectAll('a').attr('rel', 'noopener').attr('target', '_blank');
107340             } // Elements (populated later as data is requested)
107341
107342
107343             var detailsDiv = detailsEnter.append('div').attr('class', 'qa-details-subsection');
107344             var elemsDiv = detailsEnter.append('div').attr('class', 'qa-details-subsection'); // Suggested Fix (mustn't exist for every issue type)
107345
107346             if (issueString(_qaItem, 'fix')) {
107347               var _div = detailsEnter.append('div').attr('class', 'qa-details-subsection');
107348
107349               _div.append('h4').call(_t.append('QA.osmose.fix_title'));
107350
107351               _div.append('p').html(function (d) {
107352                 return issueString(d, 'fix');
107353               }).selectAll('a').attr('rel', 'noopener').attr('target', '_blank');
107354             } // Common Pitfalls (mustn't exist for every issue type)
107355
107356
107357             if (issueString(_qaItem, 'trap')) {
107358               var _div2 = detailsEnter.append('div').attr('class', 'qa-details-subsection');
107359
107360               _div2.append('h4').call(_t.append('QA.osmose.trap_title'));
107361
107362               _div2.append('p').html(function (d) {
107363                 return issueString(d, 'trap');
107364               }).selectAll('a').attr('rel', 'noopener').attr('target', '_blank');
107365             } // Save current item to check if UI changed by time request resolves
107366
107367
107368             var thisItem = _qaItem;
107369             services.osmose.loadIssueDetail(_qaItem).then(function (d) {
107370               // No details to add if there are no associated issue elements
107371               if (!d.elems || d.elems.length === 0) return; // Do nothing if UI has moved on by the time this resolves
107372
107373               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
107374
107375               if (d.detail) {
107376                 detailsDiv.append('h4').call(_t.append('QA.osmose.detail_title'));
107377                 detailsDiv.append('p').html(function (d) {
107378                   return d.detail;
107379                 }).selectAll('a').attr('rel', 'noopener').attr('target', '_blank');
107380               } // Create list of linked issue elements
107381
107382
107383               elemsDiv.append('h4').call(_t.append('QA.osmose.elems_title'));
107384               elemsDiv.append('ul').selectAll('li').data(d.elems).enter().append('li').append('a').attr('href', '#').attr('class', 'error_entity_link').text(function (d) {
107385                 return d;
107386               }).each(function () {
107387                 var link = select(this);
107388                 var entityID = this.textContent;
107389                 var entity = context.hasEntity(entityID); // Add click handler
107390
107391                 link.on('mouseenter', function () {
107392                   utilHighlightEntities([entityID], true, context);
107393                 }).on('mouseleave', function () {
107394                   utilHighlightEntities([entityID], false, context);
107395                 }).on('click', function (d3_event) {
107396                   d3_event.preventDefault();
107397                   utilHighlightEntities([entityID], false, context);
107398                   var osmlayer = context.layers().layer('osm');
107399
107400                   if (!osmlayer.enabled()) {
107401                     osmlayer.enabled(true);
107402                   }
107403
107404                   context.map().centerZoom(d.loc, 20);
107405
107406                   if (entity) {
107407                     context.enter(modeSelect(context, [entityID]));
107408                   } else {
107409                     context.loadEntity(entityID, function (err, result) {
107410                       if (err) return;
107411                       var entity = result.data.find(function (e) {
107412                         return e.id === entityID;
107413                       });
107414                       if (entity) context.enter(modeSelect(context, [entityID]));
107415                     });
107416                   }
107417                 }); // Replace with friendly name if possible
107418                 // (The entity may not yet be loaded into the graph)
107419
107420                 if (entity) {
107421                   var name = utilDisplayName(entity); // try to use common name
107422
107423                   if (!name) {
107424                     var preset = _mainPresetIndex.match(entity, context.graph());
107425                     name = preset && !preset.isFallback() && preset.name(); // fallback to preset name
107426                   }
107427
107428                   if (name) {
107429                     this.innerText = name;
107430                   }
107431                 }
107432               }); // Don't hide entities related to this issue - #5880
107433
107434               context.features().forceVisible(d.elems);
107435               context.map().pan([0, 0]); // trigger a redraw
107436             })["catch"](function (err) {
107437               console.log(err); // eslint-disable-line no-console
107438             });
107439           }
107440
107441           osmoseDetails.issue = function (val) {
107442             if (!arguments.length) return _qaItem;
107443             _qaItem = val;
107444             return osmoseDetails;
107445           };
107446
107447           return osmoseDetails;
107448         }
107449
107450         function uiOsmoseHeader() {
107451           var _qaItem;
107452
107453           function issueTitle(d) {
107454             var unknown = _t('inspector.unknown');
107455             if (!d) return unknown; // Issue titles supplied by Osmose
107456
107457             var s = services.osmose.getStrings(d.itemType);
107458             return 'title' in s ? s.title : unknown;
107459           }
107460
107461           function osmoseHeader(selection) {
107462             var header = selection.selectAll('.qa-header').data(_qaItem ? [_qaItem] : [], function (d) {
107463               return "".concat(d.id, "-").concat(d.status || 0);
107464             });
107465             header.exit().remove();
107466             var headerEnter = header.enter().append('div').attr('class', 'qa-header');
107467             var svgEnter = headerEnter.append('div').attr('class', 'qa-header-icon').classed('new', function (d) {
107468               return d.id < 0;
107469             }).append('svg').attr('width', '20px').attr('height', '30px').attr('viewbox', '0 0 20 30').attr('class', function (d) {
107470               return "preset-icon-28 qaItem ".concat(d.service, " itemId-").concat(d.id, " itemType-").concat(d.itemType);
107471             });
107472             svgEnter.append('polygon').attr('fill', function (d) {
107473               return services.osmose.getColor(d.item);
107474             }).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');
107475             svgEnter.append('use').attr('class', 'icon-annotation').attr('width', '13px').attr('height', '13px').attr('transform', 'translate(3.5, 5)').attr('xlink:href', function (d) {
107476               var picon = d.icon;
107477
107478               if (!picon) {
107479                 return '';
107480               } else {
107481                 var isMaki = /^maki-/.test(picon);
107482                 return "#".concat(picon).concat(isMaki ? '-11' : '');
107483               }
107484             });
107485             headerEnter.append('div').attr('class', 'qa-header-label').text(issueTitle);
107486           }
107487
107488           osmoseHeader.issue = function (val) {
107489             if (!arguments.length) return _qaItem;
107490             _qaItem = val;
107491             return osmoseHeader;
107492           };
107493
107494           return osmoseHeader;
107495         }
107496
107497         function uiViewOnOsmose() {
107498           var _qaItem;
107499
107500           function viewOnOsmose(selection) {
107501             var url;
107502
107503             if (services.osmose && _qaItem instanceof QAItem) {
107504               url = services.osmose.itemURL(_qaItem);
107505             }
107506
107507             var link = selection.selectAll('.view-on-osmose').data(url ? [url] : []); // exit
107508
107509             link.exit().remove(); // enter
107510
107511             var linkEnter = link.enter().append('a').attr('class', 'view-on-osmose').attr('target', '_blank').attr('rel', 'noopener') // security measure
107512             .attr('href', function (d) {
107513               return d;
107514             }).call(svgIcon('#iD-icon-out-link', 'inline'));
107515             linkEnter.append('span').call(_t.append('inspector.view_on_osmose'));
107516           }
107517
107518           viewOnOsmose.what = function (val) {
107519             if (!arguments.length) return _qaItem;
107520             _qaItem = val;
107521             return viewOnOsmose;
107522           };
107523
107524           return viewOnOsmose;
107525         }
107526
107527         function uiOsmoseEditor(context) {
107528           var dispatch = dispatch$8('change');
107529           var qaDetails = uiOsmoseDetails(context);
107530           var qaHeader = uiOsmoseHeader();
107531
107532           var _qaItem;
107533
107534           function osmoseEditor(selection) {
107535             var header = selection.selectAll('.header').data([0]);
107536             var headerEnter = header.enter().append('div').attr('class', 'header fillL');
107537             headerEnter.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
107538               return context.enter(modeBrowse(context));
107539             }).call(svgIcon('#iD-icon-close'));
107540             headerEnter.append('h2').call(_t.append('QA.osmose.title'));
107541             var body = selection.selectAll('.body').data([0]);
107542             body = body.enter().append('div').attr('class', 'body').merge(body);
107543             var editor = body.selectAll('.qa-editor').data([0]);
107544             editor.enter().append('div').attr('class', 'modal-section qa-editor').merge(editor).call(qaHeader.issue(_qaItem)).call(qaDetails.issue(_qaItem)).call(osmoseSaveSection);
107545             var footer = selection.selectAll('.footer').data([0]);
107546             footer.enter().append('div').attr('class', 'footer').merge(footer).call(uiViewOnOsmose().what(_qaItem));
107547           }
107548
107549           function osmoseSaveSection(selection) {
107550             var isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
107551
107552             var isShown = _qaItem && isSelected;
107553             var saveSection = selection.selectAll('.qa-save').data(isShown ? [_qaItem] : [], function (d) {
107554               return "".concat(d.id, "-").concat(d.status || 0);
107555             }); // exit
107556
107557             saveSection.exit().remove(); // enter
107558
107559             var saveSectionEnter = saveSection.enter().append('div').attr('class', 'qa-save save-section cf'); // update
107560
107561             saveSection = saveSectionEnter.merge(saveSection).call(qaSaveButtons);
107562           }
107563
107564           function qaSaveButtons(selection) {
107565             var isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
107566
107567             var buttonSection = selection.selectAll('.buttons').data(isSelected ? [_qaItem] : [], function (d) {
107568               return d.status + d.id;
107569             }); // exit
107570
107571             buttonSection.exit().remove(); // enter
107572
107573             var buttonEnter = buttonSection.enter().append('div').attr('class', 'buttons');
107574             buttonEnter.append('button').attr('class', 'button close-button action');
107575             buttonEnter.append('button').attr('class', 'button ignore-button action'); // update
107576
107577             buttonSection = buttonSection.merge(buttonEnter);
107578             buttonSection.select('.close-button').call(_t.append('QA.keepRight.close')).on('click.close', function (d3_event, d) {
107579               this.blur(); // avoid keeping focus on the button - #4641
107580
107581               var qaService = services.osmose;
107582
107583               if (qaService) {
107584                 d.newStatus = 'done';
107585                 qaService.postUpdate(d, function (err, item) {
107586                   return dispatch.call('change', item);
107587                 });
107588               }
107589             });
107590             buttonSection.select('.ignore-button').call(_t.append('QA.keepRight.ignore')).on('click.ignore', function (d3_event, d) {
107591               this.blur(); // avoid keeping focus on the button - #4641
107592
107593               var qaService = services.osmose;
107594
107595               if (qaService) {
107596                 d.newStatus = 'false';
107597                 qaService.postUpdate(d, function (err, item) {
107598                   return dispatch.call('change', item);
107599                 });
107600               }
107601             });
107602           } // NOTE: Don't change method name until UI v3 is merged
107603
107604
107605           osmoseEditor.error = function (val) {
107606             if (!arguments.length) return _qaItem;
107607             _qaItem = val;
107608             return osmoseEditor;
107609           };
107610
107611           return utilRebind(osmoseEditor, dispatch, 'on');
107612         }
107613
107614         function uiSidebar(context) {
107615           var inspector = uiInspector(context);
107616           var dataEditor = uiDataEditor(context);
107617           var noteEditor = uiNoteEditor(context);
107618           var improveOsmEditor = uiImproveOsmEditor(context);
107619           var keepRightEditor = uiKeepRightEditor(context);
107620           var osmoseEditor = uiOsmoseEditor(context);
107621
107622           var _current;
107623
107624           var _wasData = false;
107625           var _wasNote = false;
107626           var _wasQaItem = false; // use pointer events on supported platforms; fallback to mouse events
107627
107628           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
107629
107630           function sidebar(selection) {
107631             var container = context.container();
107632             var minWidth = 240;
107633             var sidebarWidth;
107634             var containerWidth;
107635             var dragOffset; // Set the initial width constraints
107636
107637             selection.style('min-width', minWidth + 'px').style('max-width', '400px').style('width', '33.3333%');
107638             var resizer = selection.append('div').attr('class', 'sidebar-resizer').on(_pointerPrefix + 'down.sidebar-resizer', pointerdown);
107639             var downPointerId, lastClientX, containerLocGetter;
107640
107641             function pointerdown(d3_event) {
107642               if (downPointerId) return;
107643               if ('button' in d3_event && d3_event.button !== 0) return;
107644               downPointerId = d3_event.pointerId || 'mouse';
107645               lastClientX = d3_event.clientX;
107646               containerLocGetter = utilFastMouse(container.node()); // offset from edge of sidebar-resizer
107647
107648               dragOffset = utilFastMouse(resizer.node())(d3_event)[0] - 1;
107649               sidebarWidth = selection.node().getBoundingClientRect().width;
107650               containerWidth = container.node().getBoundingClientRect().width;
107651               var widthPct = sidebarWidth / containerWidth * 100;
107652               selection.style('width', widthPct + '%') // lock in current width
107653               .style('max-width', '85%'); // but allow larger widths
107654
107655               resizer.classed('dragging', true);
107656               select(window).on('touchmove.sidebar-resizer', function (d3_event) {
107657                 // disable page scrolling while resizing on touch input
107658                 d3_event.preventDefault();
107659               }, {
107660                 passive: false
107661               }).on(_pointerPrefix + 'move.sidebar-resizer', pointermove).on(_pointerPrefix + 'up.sidebar-resizer pointercancel.sidebar-resizer', pointerup);
107662             }
107663
107664             function pointermove(d3_event) {
107665               if (downPointerId !== (d3_event.pointerId || 'mouse')) return;
107666               d3_event.preventDefault();
107667               var dx = d3_event.clientX - lastClientX;
107668               lastClientX = d3_event.clientX;
107669               var isRTL = _mainLocalizer.textDirection() === 'rtl';
107670               var scaleX = isRTL ? 0 : 1;
107671               var xMarginProperty = isRTL ? 'margin-right' : 'margin-left';
107672               var x = containerLocGetter(d3_event)[0] - dragOffset;
107673               sidebarWidth = isRTL ? containerWidth - x : x;
107674               var isCollapsed = selection.classed('collapsed');
107675               var shouldCollapse = sidebarWidth < minWidth;
107676               selection.classed('collapsed', shouldCollapse);
107677
107678               if (shouldCollapse) {
107679                 if (!isCollapsed) {
107680                   selection.style(xMarginProperty, '-400px').style('width', '400px');
107681                   context.ui().onResize([(sidebarWidth - dx) * scaleX, 0]);
107682                 }
107683               } else {
107684                 var widthPct = sidebarWidth / containerWidth * 100;
107685                 selection.style(xMarginProperty, null).style('width', widthPct + '%');
107686
107687                 if (isCollapsed) {
107688                   context.ui().onResize([-sidebarWidth * scaleX, 0]);
107689                 } else {
107690                   context.ui().onResize([-dx * scaleX, 0]);
107691                 }
107692               }
107693             }
107694
107695             function pointerup(d3_event) {
107696               if (downPointerId !== (d3_event.pointerId || 'mouse')) return;
107697               downPointerId = null;
107698               resizer.classed('dragging', false);
107699               select(window).on('touchmove.sidebar-resizer', null).on(_pointerPrefix + 'move.sidebar-resizer', null).on(_pointerPrefix + 'up.sidebar-resizer pointercancel.sidebar-resizer', null);
107700             }
107701
107702             var featureListWrap = selection.append('div').attr('class', 'feature-list-pane').call(uiFeatureList(context));
107703             var inspectorWrap = selection.append('div').attr('class', 'inspector-hidden inspector-wrap');
107704
107705             var hoverModeSelect = function hoverModeSelect(targets) {
107706               context.container().selectAll('.feature-list-item button').classed('hover', false);
107707
107708               if (context.selectedIDs().length > 1 && targets && targets.length) {
107709                 var elements = context.container().selectAll('.feature-list-item button').filter(function (node) {
107710                   return targets.indexOf(node) !== -1;
107711                 });
107712
107713                 if (!elements.empty()) {
107714                   elements.classed('hover', true);
107715                 }
107716               }
107717             };
107718
107719             sidebar.hoverModeSelect = throttle(hoverModeSelect, 200);
107720
107721             function hover(targets) {
107722               var datum = targets && targets.length && targets[0];
107723
107724               if (datum && datum.__featurehash__) {
107725                 // hovering on data
107726                 _wasData = true;
107727                 sidebar.show(dataEditor.datum(datum));
107728                 selection.selectAll('.sidebar-component').classed('inspector-hover', true);
107729               } else if (datum instanceof osmNote) {
107730                 if (context.mode().id === 'drag-note') return;
107731                 _wasNote = true;
107732                 var osm = services.osm;
107733
107734                 if (osm) {
107735                   datum = osm.getNote(datum.id); // marker may contain stale data - get latest
107736                 }
107737
107738                 sidebar.show(noteEditor.note(datum));
107739                 selection.selectAll('.sidebar-component').classed('inspector-hover', true);
107740               } else if (datum instanceof QAItem) {
107741                 _wasQaItem = true;
107742                 var errService = services[datum.service];
107743
107744                 if (errService) {
107745                   // marker may contain stale data - get latest
107746                   datum = errService.getError(datum.id);
107747                 } // Currently only three possible services
107748
107749
107750                 var errEditor;
107751
107752                 if (datum.service === 'keepRight') {
107753                   errEditor = keepRightEditor;
107754                 } else if (datum.service === 'osmose') {
107755                   errEditor = osmoseEditor;
107756                 } else {
107757                   errEditor = improveOsmEditor;
107758                 }
107759
107760                 context.container().selectAll('.qaItem.' + datum.service).classed('hover', function (d) {
107761                   return d.id === datum.id;
107762                 });
107763                 sidebar.show(errEditor.error(datum));
107764                 selection.selectAll('.sidebar-component').classed('inspector-hover', true);
107765               } else if (!_current && datum instanceof osmEntity) {
107766                 featureListWrap.classed('inspector-hidden', true);
107767                 inspectorWrap.classed('inspector-hidden', false).classed('inspector-hover', true);
107768
107769                 if (!inspector.entityIDs() || !utilArrayIdentical(inspector.entityIDs(), [datum.id]) || inspector.state() !== 'hover') {
107770                   inspector.state('hover').entityIDs([datum.id]).newFeature(false);
107771                   inspectorWrap.call(inspector);
107772                 }
107773               } else if (!_current) {
107774                 featureListWrap.classed('inspector-hidden', false);
107775                 inspectorWrap.classed('inspector-hidden', true);
107776                 inspector.state('hide');
107777               } else if (_wasData || _wasNote || _wasQaItem) {
107778                 _wasNote = false;
107779                 _wasData = false;
107780                 _wasQaItem = false;
107781                 context.container().selectAll('.note').classed('hover', false);
107782                 context.container().selectAll('.qaItem').classed('hover', false);
107783                 sidebar.hide();
107784               }
107785             }
107786
107787             sidebar.hover = throttle(hover, 200);
107788
107789             sidebar.intersects = function (extent) {
107790               var rect = selection.node().getBoundingClientRect();
107791               return extent.intersects([context.projection.invert([0, rect.height]), context.projection.invert([rect.width, 0])]);
107792             };
107793
107794             sidebar.select = function (ids, newFeature) {
107795               sidebar.hide();
107796
107797               if (ids && ids.length) {
107798                 var entity = ids.length === 1 && context.entity(ids[0]);
107799
107800                 if (entity && newFeature && selection.classed('collapsed')) {
107801                   // uncollapse the sidebar
107802                   var extent = entity.extent(context.graph());
107803                   sidebar.expand(sidebar.intersects(extent));
107804                 }
107805
107806                 featureListWrap.classed('inspector-hidden', true);
107807                 inspectorWrap.classed('inspector-hidden', false).classed('inspector-hover', false); // reload the UI even if the ids are the same since the entities
107808                 // themselves may have changed
107809
107810                 inspector.state('select').entityIDs(ids).newFeature(newFeature);
107811                 inspectorWrap.call(inspector);
107812               } else {
107813                 inspector.state('hide');
107814               }
107815             };
107816
107817             sidebar.showPresetList = function () {
107818               inspector.showList();
107819             };
107820
107821             sidebar.show = function (component, element) {
107822               featureListWrap.classed('inspector-hidden', true);
107823               inspectorWrap.classed('inspector-hidden', true);
107824               if (_current) _current.remove();
107825               _current = selection.append('div').attr('class', 'sidebar-component').call(component, element);
107826             };
107827
107828             sidebar.hide = function () {
107829               featureListWrap.classed('inspector-hidden', false);
107830               inspectorWrap.classed('inspector-hidden', true);
107831               if (_current) _current.remove();
107832               _current = null;
107833             };
107834
107835             sidebar.expand = function (moveMap) {
107836               if (selection.classed('collapsed')) {
107837                 sidebar.toggle(moveMap);
107838               }
107839             };
107840
107841             sidebar.collapse = function (moveMap) {
107842               if (!selection.classed('collapsed')) {
107843                 sidebar.toggle(moveMap);
107844               }
107845             };
107846
107847             sidebar.toggle = function (moveMap) {
107848               // Don't allow sidebar to toggle when the user is in the walkthrough.
107849               if (context.inIntro()) return;
107850               var isCollapsed = selection.classed('collapsed');
107851               var isCollapsing = !isCollapsed;
107852               var isRTL = _mainLocalizer.textDirection() === 'rtl';
107853               var scaleX = isRTL ? 0 : 1;
107854               var xMarginProperty = isRTL ? 'margin-right' : 'margin-left';
107855               sidebarWidth = selection.node().getBoundingClientRect().width; // switch from % to px
107856
107857               selection.style('width', sidebarWidth + 'px');
107858               var startMargin, endMargin, lastMargin;
107859
107860               if (isCollapsing) {
107861                 startMargin = lastMargin = 0;
107862                 endMargin = -sidebarWidth;
107863               } else {
107864                 startMargin = lastMargin = -sidebarWidth;
107865                 endMargin = 0;
107866               }
107867
107868               if (!isCollapsing) {
107869                 // unhide the sidebar's content before it transitions onscreen
107870                 selection.classed('collapsed', isCollapsing);
107871               }
107872
107873               selection.transition().style(xMarginProperty, endMargin + 'px').tween('panner', function () {
107874                 var i = d3_interpolateNumber(startMargin, endMargin);
107875                 return function (t) {
107876                   var dx = lastMargin - Math.round(i(t));
107877                   lastMargin = lastMargin - dx;
107878                   context.ui().onResize(moveMap ? undefined : [dx * scaleX, 0]);
107879                 };
107880               }).on('end', function () {
107881                 if (isCollapsing) {
107882                   // hide the sidebar's content after it transitions offscreen
107883                   selection.classed('collapsed', isCollapsing);
107884                 } // switch back from px to %
107885
107886
107887                 if (!isCollapsing) {
107888                   var containerWidth = container.node().getBoundingClientRect().width;
107889                   var widthPct = sidebarWidth / containerWidth * 100;
107890                   selection.style(xMarginProperty, null).style('width', widthPct + '%');
107891                 }
107892               });
107893             }; // toggle the sidebar collapse when double-clicking the resizer
107894
107895
107896             resizer.on('dblclick', function (d3_event) {
107897               d3_event.preventDefault();
107898
107899               if (d3_event.sourceEvent) {
107900                 d3_event.sourceEvent.preventDefault();
107901               }
107902
107903               sidebar.toggle();
107904             }); // ensure hover sidebar is closed when zooming out beyond editable zoom
107905
107906             context.map().on('crossEditableZoom.sidebar', function (within) {
107907               if (!within && !selection.select('.inspector-hover').empty()) {
107908                 hover([]);
107909               }
107910             });
107911           }
107912
107913           sidebar.showPresetList = function () {};
107914
107915           sidebar.hover = function () {};
107916
107917           sidebar.hover.cancel = function () {};
107918
107919           sidebar.intersects = function () {};
107920
107921           sidebar.select = function () {};
107922
107923           sidebar.show = function () {};
107924
107925           sidebar.hide = function () {};
107926
107927           sidebar.expand = function () {};
107928
107929           sidebar.collapse = function () {};
107930
107931           sidebar.toggle = function () {};
107932
107933           return sidebar;
107934         }
107935
107936         function modeDrawArea(context, wayID, startGraph, button) {
107937           var mode = {
107938             button: button,
107939             id: 'draw-area'
107940           };
107941           var behavior = behaviorDrawWay(context, wayID, mode, startGraph).on('rejectedSelfIntersection.modeDrawArea', function () {
107942             context.ui().flash.iconName('#iD-icon-no').label(_t.html('self_intersection.error.areas'))();
107943           });
107944           mode.wayID = wayID;
107945
107946           mode.enter = function () {
107947             context.install(behavior);
107948           };
107949
107950           mode.exit = function () {
107951             context.uninstall(behavior);
107952           };
107953
107954           mode.selectedIDs = function () {
107955             return [wayID];
107956           };
107957
107958           mode.activeID = function () {
107959             return behavior && behavior.activeID() || [];
107960           };
107961
107962           return mode;
107963         }
107964
107965         function modeAddArea(context, mode) {
107966           mode.id = 'add-area';
107967           var behavior = behaviorAddWay(context).on('start', start).on('startFromWay', startFromWay).on('startFromNode', startFromNode);
107968           var defaultTags = {
107969             area: 'yes'
107970           };
107971           if (mode.preset) defaultTags = mode.preset.setTags(defaultTags, 'area');
107972
107973           function actionClose(wayId) {
107974             return function (graph) {
107975               return graph.replace(graph.entity(wayId).close());
107976             };
107977           }
107978
107979           function start(loc) {
107980             var startGraph = context.graph();
107981             var node = osmNode({
107982               loc: loc
107983             });
107984             var way = osmWay({
107985               tags: defaultTags
107986             });
107987             context.perform(actionAddEntity(node), actionAddEntity(way), actionAddVertex(way.id, node.id), actionClose(way.id));
107988             context.enter(modeDrawArea(context, way.id, startGraph, mode.button));
107989           }
107990
107991           function startFromWay(loc, edge) {
107992             var startGraph = context.graph();
107993             var node = osmNode({
107994               loc: loc
107995             });
107996             var way = osmWay({
107997               tags: defaultTags
107998             });
107999             context.perform(actionAddEntity(node), actionAddEntity(way), actionAddVertex(way.id, node.id), actionClose(way.id), actionAddMidpoint({
108000               loc: loc,
108001               edge: edge
108002             }, node));
108003             context.enter(modeDrawArea(context, way.id, startGraph, mode.button));
108004           }
108005
108006           function startFromNode(node) {
108007             var startGraph = context.graph();
108008             var way = osmWay({
108009               tags: defaultTags
108010             });
108011             context.perform(actionAddEntity(way), actionAddVertex(way.id, node.id), actionClose(way.id));
108012             context.enter(modeDrawArea(context, way.id, startGraph, mode.button));
108013           }
108014
108015           mode.enter = function () {
108016             context.install(behavior);
108017           };
108018
108019           mode.exit = function () {
108020             context.uninstall(behavior);
108021           };
108022
108023           return mode;
108024         }
108025
108026         function modeAddLine(context, mode) {
108027           mode.id = 'add-line';
108028           var behavior = behaviorAddWay(context).on('start', start).on('startFromWay', startFromWay).on('startFromNode', startFromNode);
108029           var defaultTags = {};
108030           if (mode.preset) defaultTags = mode.preset.setTags(defaultTags, 'line');
108031
108032           function start(loc) {
108033             var startGraph = context.graph();
108034             var node = osmNode({
108035               loc: loc
108036             });
108037             var way = osmWay({
108038               tags: defaultTags
108039             });
108040             context.perform(actionAddEntity(node), actionAddEntity(way), actionAddVertex(way.id, node.id));
108041             context.enter(modeDrawLine(context, way.id, startGraph, mode.button));
108042           }
108043
108044           function startFromWay(loc, edge) {
108045             var startGraph = context.graph();
108046             var node = osmNode({
108047               loc: loc
108048             });
108049             var way = osmWay({
108050               tags: defaultTags
108051             });
108052             context.perform(actionAddEntity(node), actionAddEntity(way), actionAddVertex(way.id, node.id), actionAddMidpoint({
108053               loc: loc,
108054               edge: edge
108055             }, node));
108056             context.enter(modeDrawLine(context, way.id, startGraph, mode.button));
108057           }
108058
108059           function startFromNode(node) {
108060             var startGraph = context.graph();
108061             var way = osmWay({
108062               tags: defaultTags
108063             });
108064             context.perform(actionAddEntity(way), actionAddVertex(way.id, node.id));
108065             context.enter(modeDrawLine(context, way.id, startGraph, mode.button));
108066           }
108067
108068           mode.enter = function () {
108069             context.install(behavior);
108070           };
108071
108072           mode.exit = function () {
108073             context.uninstall(behavior);
108074           };
108075
108076           return mode;
108077         }
108078
108079         function modeAddPoint(context, mode) {
108080           mode.id = 'add-point';
108081           var behavior = behaviorDraw(context).on('click', add).on('clickWay', addWay).on('clickNode', addNode).on('cancel', cancel).on('finish', cancel);
108082           var defaultTags = {};
108083           if (mode.preset) defaultTags = mode.preset.setTags(defaultTags, 'point');
108084
108085           function add(loc) {
108086             var node = osmNode({
108087               loc: loc,
108088               tags: defaultTags
108089             });
108090             context.perform(actionAddEntity(node), _t('operations.add.annotation.point'));
108091             enterSelectMode(node);
108092           }
108093
108094           function addWay(loc, edge) {
108095             var node = osmNode({
108096               tags: defaultTags
108097             });
108098             context.perform(actionAddMidpoint({
108099               loc: loc,
108100               edge: edge
108101             }, node), _t('operations.add.annotation.vertex'));
108102             enterSelectMode(node);
108103           }
108104
108105           function enterSelectMode(node) {
108106             context.enter(modeSelect(context, [node.id]).newFeature(true));
108107           }
108108
108109           function addNode(node) {
108110             if (Object.keys(defaultTags).length === 0) {
108111               enterSelectMode(node);
108112               return;
108113             }
108114
108115             var tags = Object.assign({}, node.tags); // shallow copy
108116
108117             for (var key in defaultTags) {
108118               tags[key] = defaultTags[key];
108119             }
108120
108121             context.perform(actionChangeTags(node.id, tags), _t('operations.add.annotation.point'));
108122             enterSelectMode(node);
108123           }
108124
108125           function cancel() {
108126             context.enter(modeBrowse(context));
108127           }
108128
108129           mode.enter = function () {
108130             context.install(behavior);
108131           };
108132
108133           mode.exit = function () {
108134             context.uninstall(behavior);
108135           };
108136
108137           return mode;
108138         }
108139
108140         function modeSelectNote(context, selectedNoteID) {
108141           var mode = {
108142             id: 'select-note',
108143             button: 'browse'
108144           };
108145
108146           var _keybinding = utilKeybinding('select-note');
108147
108148           var _noteEditor = uiNoteEditor(context).on('change', function () {
108149             context.map().pan([0, 0]); // trigger a redraw
108150
108151             var note = checkSelectedID();
108152             if (!note) return;
108153             context.ui().sidebar.show(_noteEditor.note(note));
108154           });
108155
108156           var _behaviors = [behaviorBreathe(), behaviorHover(context), behaviorSelect(context), behaviorLasso(context), modeDragNode(context).behavior, modeDragNote(context).behavior];
108157           var _newFeature = false;
108158
108159           function checkSelectedID() {
108160             if (!services.osm) return;
108161             var note = services.osm.getNote(selectedNoteID);
108162
108163             if (!note) {
108164               context.enter(modeBrowse(context));
108165             }
108166
108167             return note;
108168           } // class the note as selected, or return to browse mode if the note is gone
108169
108170
108171           function selectNote(d3_event, drawn) {
108172             if (!checkSelectedID()) return;
108173             var selection = context.surface().selectAll('.layer-notes .note-' + selectedNoteID);
108174
108175             if (selection.empty()) {
108176               // Return to browse mode if selected DOM elements have
108177               // disappeared because the user moved them out of view..
108178               var source = d3_event && d3_event.type === 'zoom' && d3_event.sourceEvent;
108179
108180               if (drawn && source && (source.type === 'pointermove' || source.type === 'mousemove' || source.type === 'touchmove')) {
108181                 context.enter(modeBrowse(context));
108182               }
108183             } else {
108184               selection.classed('selected', true);
108185               context.selectedNoteID(selectedNoteID);
108186             }
108187           }
108188
108189           function esc() {
108190             if (context.container().select('.combobox').size()) return;
108191             context.enter(modeBrowse(context));
108192           }
108193
108194           mode.zoomToSelected = function () {
108195             if (!services.osm) return;
108196             var note = services.osm.getNote(selectedNoteID);
108197
108198             if (note) {
108199               context.map().centerZoomEase(note.loc, 20);
108200             }
108201           };
108202
108203           mode.newFeature = function (val) {
108204             if (!arguments.length) return _newFeature;
108205             _newFeature = val;
108206             return mode;
108207           };
108208
108209           mode.enter = function () {
108210             var note = checkSelectedID();
108211             if (!note) return;
108212
108213             _behaviors.forEach(context.install);
108214
108215             _keybinding.on(_t('inspector.zoom_to.key'), mode.zoomToSelected).on('⎋', esc, true);
108216
108217             select(document).call(_keybinding);
108218             selectNote();
108219             var sidebar = context.ui().sidebar;
108220             sidebar.show(_noteEditor.note(note).newNote(_newFeature)); // expand the sidebar, avoid obscuring the note if needed
108221
108222             sidebar.expand(sidebar.intersects(note.extent()));
108223             context.map().on('drawn.select', selectNote);
108224           };
108225
108226           mode.exit = function () {
108227             _behaviors.forEach(context.uninstall);
108228
108229             select(document).call(_keybinding.unbind);
108230             context.surface().selectAll('.layer-notes .selected').classed('selected hover', false);
108231             context.map().on('drawn.select', null);
108232             context.ui().sidebar.hide();
108233             context.selectedNoteID(null);
108234           };
108235
108236           return mode;
108237         }
108238
108239         function modeAddNote(context) {
108240           var mode = {
108241             id: 'add-note',
108242             button: 'note',
108243             description: _t.html('modes.add_note.description'),
108244             key: _t('modes.add_note.key')
108245           };
108246           var behavior = behaviorDraw(context).on('click', add).on('cancel', cancel).on('finish', cancel);
108247
108248           function add(loc) {
108249             var osm = services.osm;
108250             if (!osm) return;
108251             var note = osmNote({
108252               loc: loc,
108253               status: 'open',
108254               comments: []
108255             });
108256             osm.replaceNote(note); // force a reraw (there is no history change that would otherwise do this)
108257
108258             context.map().pan([0, 0]);
108259             context.selectedNoteID(note.id).enter(modeSelectNote(context, note.id).newFeature(true));
108260           }
108261
108262           function cancel() {
108263             context.enter(modeBrowse(context));
108264           }
108265
108266           mode.enter = function () {
108267             context.install(behavior);
108268           };
108269
108270           mode.exit = function () {
108271             context.uninstall(behavior);
108272           };
108273
108274           return mode;
108275         }
108276
108277         function modeSave(context) {
108278           var mode = {
108279             id: 'save'
108280           };
108281           var keybinding = utilKeybinding('modeSave');
108282           var commit = uiCommit(context).on('cancel', cancel);
108283
108284           var _conflictsUi; // uiConflicts
108285
108286
108287           var _location;
108288
108289           var _success;
108290
108291           var uploader = context.uploader().on('saveStarted.modeSave', function () {
108292             keybindingOff();
108293           }) // fire off some async work that we want to be ready later
108294           .on('willAttemptUpload.modeSave', prepareForSuccess).on('progressChanged.modeSave', showProgress).on('resultNoChanges.modeSave', function () {
108295             cancel();
108296           }).on('resultErrors.modeSave', showErrors).on('resultConflicts.modeSave', showConflicts).on('resultSuccess.modeSave', showSuccess);
108297
108298           function cancel() {
108299             context.enter(modeBrowse(context));
108300           }
108301
108302           function showProgress(num, total) {
108303             var modal = context.container().select('.loading-modal .modal-section');
108304             var progress = modal.selectAll('.progress').data([0]); // enter/update
108305
108306             progress.enter().append('div').attr('class', 'progress').merge(progress).text(_t('save.conflict_progress', {
108307               num: num,
108308               total: total
108309             }));
108310           }
108311
108312           function showConflicts(changeset, conflicts, origChanges) {
108313             var selection = context.container().select('.sidebar').append('div').attr('class', 'sidebar-component');
108314             context.container().selectAll('.main-content').classed('active', true).classed('inactive', false);
108315             _conflictsUi = uiConflicts(context).conflictList(conflicts).origChanges(origChanges).on('cancel', function () {
108316               context.container().selectAll('.main-content').classed('active', false).classed('inactive', true);
108317               selection.remove();
108318               keybindingOn();
108319               uploader.cancelConflictResolution();
108320             }).on('save', function () {
108321               context.container().selectAll('.main-content').classed('active', false).classed('inactive', true);
108322               selection.remove();
108323               uploader.processResolvedConflicts(changeset);
108324             });
108325             selection.call(_conflictsUi);
108326           }
108327
108328           function showErrors(errors) {
108329             keybindingOn();
108330             var selection = uiConfirm(context.container());
108331             selection.select('.modal-section.header').append('h3').text(_t('save.error'));
108332             addErrors(selection, errors);
108333             selection.okButton();
108334           }
108335
108336           function addErrors(selection, data) {
108337             var message = selection.select('.modal-section.message-text');
108338             var items = message.selectAll('.error-container').data(data);
108339             var enter = items.enter().append('div').attr('class', 'error-container');
108340             enter.append('a').attr('class', 'error-description').attr('href', '#').classed('hide-toggle', true).text(function (d) {
108341               return d.msg || _t('save.unknown_error_details');
108342             }).on('click', function (d3_event) {
108343               d3_event.preventDefault();
108344               var error = select(this);
108345               var detail = select(this.nextElementSibling);
108346               var exp = error.classed('expanded');
108347               detail.style('display', exp ? 'none' : 'block');
108348               error.classed('expanded', !exp);
108349             });
108350             var details = enter.append('div').attr('class', 'error-detail-container').style('display', 'none');
108351             details.append('ul').attr('class', 'error-detail-list').selectAll('li').data(function (d) {
108352               return d.details || [];
108353             }).enter().append('li').attr('class', 'error-detail-item').text(function (d) {
108354               return d;
108355             });
108356             items.exit().remove();
108357           }
108358
108359           function showSuccess(changeset) {
108360             commit.reset();
108361
108362             var ui = _success.changeset(changeset).location(_location).on('cancel', function () {
108363               context.ui().sidebar.hide();
108364             });
108365
108366             context.enter(modeBrowse(context).sidebar(ui));
108367           }
108368
108369           function keybindingOn() {
108370             select(document).call(keybinding.on('⎋', cancel, true));
108371           }
108372
108373           function keybindingOff() {
108374             select(document).call(keybinding.unbind);
108375           } // Reverse geocode current map location so we can display a message on
108376           // the success screen like "Thank you for editing around place, region."
108377
108378
108379           function prepareForSuccess() {
108380             _success = uiSuccess(context);
108381             _location = null;
108382             if (!services.geocoder) return;
108383             services.geocoder.reverse(context.map().center(), function (err, result) {
108384               if (err || !result || !result.address) return;
108385               var addr = result.address;
108386               var place = addr && (addr.town || addr.city || addr.county) || '';
108387               var region = addr && (addr.state || addr.country) || '';
108388               var separator = place && region ? _t('success.thank_you_where.separator') : '';
108389               _location = _t('success.thank_you_where.format', {
108390                 place: place,
108391                 separator: separator,
108392                 region: region
108393               });
108394             });
108395           }
108396
108397           mode.selectedIDs = function () {
108398             return _conflictsUi ? _conflictsUi.shownEntityIds() : [];
108399           };
108400
108401           mode.enter = function () {
108402             // Show sidebar
108403             context.ui().sidebar.expand();
108404
108405             function done() {
108406               context.ui().sidebar.show(commit);
108407             }
108408
108409             keybindingOn();
108410             context.container().selectAll('.main-content').classed('active', false).classed('inactive', true);
108411             var osm = context.connection();
108412
108413             if (!osm) {
108414               cancel();
108415               return;
108416             }
108417
108418             if (osm.authenticated()) {
108419               done();
108420             } else {
108421               osm.authenticate(function (err) {
108422                 if (err) {
108423                   cancel();
108424                 } else {
108425                   done();
108426                 }
108427               });
108428             }
108429           };
108430
108431           mode.exit = function () {
108432             keybindingOff();
108433             context.container().selectAll('.main-content').classed('active', true).classed('inactive', false);
108434             context.ui().sidebar.hide();
108435           };
108436
108437           return mode;
108438         }
108439
108440         function modeSelectError(context, selectedErrorID, selectedErrorService) {
108441           var mode = {
108442             id: 'select-error',
108443             button: 'browse'
108444           };
108445           var keybinding = utilKeybinding('select-error');
108446           var errorService = services[selectedErrorService];
108447           var errorEditor;
108448
108449           switch (selectedErrorService) {
108450             case 'improveOSM':
108451               errorEditor = uiImproveOsmEditor(context).on('change', function () {
108452                 context.map().pan([0, 0]); // trigger a redraw
108453
108454                 var error = checkSelectedID();
108455                 if (!error) return;
108456                 context.ui().sidebar.show(errorEditor.error(error));
108457               });
108458               break;
108459
108460             case 'keepRight':
108461               errorEditor = uiKeepRightEditor(context).on('change', function () {
108462                 context.map().pan([0, 0]); // trigger a redraw
108463
108464                 var error = checkSelectedID();
108465                 if (!error) return;
108466                 context.ui().sidebar.show(errorEditor.error(error));
108467               });
108468               break;
108469
108470             case 'osmose':
108471               errorEditor = uiOsmoseEditor(context).on('change', function () {
108472                 context.map().pan([0, 0]); // trigger a redraw
108473
108474                 var error = checkSelectedID();
108475                 if (!error) return;
108476                 context.ui().sidebar.show(errorEditor.error(error));
108477               });
108478               break;
108479           }
108480
108481           var behaviors = [behaviorBreathe(), behaviorHover(context), behaviorSelect(context), behaviorLasso(context), modeDragNode(context).behavior, modeDragNote(context).behavior];
108482
108483           function checkSelectedID() {
108484             if (!errorService) return;
108485             var error = errorService.getError(selectedErrorID);
108486
108487             if (!error) {
108488               context.enter(modeBrowse(context));
108489             }
108490
108491             return error;
108492           }
108493
108494           mode.zoomToSelected = function () {
108495             if (!errorService) return;
108496             var error = errorService.getError(selectedErrorID);
108497
108498             if (error) {
108499               context.map().centerZoomEase(error.loc, 20);
108500             }
108501           };
108502
108503           mode.enter = function () {
108504             var error = checkSelectedID();
108505             if (!error) return;
108506             behaviors.forEach(context.install);
108507             keybinding.on(_t('inspector.zoom_to.key'), mode.zoomToSelected).on('⎋', esc, true);
108508             select(document).call(keybinding);
108509             selectError();
108510             var sidebar = context.ui().sidebar;
108511             sidebar.show(errorEditor.error(error));
108512             context.map().on('drawn.select-error', selectError); // class the error as selected, or return to browse mode if the error is gone
108513
108514             function selectError(d3_event, drawn) {
108515               if (!checkSelectedID()) return;
108516               var selection = context.surface().selectAll('.itemId-' + selectedErrorID + '.' + selectedErrorService);
108517
108518               if (selection.empty()) {
108519                 // Return to browse mode if selected DOM elements have
108520                 // disappeared because the user moved them out of view..
108521                 var source = d3_event && d3_event.type === 'zoom' && d3_event.sourceEvent;
108522
108523                 if (drawn && source && (source.type === 'pointermove' || source.type === 'mousemove' || source.type === 'touchmove')) {
108524                   context.enter(modeBrowse(context));
108525                 }
108526               } else {
108527                 selection.classed('selected', true);
108528                 context.selectedErrorID(selectedErrorID);
108529               }
108530             }
108531
108532             function esc() {
108533               if (context.container().select('.combobox').size()) return;
108534               context.enter(modeBrowse(context));
108535             }
108536           };
108537
108538           mode.exit = function () {
108539             behaviors.forEach(context.uninstall);
108540             select(document).call(keybinding.unbind);
108541             context.surface().selectAll('.qaItem.selected').classed('selected hover', false);
108542             context.map().on('drawn.select-error', null);
108543             context.ui().sidebar.hide();
108544             context.selectedErrorID(null);
108545             context.features().forceVisible([]);
108546           };
108547
108548           return mode;
108549         }
108550
108551         function uiToolOldDrawModes(context) {
108552           var tool = {
108553             id: 'old_modes',
108554             label: _t.html('toolbar.add_feature')
108555           };
108556           var modes = [modeAddPoint(context, {
108557             title: _t.html('modes.add_point.title'),
108558             button: 'point',
108559             description: _t.html('modes.add_point.description'),
108560             preset: _mainPresetIndex.item('point'),
108561             key: '1'
108562           }), modeAddLine(context, {
108563             title: _t.html('modes.add_line.title'),
108564             button: 'line',
108565             description: _t.html('modes.add_line.description'),
108566             preset: _mainPresetIndex.item('line'),
108567             key: '2'
108568           }), modeAddArea(context, {
108569             title: _t.html('modes.add_area.title'),
108570             button: 'area',
108571             description: _t.html('modes.add_area.description'),
108572             preset: _mainPresetIndex.item('area'),
108573             key: '3'
108574           })];
108575
108576           function enabled() {
108577             return osmEditable();
108578           }
108579
108580           function osmEditable() {
108581             return context.editable();
108582           }
108583
108584           modes.forEach(function (mode) {
108585             context.keybinding().on(mode.key, function () {
108586               if (!enabled()) return;
108587
108588               if (mode.id === context.mode().id) {
108589                 context.enter(modeBrowse(context));
108590               } else {
108591                 context.enter(mode);
108592               }
108593             });
108594           });
108595
108596           tool.render = function (selection) {
108597             var wrap = selection.append('div').attr('class', 'joined').style('display', 'flex');
108598
108599             var debouncedUpdate = debounce(update, 500, {
108600               leading: true,
108601               trailing: true
108602             });
108603
108604             context.map().on('move.modes', debouncedUpdate).on('drawn.modes', debouncedUpdate);
108605             context.on('enter.modes', update);
108606             update();
108607
108608             function update() {
108609               var buttons = wrap.selectAll('button.add-button').data(modes, function (d) {
108610                 return d.id;
108611               }); // exit
108612
108613               buttons.exit().remove(); // enter
108614
108615               var buttonsEnter = buttons.enter().append('button').attr('class', function (d) {
108616                 return d.id + ' add-button bar-button';
108617               }).on('click.mode-buttons', function (d3_event, d) {
108618                 if (!enabled()) return; // When drawing, ignore accidental clicks on mode buttons - #4042
108619
108620                 var currMode = context.mode().id;
108621                 if (/^draw/.test(currMode)) return;
108622
108623                 if (d.id === currMode) {
108624                   context.enter(modeBrowse(context));
108625                 } else {
108626                   context.enter(d);
108627                 }
108628               }).call(uiTooltip().placement('bottom').title(function (d) {
108629                 return d.description;
108630               }).keys(function (d) {
108631                 return [d.key];
108632               }).scrollContainer(context.container().select('.top-toolbar')));
108633               buttonsEnter.each(function (d) {
108634                 select(this).call(svgIcon('#iD-icon-' + d.button));
108635               });
108636               buttonsEnter.append('span').attr('class', 'label').html(function (mode) {
108637                 return mode.title;
108638               }); // if we are adding/removing the buttons, check if toolbar has overflowed
108639
108640               if (buttons.enter().size() || buttons.exit().size()) {
108641                 context.ui().checkOverflow('.top-toolbar', true);
108642               } // update
108643
108644
108645               buttons = buttons.merge(buttonsEnter).attr('aria-disabled', function (d) {
108646                 return !enabled();
108647               }).classed('disabled', function (d) {
108648                 return !enabled();
108649               }).attr('aria-pressed', function (d) {
108650                 return context.mode() && context.mode().button === d.button;
108651               }).classed('active', function (d) {
108652                 return context.mode() && context.mode().button === d.button;
108653               });
108654             }
108655           };
108656
108657           return tool;
108658         }
108659
108660         function uiToolNotes(context) {
108661           var tool = {
108662             id: 'notes',
108663             label: _t.html('modes.add_note.label')
108664           };
108665           var mode = modeAddNote(context);
108666
108667           function enabled() {
108668             return notesEnabled() && notesEditable();
108669           }
108670
108671           function notesEnabled() {
108672             var noteLayer = context.layers().layer('notes');
108673             return noteLayer && noteLayer.enabled();
108674           }
108675
108676           function notesEditable() {
108677             var mode = context.mode();
108678             return context.map().notesEditable() && mode && mode.id !== 'save';
108679           }
108680
108681           context.keybinding().on(mode.key, function () {
108682             if (!enabled()) return;
108683
108684             if (mode.id === context.mode().id) {
108685               context.enter(modeBrowse(context));
108686             } else {
108687               context.enter(mode);
108688             }
108689           });
108690
108691           tool.render = function (selection) {
108692             var debouncedUpdate = debounce(update, 500, {
108693               leading: true,
108694               trailing: true
108695             });
108696
108697             context.map().on('move.notes', debouncedUpdate).on('drawn.notes', debouncedUpdate);
108698             context.on('enter.notes', update);
108699             update();
108700
108701             function update() {
108702               var showNotes = notesEnabled();
108703               var data = showNotes ? [mode] : [];
108704               var buttons = selection.selectAll('button.add-button').data(data, function (d) {
108705                 return d.id;
108706               }); // exit
108707
108708               buttons.exit().remove(); // enter
108709
108710               var buttonsEnter = buttons.enter().append('button').attr('class', function (d) {
108711                 return d.id + ' add-button bar-button';
108712               }).on('click.notes', function (d3_event, d) {
108713                 if (!enabled()) return; // When drawing, ignore accidental clicks on mode buttons - #4042
108714
108715                 var currMode = context.mode().id;
108716                 if (/^draw/.test(currMode)) return;
108717
108718                 if (d.id === currMode) {
108719                   context.enter(modeBrowse(context));
108720                 } else {
108721                   context.enter(d);
108722                 }
108723               }).call(uiTooltip().placement('bottom').title(function (d) {
108724                 return d.description;
108725               }).keys(function (d) {
108726                 return [d.key];
108727               }).scrollContainer(context.container().select('.top-toolbar')));
108728               buttonsEnter.each(function (d) {
108729                 select(this).call(svgIcon(d.icon || '#iD-icon-' + d.button));
108730               }); // if we are adding/removing the buttons, check if toolbar has overflowed
108731
108732               if (buttons.enter().size() || buttons.exit().size()) {
108733                 context.ui().checkOverflow('.top-toolbar', true);
108734               } // update
108735
108736
108737               buttons = buttons.merge(buttonsEnter).classed('disabled', function (d) {
108738                 return !enabled();
108739               }).attr('aria-disabled', function (d) {
108740                 return !enabled();
108741               }).classed('active', function (d) {
108742                 return context.mode() && context.mode().button === d.button;
108743               }).attr('aria-pressed', function (d) {
108744                 return context.mode() && context.mode().button === d.button;
108745               });
108746             }
108747           };
108748
108749           tool.uninstall = function () {
108750             context.on('enter.editor.notes', null).on('exit.editor.notes', null).on('enter.notes', null);
108751             context.map().on('move.notes', null).on('drawn.notes', null);
108752           };
108753
108754           return tool;
108755         }
108756
108757         function uiToolSave(context) {
108758           var tool = {
108759             id: 'save',
108760             label: _t.html('save.title')
108761           };
108762           var button = null;
108763           var tooltipBehavior = null;
108764           var history = context.history();
108765           var key = uiCmd('⌘S');
108766           var _numChanges = 0;
108767
108768           function isSaving() {
108769             var mode = context.mode();
108770             return mode && mode.id === 'save';
108771           }
108772
108773           function isDisabled() {
108774             return _numChanges === 0 || isSaving();
108775           }
108776
108777           function save(d3_event) {
108778             d3_event.preventDefault();
108779
108780             if (!context.inIntro() && !isSaving() && history.hasChanges()) {
108781               context.enter(modeSave(context));
108782             }
108783           }
108784
108785           function bgColor() {
108786             var step;
108787
108788             if (_numChanges === 0) {
108789               return null;
108790             } else if (_numChanges <= 50) {
108791               step = _numChanges / 50;
108792               return d3_interpolateRgb('#fff', '#ff8')(step); // white -> yellow
108793             } else {
108794               step = Math.min((_numChanges - 50) / 50, 1.0);
108795               return d3_interpolateRgb('#ff8', '#f88')(step); // yellow -> red
108796             }
108797           }
108798
108799           function updateCount() {
108800             var val = history.difference().summary().length;
108801             if (val === _numChanges) return;
108802             _numChanges = val;
108803
108804             if (tooltipBehavior) {
108805               tooltipBehavior.title(_t.html(_numChanges > 0 ? 'save.help' : 'save.no_changes')).keys([key]);
108806             }
108807
108808             if (button) {
108809               button.classed('disabled', isDisabled()).style('background', bgColor());
108810               button.select('span.count').text(_numChanges);
108811             }
108812           }
108813
108814           tool.render = function (selection) {
108815             tooltipBehavior = uiTooltip().placement('bottom').title(_t.html('save.no_changes')).keys([key]).scrollContainer(context.container().select('.top-toolbar'));
108816             var lastPointerUpType;
108817             button = selection.append('button').attr('class', 'save disabled bar-button').on('pointerup', function (d3_event) {
108818               lastPointerUpType = d3_event.pointerType;
108819             }).on('click', function (d3_event) {
108820               save(d3_event);
108821
108822               if (_numChanges === 0 && (lastPointerUpType === 'touch' || lastPointerUpType === 'pen')) {
108823                 // there are no tooltips for touch interactions so flash feedback instead
108824                 context.ui().flash.duration(2000).iconName('#iD-icon-save').iconClass('disabled').label(_t.html('save.no_changes'))();
108825               }
108826
108827               lastPointerUpType = null;
108828             }).call(tooltipBehavior);
108829             button.call(svgIcon('#iD-icon-save'));
108830             button.append('span').attr('class', 'count').attr('aria-hidden', 'true').text('0');
108831             updateCount();
108832             context.keybinding().on(key, save, true);
108833             context.history().on('change.save', updateCount);
108834             context.on('enter.save', function () {
108835               if (button) {
108836                 button.classed('disabled', isDisabled());
108837
108838                 if (isSaving()) {
108839                   button.call(tooltipBehavior.hide);
108840                 }
108841               }
108842             });
108843           };
108844
108845           tool.uninstall = function () {
108846             context.keybinding().off(key, true);
108847             context.history().on('change.save', null);
108848             context.on('enter.save', null);
108849             button = null;
108850             tooltipBehavior = null;
108851           };
108852
108853           return tool;
108854         }
108855
108856         function uiToolSidebarToggle(context) {
108857           var tool = {
108858             id: 'sidebar_toggle',
108859             label: _t.html('toolbar.inspect')
108860           };
108861
108862           tool.render = function (selection) {
108863             selection.append('button').attr('class', 'bar-button').attr('aria-label', _t('sidebar.tooltip')).on('click', function () {
108864               context.ui().sidebar.toggle();
108865             }).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')));
108866           };
108867
108868           return tool;
108869         }
108870
108871         function uiToolUndoRedo(context) {
108872           var tool = {
108873             id: 'undo_redo',
108874             label: _t.html('toolbar.undo_redo')
108875           };
108876           var commands = [{
108877             id: 'undo',
108878             cmd: uiCmd('⌘Z'),
108879             action: function action() {
108880               context.undo();
108881             },
108882             annotation: function annotation() {
108883               return context.history().undoAnnotation();
108884             },
108885             icon: 'iD-icon-' + (_mainLocalizer.textDirection() === 'rtl' ? 'redo' : 'undo')
108886           }, {
108887             id: 'redo',
108888             cmd: uiCmd('⌘⇧Z'),
108889             action: function action() {
108890               context.redo();
108891             },
108892             annotation: function annotation() {
108893               return context.history().redoAnnotation();
108894             },
108895             icon: 'iD-icon-' + (_mainLocalizer.textDirection() === 'rtl' ? 'undo' : 'redo')
108896           }];
108897
108898           function editable() {
108899             return context.mode() && context.mode().id !== 'save' && context.map().editableDataEnabled(true
108900             /* ignore min zoom */
108901             );
108902           }
108903
108904           tool.render = function (selection) {
108905             var tooltipBehavior = uiTooltip().placement('bottom').title(function (d) {
108906               return d.annotation() ? _t.html(d.id + '.tooltip', {
108907                 action: d.annotation()
108908               }) : _t.html(d.id + '.nothing');
108909             }).keys(function (d) {
108910               return [d.cmd];
108911             }).scrollContainer(context.container().select('.top-toolbar'));
108912             var lastPointerUpType;
108913             var buttons = selection.selectAll('button').data(commands).enter().append('button').attr('class', function (d) {
108914               return 'disabled ' + d.id + '-button bar-button';
108915             }).on('pointerup', function (d3_event) {
108916               // `pointerup` is always called before `click`
108917               lastPointerUpType = d3_event.pointerType;
108918             }).on('click', function (d3_event, d) {
108919               d3_event.preventDefault();
108920               var annotation = d.annotation();
108921
108922               if (editable() && annotation) {
108923                 d.action();
108924               }
108925
108926               if (editable() && (lastPointerUpType === 'touch' || lastPointerUpType === 'pen')) {
108927                 // there are no tooltips for touch interactions so flash feedback instead
108928                 var text = annotation ? _t.html(d.id + '.tooltip', {
108929                   action: annotation
108930                 }) : _t.html(d.id + '.nothing');
108931                 context.ui().flash.duration(2000).iconName('#' + d.icon).iconClass(annotation ? '' : 'disabled').label(text)();
108932               }
108933
108934               lastPointerUpType = null;
108935             }).call(tooltipBehavior);
108936             buttons.each(function (d) {
108937               select(this).call(svgIcon('#' + d.icon));
108938             });
108939             context.keybinding().on(commands[0].cmd, function (d3_event) {
108940               d3_event.preventDefault();
108941               if (editable()) commands[0].action();
108942             }).on(commands[1].cmd, function (d3_event) {
108943               d3_event.preventDefault();
108944               if (editable()) commands[1].action();
108945             });
108946
108947             var debouncedUpdate = debounce(update, 500, {
108948               leading: true,
108949               trailing: true
108950             });
108951
108952             context.map().on('move.undo_redo', debouncedUpdate).on('drawn.undo_redo', debouncedUpdate);
108953             context.history().on('change.undo_redo', function (difference) {
108954               if (difference) update();
108955             });
108956             context.on('enter.undo_redo', update);
108957
108958             function update() {
108959               buttons.classed('disabled', function (d) {
108960                 return !editable() || !d.annotation();
108961               }).each(function () {
108962                 var selection = select(this);
108963
108964                 if (!selection.select('.tooltip.in').empty()) {
108965                   selection.call(tooltipBehavior.updateContent);
108966                 }
108967               });
108968             }
108969           };
108970
108971           tool.uninstall = function () {
108972             context.keybinding().off(commands[0].cmd).off(commands[1].cmd);
108973             context.map().on('move.undo_redo', null).on('drawn.undo_redo', null);
108974             context.history().on('change.undo_redo', null);
108975             context.on('enter.undo_redo', null);
108976           };
108977
108978           return tool;
108979         }
108980
108981         function uiTopToolbar(context) {
108982           var sidebarToggle = uiToolSidebarToggle(context),
108983               modes = uiToolOldDrawModes(context),
108984               notes = uiToolNotes(context),
108985               undoRedo = uiToolUndoRedo(context),
108986               save = uiToolSave(context);
108987
108988           function notesEnabled() {
108989             var noteLayer = context.layers().layer('notes');
108990             return noteLayer && noteLayer.enabled();
108991           }
108992
108993           function topToolbar(bar) {
108994             bar.on('wheel.topToolbar', function (d3_event) {
108995               if (!d3_event.deltaX) {
108996                 // translate vertical scrolling into horizontal scrolling in case
108997                 // the user doesn't have an input device that can scroll horizontally
108998                 bar.node().scrollLeft += d3_event.deltaY;
108999               }
109000             });
109001
109002             var debouncedUpdate = debounce(update, 500, {
109003               leading: true,
109004               trailing: true
109005             });
109006
109007             context.layers().on('change.topToolbar', debouncedUpdate);
109008             update();
109009
109010             function update() {
109011               var tools = [sidebarToggle, 'spacer', modes];
109012               tools.push('spacer');
109013
109014               if (notesEnabled()) {
109015                 tools = tools.concat([notes, 'spacer']);
109016               }
109017
109018               tools = tools.concat([undoRedo, save]);
109019               var toolbarItems = bar.selectAll('.toolbar-item').data(tools, function (d) {
109020                 return d.id || d;
109021               });
109022               toolbarItems.exit().each(function (d) {
109023                 if (d.uninstall) {
109024                   d.uninstall();
109025                 }
109026               }).remove();
109027               var itemsEnter = toolbarItems.enter().append('div').attr('class', function (d) {
109028                 var classes = 'toolbar-item ' + (d.id || d).replace('_', '-');
109029                 if (d.klass) classes += ' ' + d.klass;
109030                 return classes;
109031               });
109032               var actionableItems = itemsEnter.filter(function (d) {
109033                 return d !== 'spacer';
109034               });
109035               actionableItems.append('div').attr('class', 'item-content').each(function (d) {
109036                 select(this).call(d.render, bar);
109037               });
109038               actionableItems.append('div').attr('class', 'item-label').html(function (d) {
109039                 return d.label;
109040               });
109041             }
109042           }
109043
109044           return topToolbar;
109045         }
109046
109047         function uiZoomToSelection(context) {
109048           function isDisabled() {
109049             var mode = context.mode();
109050             return !mode || !mode.zoomToSelected;
109051           }
109052
109053           var _lastPointerUpType;
109054
109055           function pointerup(d3_event) {
109056             _lastPointerUpType = d3_event.pointerType;
109057           }
109058
109059           function click(d3_event) {
109060             d3_event.preventDefault();
109061
109062             if (isDisabled()) {
109063               if (_lastPointerUpType === 'touch' || _lastPointerUpType === 'pen') {
109064                 context.ui().flash.duration(2000).iconName('#iD-icon-framed-dot').iconClass('disabled').label(_t.html('inspector.zoom_to.no_selection'))();
109065               }
109066             } else {
109067               var mode = context.mode();
109068
109069               if (mode && mode.zoomToSelected) {
109070                 mode.zoomToSelected();
109071               }
109072             }
109073
109074             _lastPointerUpType = null;
109075           }
109076
109077           return function (selection) {
109078             var tooltipBehavior = uiTooltip().placement(_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left').title(function () {
109079               if (isDisabled()) {
109080                 return _t.html('inspector.zoom_to.no_selection');
109081               }
109082
109083               return _t.html('inspector.zoom_to.title');
109084             }).keys([_t('inspector.zoom_to.key')]);
109085             var button = selection.append('button').on('pointerup', pointerup).on('click', click).call(svgIcon('#iD-icon-framed-dot', 'light')).call(tooltipBehavior);
109086
109087             function setEnabledState() {
109088               button.classed('disabled', isDisabled());
109089
109090               if (!button.select('.tooltip.in').empty()) {
109091                 button.call(tooltipBehavior.updateContent);
109092               }
109093             }
109094
109095             context.on('enter.uiZoomToSelection', setEnabledState);
109096             setEnabledState();
109097           };
109098         }
109099
109100         function uiPane(id, context) {
109101           var _key;
109102
109103           var _label = '';
109104           var _description = '';
109105           var _iconName = '';
109106
109107           var _sections; // array of uiSection objects
109108
109109
109110           var _paneSelection = select(null);
109111
109112           var _paneTooltip;
109113
109114           var pane = {
109115             id: id
109116           };
109117
109118           pane.label = function (val) {
109119             if (!arguments.length) return _label;
109120             _label = val;
109121             return pane;
109122           };
109123
109124           pane.key = function (val) {
109125             if (!arguments.length) return _key;
109126             _key = val;
109127             return pane;
109128           };
109129
109130           pane.description = function (val) {
109131             if (!arguments.length) return _description;
109132             _description = val;
109133             return pane;
109134           };
109135
109136           pane.iconName = function (val) {
109137             if (!arguments.length) return _iconName;
109138             _iconName = val;
109139             return pane;
109140           };
109141
109142           pane.sections = function (val) {
109143             if (!arguments.length) return _sections;
109144             _sections = val;
109145             return pane;
109146           };
109147
109148           pane.selection = function () {
109149             return _paneSelection;
109150           };
109151
109152           function hidePane() {
109153             context.ui().togglePanes();
109154           }
109155
109156           pane.togglePane = function (d3_event) {
109157             if (d3_event) d3_event.preventDefault();
109158
109159             _paneTooltip.hide();
109160
109161             context.ui().togglePanes(!_paneSelection.classed('shown') ? _paneSelection : undefined);
109162           };
109163
109164           pane.renderToggleButton = function (selection) {
109165             if (!_paneTooltip) {
109166               _paneTooltip = uiTooltip().placement(_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left').title(_description).keys([_key]);
109167             }
109168
109169             selection.append('button').on('click', pane.togglePane).call(svgIcon('#' + _iconName, 'light')).call(_paneTooltip);
109170           };
109171
109172           pane.renderContent = function (selection) {
109173             // override to fully customize content
109174             if (_sections) {
109175               _sections.forEach(function (section) {
109176                 selection.call(section.render);
109177               });
109178             }
109179           };
109180
109181           pane.renderPane = function (selection) {
109182             _paneSelection = selection.append('div').attr('class', 'fillL map-pane hide ' + id + '-pane').attr('pane', id);
109183
109184             var heading = _paneSelection.append('div').attr('class', 'pane-heading');
109185
109186             heading.append('h2').html(_label);
109187             heading.append('button').attr('title', _t('icons.close')).on('click', hidePane).call(svgIcon('#iD-icon-close'));
109188
109189             _paneSelection.append('div').attr('class', 'pane-content').call(pane.renderContent);
109190
109191             if (_key) {
109192               context.keybinding().on(_key, pane.togglePane);
109193             }
109194           };
109195
109196           return pane;
109197         }
109198
109199         function uiSectionBackgroundDisplayOptions(context) {
109200           var section = uiSection('background-display-options', context).label(_t.html('background.display_options')).disclosureContent(renderDisclosureContent);
109201
109202           var _detected = utilDetect();
109203
109204           var _storedOpacity = corePreferences('background-opacity');
109205
109206           var _minVal = 0;
109207
109208           var _maxVal = _detected.cssfilters ? 3 : 1;
109209
109210           var _sliders = _detected.cssfilters ? ['brightness', 'contrast', 'saturation', 'sharpness'] : ['brightness'];
109211
109212           var _options = {
109213             brightness: _storedOpacity !== null ? +_storedOpacity : 1,
109214             contrast: 1,
109215             saturation: 1,
109216             sharpness: 1
109217           };
109218
109219           function clamp(x, min, max) {
109220             return Math.max(min, Math.min(x, max));
109221           }
109222
109223           function updateValue(d, val) {
109224             val = clamp(val, _minVal, _maxVal);
109225             _options[d] = val;
109226             context.background()[d](val);
109227
109228             if (d === 'brightness') {
109229               corePreferences('background-opacity', val);
109230             }
109231
109232             section.reRender();
109233           }
109234
109235           function renderDisclosureContent(selection) {
109236             var container = selection.selectAll('.display-options-container').data([0]);
109237             var containerEnter = container.enter().append('div').attr('class', 'display-options-container controls-list'); // add slider controls
109238
109239             var slidersEnter = containerEnter.selectAll('.display-control').data(_sliders).enter().append('label').attr('class', function (d) {
109240               return 'display-control display-control-' + d;
109241             });
109242             slidersEnter.html(function (d) {
109243               return _t.html('background.' + d);
109244             }).append('span').attr('class', function (d) {
109245               return 'display-option-value display-option-value-' + d;
109246             });
109247             var sildersControlEnter = slidersEnter.append('div').attr('class', 'control-wrap');
109248             sildersControlEnter.append('input').attr('class', function (d) {
109249               return 'display-option-input display-option-input-' + d;
109250             }).attr('type', 'range').attr('min', _minVal).attr('max', _maxVal).attr('step', '0.05').on('input', function (d3_event, d) {
109251               var val = select(this).property('value');
109252
109253               if (!val && d3_event && d3_event.target) {
109254                 val = d3_event.target.value;
109255               }
109256
109257               updateValue(d, val);
109258             });
109259             sildersControlEnter.append('button').attr('title', function (d) {
109260               return "".concat(_t('background.reset'), " ").concat(_t('background.' + d));
109261             }).attr('class', function (d) {
109262               return 'display-option-reset display-option-reset-' + d;
109263             }).on('click', function (d3_event, d) {
109264               if (d3_event.button !== 0) return;
109265               updateValue(d, 1);
109266             }).call(svgIcon('#iD-icon-' + (_mainLocalizer.textDirection() === 'rtl' ? 'redo' : 'undo'))); // reset all button
109267
109268             containerEnter.append('a').attr('class', 'display-option-resetlink').attr('role', 'button').attr('href', '#').call(_t.append('background.reset_all')).on('click', function (d3_event) {
109269               d3_event.preventDefault();
109270
109271               for (var i = 0; i < _sliders.length; i++) {
109272                 updateValue(_sliders[i], 1);
109273               }
109274             }); // update
109275
109276             container = containerEnter.merge(container);
109277             container.selectAll('.display-option-input').property('value', function (d) {
109278               return _options[d];
109279             });
109280             container.selectAll('.display-option-value').text(function (d) {
109281               return Math.floor(_options[d] * 100) + '%';
109282             });
109283             container.selectAll('.display-option-reset').classed('disabled', function (d) {
109284               return _options[d] === 1;
109285             }); // first time only, set brightness if needed
109286
109287             if (containerEnter.size() && _options.brightness !== 1) {
109288               context.background().brightness(_options.brightness);
109289             }
109290           }
109291
109292           return section;
109293         }
109294
109295         function uiSettingsCustomBackground() {
109296           var dispatch = dispatch$8('change');
109297
109298           function render(selection) {
109299             // keep separate copies of original and current settings
109300             var _origSettings = {
109301               template: corePreferences('background-custom-template')
109302             };
109303             var _currSettings = {
109304               template: corePreferences('background-custom-template')
109305             };
109306             var example = 'https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png';
109307             var modal = uiConfirm(selection).okButton();
109308             modal.classed('settings-modal settings-custom-background', true);
109309             modal.select('.modal-section.header').append('h3').call(_t.append('settings.custom_background.header'));
109310             var textSection = modal.select('.modal-section.message-text');
109311             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, "`");
109312             textSection.append('div').attr('class', 'instructions-template').html(marked_1(instructions));
109313             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
109314
109315             var buttonSection = modal.select('.modal-section.buttons');
109316             buttonSection.insert('button', '.ok-button').attr('class', 'button cancel-button secondary-action').call(_t.append('confirm.cancel'));
109317             buttonSection.select('.cancel-button').on('click.cancel', clickCancel);
109318             buttonSection.select('.ok-button').attr('disabled', isSaveDisabled).on('click.save', clickSave);
109319
109320             function isSaveDisabled() {
109321               return null;
109322             } // restore the original template
109323
109324
109325             function clickCancel() {
109326               textSection.select('.field-template').property('value', _origSettings.template);
109327               corePreferences('background-custom-template', _origSettings.template);
109328               this.blur();
109329               modal.close();
109330             } // accept the current template
109331
109332
109333             function clickSave() {
109334               _currSettings.template = textSection.select('.field-template').property('value');
109335               corePreferences('background-custom-template', _currSettings.template);
109336               this.blur();
109337               modal.close();
109338               dispatch.call('change', this, _currSettings);
109339             }
109340           }
109341
109342           return utilRebind(render, dispatch, 'on');
109343         }
109344
109345         function uiSectionBackgroundList(context) {
109346           var _backgroundList = select(null);
109347
109348           var _customSource = context.background().findSource('custom');
109349
109350           var _settingsCustomBackground = uiSettingsCustomBackground().on('change', customChanged);
109351
109352           var section = uiSection('background-list', context).label(_t.html('background.backgrounds')).disclosureContent(renderDisclosureContent);
109353
109354           function previousBackgroundID() {
109355             return corePreferences('background-last-used-toggle');
109356           }
109357
109358           function renderDisclosureContent(selection) {
109359             // the background list
109360             var container = selection.selectAll('.layer-background-list').data([0]);
109361             _backgroundList = container.enter().append('ul').attr('class', 'layer-list layer-background-list').attr('dir', 'auto').merge(container); // add minimap toggle below list
109362
109363             var bgExtrasListEnter = selection.selectAll('.bg-extras-list').data([0]).enter().append('ul').attr('class', 'layer-list bg-extras-list');
109364             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'));
109365             minimapLabelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event) {
109366               d3_event.preventDefault();
109367               uiMapInMap.toggle();
109368             });
109369             minimapLabelEnter.append('span').call(_t.append('background.minimap.description'));
109370             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'));
109371             panelLabelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event) {
109372               d3_event.preventDefault();
109373               context.ui().info.toggle('background');
109374             });
109375             panelLabelEnter.append('span').call(_t.append('background.panel.description'));
109376             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'));
109377             locPanelLabelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event) {
109378               d3_event.preventDefault();
109379               context.ui().info.toggle('location');
109380             });
109381             locPanelLabelEnter.append('span').call(_t.append('background.location_panel.description')); // "Info / Report a Problem" link
109382
109383             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'));
109384
109385             _backgroundList.call(drawListItems, 'radio', function (d3_event, d) {
109386               chooseBackground(d);
109387             }, function (d) {
109388               return !d.isHidden() && !d.overlay;
109389             });
109390           }
109391
109392           function setTooltips(selection) {
109393             selection.each(function (d, i, nodes) {
109394               var item = select(this).select('label');
109395               var span = item.select('span');
109396               var placement = i < nodes.length / 2 ? 'bottom' : 'top';
109397               var description = d.description();
109398               var isOverflowing = span.property('clientWidth') !== span.property('scrollWidth');
109399               item.call(uiTooltip().destroyAny);
109400
109401               if (d.id === previousBackgroundID()) {
109402                 item.call(uiTooltip().placement(placement).title('<div>' + _t.html('background.switch') + '</div>').keys([uiCmd('⌘' + _t('background.key'))]));
109403               } else if (description || isOverflowing) {
109404                 item.call(uiTooltip().placement(placement).title(description || d.label()));
109405               }
109406             });
109407           }
109408
109409           function drawListItems(layerList, type, change, filter) {
109410             var sources = context.background().sources(context.map().extent(), context.map().zoom(), true).filter(filter).sort(function (a, b) {
109411               return a.best() && !b.best() ? -1 : b.best() && !a.best() ? 1 : d3_descending(a.area(), b.area()) || d3_ascending(a.name(), b.name()) || 0;
109412             });
109413             var layerLinks = layerList.selectAll('li') // We have to be a bit inefficient about reordering the list since
109414             // arrow key navigation of radio values likes to work in the order
109415             // they were added, not the display document order.
109416             .data(sources, function (d, i) {
109417               return d.id + '---' + i;
109418             });
109419             layerLinks.exit().remove();
109420             var enter = layerLinks.enter().append('li').classed('layer-custom', function (d) {
109421               return d.id === 'custom';
109422             }).classed('best', function (d) {
109423               return d.best();
109424             });
109425             var label = enter.append('label');
109426             label.append('input').attr('type', type).attr('name', 'background-layer').attr('value', function (d) {
109427               return d.id;
109428             }).on('change', change);
109429             label.append('span').html(function (d) {
109430               return d.label();
109431             });
109432             enter.filter(function (d) {
109433               return d.id === 'custom';
109434             }).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) {
109435               d3_event.preventDefault();
109436               editCustom();
109437             }).call(svgIcon('#iD-icon-more'));
109438             enter.filter(function (d) {
109439               return d.best();
109440             }).append('div').attr('class', 'best').call(uiTooltip().title(_t.html('background.best_imagery')).placement(_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left')).append('span').html('&#9733;');
109441             layerList.call(updateLayerSelections);
109442           }
109443
109444           function updateLayerSelections(selection) {
109445             function active(d) {
109446               return context.background().showsLayer(d);
109447             }
109448
109449             selection.selectAll('li').classed('active', active).classed('switch', function (d) {
109450               return d.id === previousBackgroundID();
109451             }).call(setTooltips).selectAll('input').property('checked', active);
109452           }
109453
109454           function chooseBackground(d) {
109455             if (d.id === 'custom' && !d.template()) {
109456               return editCustom();
109457             }
109458
109459             var previousBackground = context.background().baseLayerSource();
109460             corePreferences('background-last-used-toggle', previousBackground.id);
109461             corePreferences('background-last-used', d.id);
109462             context.background().baseLayerSource(d);
109463           }
109464
109465           function customChanged(d) {
109466             if (d && d.template) {
109467               _customSource.template(d.template);
109468
109469               chooseBackground(_customSource);
109470             } else {
109471               _customSource.template('');
109472
109473               chooseBackground(context.background().findSource('none'));
109474             }
109475           }
109476
109477           function editCustom() {
109478             context.container().call(_settingsCustomBackground);
109479           }
109480
109481           context.background().on('change.background_list', function () {
109482             _backgroundList.call(updateLayerSelections);
109483           });
109484           context.map().on('move.background_list', debounce(function () {
109485             // layers in-view may have changed due to map move
109486             window.requestIdleCallback(section.reRender);
109487           }, 1000));
109488           return section;
109489         }
109490
109491         function uiSectionBackgroundOffset(context) {
109492           var section = uiSection('background-offset', context).label(_t.html('background.fix_misalignment')).disclosureContent(renderDisclosureContent).expandedByDefault(false);
109493
109494           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
109495
109496           var _directions = [['top', [0, -0.5]], ['left', [-0.5, 0]], ['right', [0.5, 0]], ['bottom', [0, 0.5]]];
109497
109498           function updateValue() {
109499             var meters = geoOffsetToMeters(context.background().offset());
109500             var x = +meters[0].toFixed(2);
109501             var y = +meters[1].toFixed(2);
109502             context.container().selectAll('.nudge-inner-rect').select('input').classed('error', false).property('value', x + ', ' + y);
109503             context.container().selectAll('.nudge-reset').classed('disabled', function () {
109504               return x === 0 && y === 0;
109505             });
109506           }
109507
109508           function resetOffset() {
109509             context.background().offset([0, 0]);
109510             updateValue();
109511           }
109512
109513           function nudge(d) {
109514             context.background().nudge(d, context.map().zoom());
109515             updateValue();
109516           }
109517
109518           function inputOffset() {
109519             var input = select(this);
109520             var d = input.node().value;
109521             if (d === '') return resetOffset();
109522             d = d.replace(/;/g, ',').split(',').map(function (n) {
109523               // if n is NaN, it will always get mapped to false.
109524               return !isNaN(n) && n;
109525             });
109526
109527             if (d.length !== 2 || !d[0] || !d[1]) {
109528               input.classed('error', true);
109529               return;
109530             }
109531
109532             context.background().offset(geoMetersToOffset(d));
109533             updateValue();
109534           }
109535
109536           function dragOffset(d3_event) {
109537             if (d3_event.button !== 0) return;
109538             var origin = [d3_event.clientX, d3_event.clientY];
109539             var pointerId = d3_event.pointerId || 'mouse';
109540             context.container().append('div').attr('class', 'nudge-surface');
109541             select(window).on(_pointerPrefix + 'move.drag-bg-offset', pointermove).on(_pointerPrefix + 'up.drag-bg-offset', pointerup);
109542
109543             if (_pointerPrefix === 'pointer') {
109544               select(window).on('pointercancel.drag-bg-offset', pointerup);
109545             }
109546
109547             function pointermove(d3_event) {
109548               if (pointerId !== (d3_event.pointerId || 'mouse')) return;
109549               var latest = [d3_event.clientX, d3_event.clientY];
109550               var d = [-(origin[0] - latest[0]) / 4, -(origin[1] - latest[1]) / 4];
109551               origin = latest;
109552               nudge(d);
109553             }
109554
109555             function pointerup(d3_event) {
109556               if (pointerId !== (d3_event.pointerId || 'mouse')) return;
109557               if (d3_event.button !== 0) return;
109558               context.container().selectAll('.nudge-surface').remove();
109559               select(window).on('.drag-bg-offset', null);
109560             }
109561           }
109562
109563           function renderDisclosureContent(selection) {
109564             var container = selection.selectAll('.nudge-container').data([0]);
109565             var containerEnter = container.enter().append('div').attr('class', 'nudge-container');
109566             containerEnter.append('div').attr('class', 'nudge-instructions').call(_t.append('background.offset'));
109567             var nudgeWrapEnter = containerEnter.append('div').attr('class', 'nudge-controls-wrap');
109568             var nudgeEnter = nudgeWrapEnter.append('div').attr('class', 'nudge-outer-rect').on(_pointerPrefix + 'down', dragOffset);
109569             nudgeEnter.append('div').attr('class', 'nudge-inner-rect').append('input').attr('type', 'text').attr('aria-label', _t('background.offset_label')).on('change', inputOffset);
109570             nudgeWrapEnter.append('div').selectAll('button').data(_directions).enter().append('button').attr('title', function (d) {
109571               return _t("background.nudge.".concat(d[0]));
109572             }).attr('class', function (d) {
109573               return d[0] + ' nudge';
109574             }).on('click', function (d3_event, d) {
109575               nudge(d[1]);
109576             });
109577             nudgeWrapEnter.append('button').attr('title', _t('background.reset')).attr('class', 'nudge-reset disabled').on('click', function (d3_event) {
109578               d3_event.preventDefault();
109579               resetOffset();
109580             }).call(svgIcon('#iD-icon-' + (_mainLocalizer.textDirection() === 'rtl' ? 'redo' : 'undo')));
109581             updateValue();
109582           }
109583
109584           context.background().on('change.backgroundOffset-update', updateValue);
109585           return section;
109586         }
109587
109588         function uiSectionOverlayList(context) {
109589           var section = uiSection('overlay-list', context).label(_t.html('background.overlays')).disclosureContent(renderDisclosureContent);
109590
109591           var _overlayList = select(null);
109592
109593           function setTooltips(selection) {
109594             selection.each(function (d, i, nodes) {
109595               var item = select(this).select('label');
109596               var span = item.select('span');
109597               var placement = i < nodes.length / 2 ? 'bottom' : 'top';
109598               var description = d.description();
109599               var isOverflowing = span.property('clientWidth') !== span.property('scrollWidth');
109600               item.call(uiTooltip().destroyAny);
109601
109602               if (description || isOverflowing) {
109603                 item.call(uiTooltip().placement(placement).title(description || d.name()));
109604               }
109605             });
109606           }
109607
109608           function updateLayerSelections(selection) {
109609             function active(d) {
109610               return context.background().showsLayer(d);
109611             }
109612
109613             selection.selectAll('li').classed('active', active).call(setTooltips).selectAll('input').property('checked', active);
109614           }
109615
109616           function chooseOverlay(d3_event, d) {
109617             d3_event.preventDefault();
109618             context.background().toggleOverlayLayer(d);
109619
109620             _overlayList.call(updateLayerSelections);
109621
109622             document.activeElement.blur();
109623           }
109624
109625           function drawListItems(layerList, type, change, filter) {
109626             var sources = context.background().sources(context.map().extent(), context.map().zoom(), true).filter(filter);
109627             var layerLinks = layerList.selectAll('li').data(sources, function (d) {
109628               return d.name();
109629             });
109630             layerLinks.exit().remove();
109631             var enter = layerLinks.enter().append('li');
109632             var label = enter.append('label');
109633             label.append('input').attr('type', type).attr('name', 'layers').on('change', change);
109634             label.append('span').html(function (d) {
109635               return d.label();
109636             });
109637             layerList.selectAll('li').sort(sortSources);
109638             layerList.call(updateLayerSelections);
109639
109640             function sortSources(a, b) {
109641               return a.best() && !b.best() ? -1 : b.best() && !a.best() ? 1 : d3_descending(a.area(), b.area()) || d3_ascending(a.name(), b.name()) || 0;
109642             }
109643           }
109644
109645           function renderDisclosureContent(selection) {
109646             var container = selection.selectAll('.layer-overlay-list').data([0]);
109647             _overlayList = container.enter().append('ul').attr('class', 'layer-list layer-overlay-list').attr('dir', 'auto').merge(container);
109648
109649             _overlayList.call(drawListItems, 'checkbox', chooseOverlay, function (d) {
109650               return !d.isHidden() && d.overlay;
109651             });
109652           }
109653
109654           context.map().on('move.overlay_list', debounce(function () {
109655             // layers in-view may have changed due to map move
109656             window.requestIdleCallback(section.reRender);
109657           }, 1000));
109658           return section;
109659         }
109660
109661         function uiPaneBackground(context) {
109662           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)]);
109663           return backgroundPane;
109664         }
109665
109666         function uiPaneHelp(context) {
109667           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']]];
109668           var headings = {
109669             'help.help.open_data_h': 3,
109670             'help.help.before_start_h': 3,
109671             'help.help.open_source_h': 3,
109672             'help.overview.navigation_h': 3,
109673             'help.overview.features_h': 3,
109674             'help.editing.select_h': 3,
109675             'help.editing.multiselect_h': 3,
109676             'help.editing.undo_redo_h': 3,
109677             'help.editing.save_h': 3,
109678             'help.editing.upload_h': 3,
109679             'help.editing.backups_h': 3,
109680             'help.editing.keyboard_h': 3,
109681             'help.feature_editor.type_h': 3,
109682             'help.feature_editor.fields_h': 3,
109683             'help.feature_editor.tags_h': 3,
109684             'help.points.add_point_h': 3,
109685             'help.points.move_point_h': 3,
109686             'help.points.delete_point_h': 3,
109687             'help.lines.add_line_h': 3,
109688             'help.lines.modify_line_h': 3,
109689             'help.lines.connect_line_h': 3,
109690             'help.lines.disconnect_line_h': 3,
109691             'help.lines.move_line_h': 3,
109692             'help.lines.delete_line_h': 3,
109693             'help.areas.point_or_area_h': 3,
109694             'help.areas.add_area_h': 3,
109695             'help.areas.square_area_h': 3,
109696             'help.areas.modify_area_h': 3,
109697             'help.areas.delete_area_h': 3,
109698             'help.relations.edit_relation_h': 3,
109699             'help.relations.maintain_relation_h': 3,
109700             'help.relations.relation_types_h': 2,
109701             'help.relations.multipolygon_h': 3,
109702             'help.relations.turn_restriction_h': 3,
109703             'help.relations.route_h': 3,
109704             'help.relations.boundary_h': 3,
109705             'help.notes.add_note_h': 3,
109706             'help.notes.update_note_h': 3,
109707             'help.notes.save_note_h': 3,
109708             'help.imagery.sources_h': 3,
109709             'help.imagery.offsets_h': 3,
109710             'help.streetlevel.using_h': 3,
109711             'help.gps.using_h': 3,
109712             'help.qa.tools_h': 3,
109713             'help.qa.issues_h': 3
109714           }; // For each section, squash all the texts into a single markdown document
109715
109716           var docs = docKeys.map(function (key) {
109717             var helpkey = 'help.' + key[0];
109718             var helpPaneReplacements = {
109719               version: context.version
109720             };
109721             var text = key[1].reduce(function (all, part) {
109722               var subkey = helpkey + '.' + part;
109723               var depth = headings[subkey]; // is this subkey a heading?
109724
109725               var hhh = depth ? Array(depth + 1).join('#') + ' ' : ''; // if so, prepend with some ##'s
109726
109727               return all + hhh + helpHtml(subkey, helpPaneReplacements) + '\n\n';
109728             }, '');
109729             return {
109730               title: _t.html(helpkey + '.title'),
109731               content: marked_1(text.trim()) // use keyboard key styling for shortcuts
109732               .replace(/<code>/g, '<kbd>').replace(/<\/code>/g, '<\/kbd>')
109733             };
109734           });
109735           var helpPane = uiPane('help', context).key(_t('help.key')).label(_t.html('help.title')).description(_t.html('help.title')).iconName('iD-icon-help');
109736
109737           helpPane.renderContent = function (content) {
109738             function clickHelp(d, i) {
109739               var rtl = _mainLocalizer.textDirection() === 'rtl';
109740               content.property('scrollTop', 0);
109741               helpPane.selection().select('.pane-heading h2').html(d.title);
109742               body.html(d.content);
109743               body.selectAll('a').attr('target', '_blank');
109744               menuItems.classed('selected', function (m) {
109745                 return m.title === d.title;
109746               });
109747               nav.html('');
109748
109749               if (rtl) {
109750                 nav.call(drawNext).call(drawPrevious);
109751               } else {
109752                 nav.call(drawPrevious).call(drawNext);
109753               }
109754
109755               function drawNext(selection) {
109756                 if (i < docs.length - 1) {
109757                   var nextLink = selection.append('a').attr('href', '#').attr('class', 'next').on('click', function (d3_event) {
109758                     d3_event.preventDefault();
109759                     clickHelp(docs[i + 1], i + 1);
109760                   });
109761                   nextLink.append('span').html(docs[i + 1].title).call(svgIcon(rtl ? '#iD-icon-backward' : '#iD-icon-forward', 'inline'));
109762                 }
109763               }
109764
109765               function drawPrevious(selection) {
109766                 if (i > 0) {
109767                   var prevLink = selection.append('a').attr('href', '#').attr('class', 'previous').on('click', function (d3_event) {
109768                     d3_event.preventDefault();
109769                     clickHelp(docs[i - 1], i - 1);
109770                   });
109771                   prevLink.call(svgIcon(rtl ? '#iD-icon-forward' : '#iD-icon-backward', 'inline')).append('span').html(docs[i - 1].title);
109772                 }
109773               }
109774             }
109775
109776             function clickWalkthrough(d3_event) {
109777               d3_event.preventDefault();
109778               if (context.inIntro()) return;
109779               context.container().call(uiIntro(context));
109780               context.ui().togglePanes();
109781             }
109782
109783             function clickShortcuts(d3_event) {
109784               d3_event.preventDefault();
109785               context.container().call(context.ui().shortcuts, true);
109786             }
109787
109788             var toc = content.append('ul').attr('class', 'toc');
109789             var menuItems = toc.selectAll('li').data(docs).enter().append('li').append('a').attr('role', 'button').attr('href', '#').html(function (d) {
109790               return d.title;
109791             }).on('click', function (d3_event, d) {
109792               d3_event.preventDefault();
109793               clickHelp(d, docs.indexOf(d));
109794             });
109795             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);
109796             shortcuts.append('div').call(_t.append('shortcuts.title'));
109797             var walkthrough = toc.append('li').attr('class', 'walkthrough').append('a').attr('href', '#').on('click', clickWalkthrough);
109798             walkthrough.append('svg').attr('class', 'logo logo-walkthrough').append('use').attr('xlink:href', '#iD-logo-walkthrough');
109799             walkthrough.append('div').call(_t.append('splash.walkthrough'));
109800             var helpContent = content.append('div').attr('class', 'left-content');
109801             var body = helpContent.append('div').attr('class', 'body');
109802             var nav = helpContent.append('div').attr('class', 'nav');
109803             clickHelp(docs[0], 0);
109804           };
109805
109806           return helpPane;
109807         }
109808
109809         function uiSectionValidationIssues(id, severity, context) {
109810           var _issues = [];
109811           var section = uiSection(id, context).label(function () {
109812             if (!_issues) return '';
109813             var issueCountText = _issues.length > 1000 ? '1000+' : String(_issues.length);
109814             return _t.html('inspector.title_count', {
109815               title: {
109816                 html: _t.html('issues.' + severity + 's.list_title')
109817               },
109818               count: issueCountText
109819             });
109820           }).disclosureContent(renderDisclosureContent).shouldDisplay(function () {
109821             return _issues && _issues.length;
109822           });
109823
109824           function getOptions() {
109825             return {
109826               what: corePreferences('validate-what') || 'edited',
109827               where: corePreferences('validate-where') || 'all'
109828             };
109829           } // get and cache the issues to display, unordered
109830
109831
109832           function reloadIssues() {
109833             _issues = context.validator().getIssuesBySeverity(getOptions())[severity];
109834           }
109835
109836           function renderDisclosureContent(selection) {
109837             var center = context.map().center();
109838             var graph = context.graph(); // sort issues by distance away from the center of the map
109839
109840             var issues = _issues.map(function withDistance(issue) {
109841               var extent = issue.extent(graph);
109842               var dist = extent ? geoSphericalDistance(center, extent.center()) : 0;
109843               return Object.assign(issue, {
109844                 dist: dist
109845               });
109846             }).sort(function byDistance(a, b) {
109847               return a.dist - b.dist;
109848             }); // cut off at 1000
109849
109850
109851             issues = issues.slice(0, 1000); //renderIgnoredIssuesReset(_warningsSelection);
109852
109853             selection.call(drawIssuesList, issues);
109854           }
109855
109856           function drawIssuesList(selection, issues) {
109857             var list = selection.selectAll('.issues-list').data([0]);
109858             list = list.enter().append('ul').attr('class', 'layer-list issues-list ' + severity + 's-list').merge(list);
109859             var items = list.selectAll('li').data(issues, function (d) {
109860               return d.key;
109861             }); // Exit
109862
109863             items.exit().remove(); // Enter
109864
109865             var itemsEnter = items.enter().append('li').attr('class', function (d) {
109866               return 'issue severity-' + d.severity;
109867             });
109868             var labelsEnter = itemsEnter.append('button').attr('class', 'issue-label').on('click', function (d3_event, d) {
109869               context.validator().focusIssue(d);
109870             }).on('mouseover', function (d3_event, d) {
109871               utilHighlightEntities(d.entityIds, true, context);
109872             }).on('mouseout', function (d3_event, d) {
109873               utilHighlightEntities(d.entityIds, false, context);
109874             });
109875             var textEnter = labelsEnter.append('span').attr('class', 'issue-text');
109876             textEnter.append('span').attr('class', 'issue-icon').each(function (d) {
109877               var iconName = '#iD-icon-' + (d.severity === 'warning' ? 'alert' : 'error');
109878               select(this).call(svgIcon(iconName));
109879             });
109880             textEnter.append('span').attr('class', 'issue-message');
109881             /*
109882             labelsEnter
109883                 .append('span')
109884                 .attr('class', 'issue-autofix')
109885                 .each(function(d) {
109886                     if (!d.autoFix) return;
109887                      d3_select(this)
109888                         .append('button')
109889                         .attr('title', t('issues.fix_one.title'))
109890                         .datum(d.autoFix)  // set button datum to the autofix
109891                         .attr('class', 'autofix action')
109892                         .on('click', function(d3_event, d) {
109893                             d3_event.preventDefault();
109894                             d3_event.stopPropagation();
109895                              var issuesEntityIDs = d.issue.entityIds;
109896                             utilHighlightEntities(issuesEntityIDs.concat(d.entityIds), false, context);
109897                              context.perform.apply(context, d.autoArgs);
109898                             context.validator().validate();
109899                         })
109900                         .call(svgIcon('#iD-icon-wrench'));
109901                 });
109902             */
109903             // Update
109904
109905             items = items.merge(itemsEnter).order();
109906             items.selectAll('.issue-message').html(function (d) {
109907               return d.message(context);
109908             });
109909             /*
109910             // autofix
109911             var canAutoFix = issues.filter(function(issue) { return issue.autoFix; });
109912              var autoFixAll = selection.selectAll('.autofix-all')
109913                 .data(canAutoFix.length ? [0] : []);
109914              // exit
109915             autoFixAll.exit()
109916                 .remove();
109917              // enter
109918             var autoFixAllEnter = autoFixAll.enter()
109919                 .insert('div', '.issues-list')
109920                 .attr('class', 'autofix-all');
109921              var linkEnter = autoFixAllEnter
109922                 .append('a')
109923                 .attr('class', 'autofix-all-link')
109924                 .attr('href', '#');
109925              linkEnter
109926                 .append('span')
109927                 .attr('class', 'autofix-all-link-text')
109928                 .call(t.append('issues.fix_all.title'));
109929              linkEnter
109930                 .append('span')
109931                 .attr('class', 'autofix-all-link-icon')
109932                 .call(svgIcon('#iD-icon-wrench'));
109933              if (severity === 'warning') {
109934                 renderIgnoredIssuesReset(selection);
109935             }
109936              // update
109937             autoFixAll = autoFixAll
109938                 .merge(autoFixAllEnter);
109939              autoFixAll.selectAll('.autofix-all-link')
109940                 .on('click', function() {
109941                     context.pauseChangeDispatch();
109942                     context.perform(actionNoop());
109943                     canAutoFix.forEach(function(issue) {
109944                         var args = issue.autoFix.autoArgs.slice();  // copy
109945                         if (typeof args[args.length - 1] !== 'function') {
109946                             args.pop();
109947                         }
109948                         args.push(t('issues.fix_all.annotation'));
109949                         context.replace.apply(context, args);
109950                     });
109951                     context.resumeChangeDispatch();
109952                     context.validator().validate();
109953                 });
109954             */
109955           }
109956
109957           context.validator().on('validated.uiSectionValidationIssues' + id, function () {
109958             window.requestIdleCallback(function () {
109959               reloadIssues();
109960               section.reRender();
109961             });
109962           });
109963           context.map().on('move.uiSectionValidationIssues' + id, debounce(function () {
109964             window.requestIdleCallback(function () {
109965               if (getOptions().where === 'visible') {
109966                 // must refetch issues if they are viewport-dependent
109967                 reloadIssues();
109968               } // always reload list to re-sort-by-distance
109969
109970
109971               section.reRender();
109972             });
109973           }, 1000));
109974           return section;
109975         }
109976
109977         function uiSectionValidationOptions(context) {
109978           var section = uiSection('issues-options', context).content(renderContent);
109979
109980           function renderContent(selection) {
109981             var container = selection.selectAll('.issues-options-container').data([0]);
109982             container = container.enter().append('div').attr('class', 'issues-options-container').merge(container);
109983             var data = [{
109984               key: 'what',
109985               values: ['edited', 'all']
109986             }, {
109987               key: 'where',
109988               values: ['visible', 'all']
109989             }];
109990             var options = container.selectAll('.issues-option').data(data, function (d) {
109991               return d.key;
109992             });
109993             var optionsEnter = options.enter().append('div').attr('class', function (d) {
109994               return 'issues-option issues-option-' + d.key;
109995             });
109996             optionsEnter.append('div').attr('class', 'issues-option-title').html(function (d) {
109997               return _t.html('issues.options.' + d.key + '.title');
109998             });
109999             var valuesEnter = optionsEnter.selectAll('label').data(function (d) {
110000               return d.values.map(function (val) {
110001                 return {
110002                   value: val,
110003                   key: d.key
110004                 };
110005               });
110006             }).enter().append('label');
110007             valuesEnter.append('input').attr('type', 'radio').attr('name', function (d) {
110008               return 'issues-option-' + d.key;
110009             }).attr('value', function (d) {
110010               return d.value;
110011             }).property('checked', function (d) {
110012               return getOptions()[d.key] === d.value;
110013             }).on('change', function (d3_event, d) {
110014               updateOptionValue(d3_event, d.key, d.value);
110015             });
110016             valuesEnter.append('span').html(function (d) {
110017               return _t.html('issues.options.' + d.key + '.' + d.value);
110018             });
110019           }
110020
110021           function getOptions() {
110022             return {
110023               what: corePreferences('validate-what') || 'edited',
110024               // 'all', 'edited'
110025               where: corePreferences('validate-where') || 'all' // 'all', 'visible'
110026
110027             };
110028           }
110029
110030           function updateOptionValue(d3_event, d, val) {
110031             if (!val && d3_event && d3_event.target) {
110032               val = d3_event.target.value;
110033             }
110034
110035             corePreferences('validate-' + d, val);
110036             context.validator().validate();
110037           }
110038
110039           return section;
110040         }
110041
110042         function uiSectionValidationRules(context) {
110043           var MINSQUARE = 0;
110044           var MAXSQUARE = 20;
110045           var DEFAULTSQUARE = 5; // see also unsquare_way.js
110046
110047           var section = uiSection('issues-rules', context).disclosureContent(renderDisclosureContent).label(_t.html('issues.rules.title'));
110048
110049           var _ruleKeys = context.validator().getRuleKeys().filter(function (key) {
110050             return key !== 'maprules';
110051           }).sort(function (key1, key2) {
110052             // alphabetize by localized title
110053             return _t('issues.' + key1 + '.title') < _t('issues.' + key2 + '.title') ? -1 : 1;
110054           });
110055
110056           function renderDisclosureContent(selection) {
110057             var container = selection.selectAll('.issues-rulelist-container').data([0]);
110058             var containerEnter = container.enter().append('div').attr('class', 'issues-rulelist-container');
110059             containerEnter.append('ul').attr('class', 'layer-list issue-rules-list');
110060             var ruleLinks = containerEnter.append('div').attr('class', 'issue-rules-links section-footer');
110061             ruleLinks.append('a').attr('class', 'issue-rules-link').attr('role', 'button').attr('href', '#').call(_t.append('issues.disable_all')).on('click', function (d3_event) {
110062               d3_event.preventDefault();
110063               context.validator().disableRules(_ruleKeys);
110064             });
110065             ruleLinks.append('a').attr('class', 'issue-rules-link').attr('role', 'button').attr('href', '#').call(_t.append('issues.enable_all')).on('click', function (d3_event) {
110066               d3_event.preventDefault();
110067               context.validator().disableRules([]);
110068             }); // Update
110069
110070             container = container.merge(containerEnter);
110071             container.selectAll('.issue-rules-list').call(drawListItems, _ruleKeys, 'checkbox', 'rule', toggleRule, isRuleEnabled);
110072           }
110073
110074           function drawListItems(selection, data, type, name, change, active) {
110075             var items = selection.selectAll('li').data(data); // Exit
110076
110077             items.exit().remove(); // Enter
110078
110079             var enter = items.enter().append('li');
110080
110081             if (name === 'rule') {
110082               enter.call(uiTooltip().title(function (d) {
110083                 return _t.html('issues.' + d + '.tip');
110084               }).placement('top'));
110085             }
110086
110087             var label = enter.append('label');
110088             label.append('input').attr('type', type).attr('name', name).on('change', change);
110089             label.append('span').html(function (d) {
110090               var params = {};
110091
110092               if (d === 'unsquare_way') {
110093                 params.val = {
110094                   html: '<span class="square-degrees"></span>'
110095                 };
110096               }
110097
110098               return _t.html('issues.' + d + '.title', params);
110099             }); // Update
110100
110101             items = items.merge(enter);
110102             items.classed('active', active).selectAll('input').property('checked', active).property('indeterminate', false); // user-configurable square threshold
110103
110104             var degStr = corePreferences('validate-square-degrees');
110105
110106             if (degStr === null) {
110107               degStr = DEFAULTSQUARE.toString();
110108             }
110109
110110             var span = items.selectAll('.square-degrees');
110111             var input = span.selectAll('.square-degrees-input').data([0]); // enter / update
110112
110113             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) {
110114               d3_event.preventDefault();
110115               d3_event.stopPropagation();
110116               this.select();
110117             }).on('keyup', function (d3_event) {
110118               if (d3_event.keyCode === 13) {
110119                 // ↩ Return
110120                 this.blur();
110121                 this.select();
110122               }
110123             }).on('blur', changeSquare).merge(input).property('value', degStr);
110124           }
110125
110126           function changeSquare() {
110127             var input = select(this);
110128             var degStr = utilGetSetValue(input).trim();
110129             var degNum = parseFloat(degStr, 10);
110130
110131             if (!isFinite(degNum)) {
110132               degNum = DEFAULTSQUARE;
110133             } else if (degNum > MAXSQUARE) {
110134               degNum = MAXSQUARE;
110135             } else if (degNum < MINSQUARE) {
110136               degNum = MINSQUARE;
110137             }
110138
110139             degNum = Math.round(degNum * 10) / 10; // round to 1 decimal
110140
110141             degStr = degNum.toString();
110142             input.property('value', degStr);
110143             corePreferences('validate-square-degrees', degStr);
110144             context.validator().revalidateUnsquare();
110145           }
110146
110147           function isRuleEnabled(d) {
110148             return context.validator().isRuleEnabled(d);
110149           }
110150
110151           function toggleRule(d3_event, d) {
110152             context.validator().toggleRule(d);
110153           }
110154
110155           context.validator().on('validated.uiSectionValidationRules', function () {
110156             window.requestIdleCallback(section.reRender);
110157           });
110158           return section;
110159         }
110160
110161         function uiSectionValidationStatus(context) {
110162           var section = uiSection('issues-status', context).content(renderContent).shouldDisplay(function () {
110163             var issues = context.validator().getIssues(getOptions());
110164             return issues.length === 0;
110165           });
110166
110167           function getOptions() {
110168             return {
110169               what: corePreferences('validate-what') || 'edited',
110170               where: corePreferences('validate-where') || 'all'
110171             };
110172           }
110173
110174           function renderContent(selection) {
110175             var box = selection.selectAll('.box').data([0]);
110176             var boxEnter = box.enter().append('div').attr('class', 'box');
110177             boxEnter.append('div').call(svgIcon('#iD-icon-apply', 'pre-text'));
110178             var noIssuesMessage = boxEnter.append('span');
110179             noIssuesMessage.append('strong').attr('class', 'message');
110180             noIssuesMessage.append('br');
110181             noIssuesMessage.append('span').attr('class', 'details');
110182             renderIgnoredIssuesReset(selection);
110183             setNoIssuesText(selection);
110184           }
110185
110186           function renderIgnoredIssuesReset(selection) {
110187             var ignoredIssues = context.validator().getIssues({
110188               what: 'all',
110189               where: 'all',
110190               includeDisabledRules: true,
110191               includeIgnored: 'only'
110192             });
110193             var resetIgnored = selection.selectAll('.reset-ignored').data(ignoredIssues.length ? [0] : []); // exit
110194
110195             resetIgnored.exit().remove(); // enter
110196
110197             var resetIgnoredEnter = resetIgnored.enter().append('div').attr('class', 'reset-ignored section-footer');
110198             resetIgnoredEnter.append('a').attr('href', '#'); // update
110199
110200             resetIgnored = resetIgnored.merge(resetIgnoredEnter);
110201             resetIgnored.select('a').html(_t.html('inspector.title_count', {
110202               title: {
110203                 html: _t.html('issues.reset_ignored')
110204               },
110205               count: ignoredIssues.length
110206             }));
110207             resetIgnored.on('click', function (d3_event) {
110208               d3_event.preventDefault();
110209               context.validator().resetIgnoredIssues();
110210             });
110211           }
110212
110213           function setNoIssuesText(selection) {
110214             var opts = getOptions();
110215
110216             function checkForHiddenIssues(cases) {
110217               for (var type in cases) {
110218                 var hiddenOpts = cases[type];
110219                 var hiddenIssues = context.validator().getIssues(hiddenOpts);
110220
110221                 if (hiddenIssues.length) {
110222                   selection.select('.box .details').html('').call(_t.append('issues.no_issues.hidden_issues.' + type, {
110223                     count: hiddenIssues.length.toString()
110224                   }));
110225                   return;
110226                 }
110227               }
110228
110229               selection.select('.box .details').html('').call(_t.append('issues.no_issues.hidden_issues.none'));
110230             }
110231
110232             var messageType;
110233
110234             if (opts.what === 'edited' && opts.where === 'visible') {
110235               messageType = 'edits_in_view';
110236               checkForHiddenIssues({
110237                 elsewhere: {
110238                   what: 'edited',
110239                   where: 'all'
110240                 },
110241                 everything_else: {
110242                   what: 'all',
110243                   where: 'visible'
110244                 },
110245                 disabled_rules: {
110246                   what: 'edited',
110247                   where: 'visible',
110248                   includeDisabledRules: 'only'
110249                 },
110250                 everything_else_elsewhere: {
110251                   what: 'all',
110252                   where: 'all'
110253                 },
110254                 disabled_rules_elsewhere: {
110255                   what: 'edited',
110256                   where: 'all',
110257                   includeDisabledRules: 'only'
110258                 },
110259                 ignored_issues: {
110260                   what: 'edited',
110261                   where: 'visible',
110262                   includeIgnored: 'only'
110263                 },
110264                 ignored_issues_elsewhere: {
110265                   what: 'edited',
110266                   where: 'all',
110267                   includeIgnored: 'only'
110268                 }
110269               });
110270             } else if (opts.what === 'edited' && opts.where === 'all') {
110271               messageType = 'edits';
110272               checkForHiddenIssues({
110273                 everything_else: {
110274                   what: 'all',
110275                   where: 'all'
110276                 },
110277                 disabled_rules: {
110278                   what: 'edited',
110279                   where: 'all',
110280                   includeDisabledRules: 'only'
110281                 },
110282                 ignored_issues: {
110283                   what: 'edited',
110284                   where: 'all',
110285                   includeIgnored: 'only'
110286                 }
110287               });
110288             } else if (opts.what === 'all' && opts.where === 'visible') {
110289               messageType = 'everything_in_view';
110290               checkForHiddenIssues({
110291                 elsewhere: {
110292                   what: 'all',
110293                   where: 'all'
110294                 },
110295                 disabled_rules: {
110296                   what: 'all',
110297                   where: 'visible',
110298                   includeDisabledRules: 'only'
110299                 },
110300                 disabled_rules_elsewhere: {
110301                   what: 'all',
110302                   where: 'all',
110303                   includeDisabledRules: 'only'
110304                 },
110305                 ignored_issues: {
110306                   what: 'all',
110307                   where: 'visible',
110308                   includeIgnored: 'only'
110309                 },
110310                 ignored_issues_elsewhere: {
110311                   what: 'all',
110312                   where: 'all',
110313                   includeIgnored: 'only'
110314                 }
110315               });
110316             } else if (opts.what === 'all' && opts.where === 'all') {
110317               messageType = 'everything';
110318               checkForHiddenIssues({
110319                 disabled_rules: {
110320                   what: 'all',
110321                   where: 'all',
110322                   includeDisabledRules: 'only'
110323                 },
110324                 ignored_issues: {
110325                   what: 'all',
110326                   where: 'all',
110327                   includeIgnored: 'only'
110328                 }
110329               });
110330             }
110331
110332             if (opts.what === 'edited' && context.history().difference().summary().length === 0) {
110333               messageType = 'no_edits';
110334             }
110335
110336             selection.select('.box .message').html('').call(_t.append('issues.no_issues.message.' + messageType));
110337           }
110338
110339           context.validator().on('validated.uiSectionValidationStatus', function () {
110340             window.requestIdleCallback(section.reRender);
110341           });
110342           context.map().on('move.uiSectionValidationStatus', debounce(function () {
110343             window.requestIdleCallback(section.reRender);
110344           }, 1000));
110345           return section;
110346         }
110347
110348         function uiPaneIssues(context) {
110349           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)]);
110350           return issuesPane;
110351         }
110352
110353         function uiSettingsCustomData(context) {
110354           var dispatch = dispatch$8('change');
110355
110356           function render(selection) {
110357             var dataLayer = context.layers().layer('data'); // keep separate copies of original and current settings
110358
110359             var _origSettings = {
110360               fileList: dataLayer && dataLayer.fileList() || null,
110361               url: corePreferences('settings-custom-data-url')
110362             };
110363             var _currSettings = {
110364               fileList: dataLayer && dataLayer.fileList() || null,
110365               url: corePreferences('settings-custom-data-url')
110366             }; // var example = 'https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png';
110367
110368             var modal = uiConfirm(selection).okButton();
110369             modal.classed('settings-modal settings-custom-data', true);
110370             modal.select('.modal-section.header').append('h3').call(_t.append('settings.custom_data.header'));
110371             var textSection = modal.select('.modal-section.message-text');
110372             textSection.append('pre').attr('class', 'instructions-file').call(_t.append('settings.custom_data.file.instructions'));
110373             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
110374             .on('change', function (d3_event) {
110375               var files = d3_event.target.files;
110376
110377               if (files && files.length) {
110378                 _currSettings.url = '';
110379                 textSection.select('.field-url').property('value', '');
110380                 _currSettings.fileList = files;
110381               } else {
110382                 _currSettings.fileList = null;
110383               }
110384             });
110385             textSection.append('h4').call(_t.append('settings.custom_data.or'));
110386             textSection.append('pre').attr('class', 'instructions-url').call(_t.append('settings.custom_data.url.instructions'));
110387             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
110388
110389             var buttonSection = modal.select('.modal-section.buttons');
110390             buttonSection.insert('button', '.ok-button').attr('class', 'button cancel-button secondary-action').call(_t.append('confirm.cancel'));
110391             buttonSection.select('.cancel-button').on('click.cancel', clickCancel);
110392             buttonSection.select('.ok-button').attr('disabled', isSaveDisabled).on('click.save', clickSave);
110393
110394             function isSaveDisabled() {
110395               return null;
110396             } // restore the original url
110397
110398
110399             function clickCancel() {
110400               textSection.select('.field-url').property('value', _origSettings.url);
110401               corePreferences('settings-custom-data-url', _origSettings.url);
110402               this.blur();
110403               modal.close();
110404             } // accept the current url
110405
110406
110407             function clickSave() {
110408               _currSettings.url = textSection.select('.field-url').property('value').trim(); // one or the other but not both
110409
110410               if (_currSettings.url) {
110411                 _currSettings.fileList = null;
110412               }
110413
110414               if (_currSettings.fileList) {
110415                 _currSettings.url = '';
110416               }
110417
110418               corePreferences('settings-custom-data-url', _currSettings.url);
110419               this.blur();
110420               modal.close();
110421               dispatch.call('change', this, _currSettings);
110422             }
110423           }
110424
110425           return utilRebind(render, dispatch, 'on');
110426         }
110427
110428         function uiSectionDataLayers(context) {
110429           var settingsCustomData = uiSettingsCustomData(context).on('change', customChanged);
110430           var layers = context.layers();
110431           var section = uiSection('data-layers', context).label(_t.html('map_data.data_layers')).disclosureContent(renderDisclosureContent);
110432
110433           function renderDisclosureContent(selection) {
110434             var container = selection.selectAll('.data-layer-container').data([0]);
110435             container.enter().append('div').attr('class', 'data-layer-container').merge(container).call(drawOsmItems).call(drawQAItems).call(drawCustomDataItems).call(drawVectorItems) // Beta - Detroit mapping challenge
110436             .call(drawPanelItems);
110437           }
110438
110439           function showsLayer(which) {
110440             var layer = layers.layer(which);
110441
110442             if (layer) {
110443               return layer.enabled();
110444             }
110445
110446             return false;
110447           }
110448
110449           function setLayer(which, enabled) {
110450             // Don't allow layer changes while drawing - #6584
110451             var mode = context.mode();
110452             if (mode && /^draw/.test(mode.id)) return;
110453             var layer = layers.layer(which);
110454
110455             if (layer) {
110456               layer.enabled(enabled);
110457
110458               if (!enabled && (which === 'osm' || which === 'notes')) {
110459                 context.enter(modeBrowse(context));
110460               }
110461             }
110462           }
110463
110464           function toggleLayer(which) {
110465             setLayer(which, !showsLayer(which));
110466           }
110467
110468           function drawOsmItems(selection) {
110469             var osmKeys = ['osm', 'notes'];
110470             var osmLayers = layers.all().filter(function (obj) {
110471               return osmKeys.indexOf(obj.id) !== -1;
110472             });
110473             var ul = selection.selectAll('.layer-list-osm').data([0]);
110474             ul = ul.enter().append('ul').attr('class', 'layer-list layer-list-osm').merge(ul);
110475             var li = ul.selectAll('.list-item').data(osmLayers);
110476             li.exit().remove();
110477             var liEnter = li.enter().append('li').attr('class', function (d) {
110478               return 'list-item list-item-' + d.id;
110479             });
110480             var labelEnter = liEnter.append('label').each(function (d) {
110481               if (d.id === 'osm') {
110482                 select(this).call(uiTooltip().title(_t.html('map_data.layers.' + d.id + '.tooltip')).keys([uiCmd('⌥' + _t('area_fill.wireframe.key'))]).placement('bottom'));
110483               } else {
110484                 select(this).call(uiTooltip().title(_t.html('map_data.layers.' + d.id + '.tooltip')).placement('bottom'));
110485               }
110486             });
110487             labelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event, d) {
110488               toggleLayer(d.id);
110489             });
110490             labelEnter.append('span').html(function (d) {
110491               return _t.html('map_data.layers.' + d.id + '.title');
110492             }); // Update
110493
110494             li.merge(liEnter).classed('active', function (d) {
110495               return d.layer.enabled();
110496             }).selectAll('input').property('checked', function (d) {
110497               return d.layer.enabled();
110498             });
110499           }
110500
110501           function drawQAItems(selection) {
110502             var qaKeys = ['keepRight', 'improveOSM', 'osmose'];
110503             var qaLayers = layers.all().filter(function (obj) {
110504               return qaKeys.indexOf(obj.id) !== -1;
110505             });
110506             var ul = selection.selectAll('.layer-list-qa').data([0]);
110507             ul = ul.enter().append('ul').attr('class', 'layer-list layer-list-qa').merge(ul);
110508             var li = ul.selectAll('.list-item').data(qaLayers);
110509             li.exit().remove();
110510             var liEnter = li.enter().append('li').attr('class', function (d) {
110511               return 'list-item list-item-' + d.id;
110512             });
110513             var labelEnter = liEnter.append('label').each(function (d) {
110514               select(this).call(uiTooltip().title(_t.html('map_data.layers.' + d.id + '.tooltip')).placement('bottom'));
110515             });
110516             labelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event, d) {
110517               toggleLayer(d.id);
110518             });
110519             labelEnter.append('span').html(function (d) {
110520               return _t.html('map_data.layers.' + d.id + '.title');
110521             }); // Update
110522
110523             li.merge(liEnter).classed('active', function (d) {
110524               return d.layer.enabled();
110525             }).selectAll('input').property('checked', function (d) {
110526               return d.layer.enabled();
110527             });
110528           } // Beta feature - sample vector layers to support Detroit Mapping Challenge
110529           // https://github.com/osmus/detroit-mapping-challenge
110530
110531
110532           function drawVectorItems(selection) {
110533             var dataLayer = layers.layer('data');
110534             var vtData = [{
110535               name: 'Detroit Neighborhoods/Parks',
110536               src: 'neighborhoods-parks',
110537               tooltip: 'Neighborhood boundaries and parks as compiled by City of Detroit in concert with community groups.',
110538               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'
110539             }, {
110540               name: 'Detroit Composite POIs',
110541               src: 'composite-poi',
110542               tooltip: 'Fire Inspections, Business Licenses, and other public location data collated from the City of Detroit.',
110543               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'
110544             }, {
110545               name: 'Detroit All-The-Places POIs',
110546               src: 'alltheplaces-poi',
110547               tooltip: 'Public domain business location data created by web scrapers.',
110548               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'
110549             }]; // Only show this if the map is around Detroit..
110550
110551             var detroit = geoExtent([-83.5, 42.1], [-82.8, 42.5]);
110552             var showVectorItems = context.map().zoom() > 9 && detroit.contains(context.map().center());
110553             var container = selection.selectAll('.vectortile-container').data(showVectorItems ? [0] : []);
110554             container.exit().remove();
110555             var containerEnter = container.enter().append('div').attr('class', 'vectortile-container');
110556             containerEnter.append('h4').attr('class', 'vectortile-header').text('Detroit Vector Tiles (Beta)');
110557             containerEnter.append('ul').attr('class', 'layer-list layer-list-vectortile');
110558             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');
110559             container = container.merge(containerEnter);
110560             var ul = container.selectAll('.layer-list-vectortile');
110561             var li = ul.selectAll('.list-item').data(vtData);
110562             li.exit().remove();
110563             var liEnter = li.enter().append('li').attr('class', function (d) {
110564               return 'list-item list-item-' + d.src;
110565             });
110566             var labelEnter = liEnter.append('label').each(function (d) {
110567               select(this).call(uiTooltip().title(d.tooltip).placement('top'));
110568             });
110569             labelEnter.append('input').attr('type', 'radio').attr('name', 'vectortile').on('change', selectVTLayer);
110570             labelEnter.append('span').text(function (d) {
110571               return d.name;
110572             }); // Update
110573
110574             li.merge(liEnter).classed('active', isVTLayerSelected).selectAll('input').property('checked', isVTLayerSelected);
110575
110576             function isVTLayerSelected(d) {
110577               return dataLayer && dataLayer.template() === d.template;
110578             }
110579
110580             function selectVTLayer(d3_event, d) {
110581               corePreferences('settings-custom-data-url', d.template);
110582
110583               if (dataLayer) {
110584                 dataLayer.template(d.template, d.src);
110585                 dataLayer.enabled(true);
110586               }
110587             }
110588           }
110589
110590           function drawCustomDataItems(selection) {
110591             var dataLayer = layers.layer('data');
110592             var hasData = dataLayer && dataLayer.hasData();
110593             var showsData = hasData && dataLayer.enabled();
110594             var ul = selection.selectAll('.layer-list-data').data(dataLayer ? [0] : []); // Exit
110595
110596             ul.exit().remove(); // Enter
110597
110598             var ulEnter = ul.enter().append('ul').attr('class', 'layer-list layer-list-data');
110599             var liEnter = ulEnter.append('li').attr('class', 'list-item-data');
110600             var labelEnter = liEnter.append('label').call(uiTooltip().title(_t.html('map_data.layers.custom.tooltip')).placement('top'));
110601             labelEnter.append('input').attr('type', 'checkbox').on('change', function () {
110602               toggleLayer('data');
110603             });
110604             labelEnter.append('span').call(_t.append('map_data.layers.custom.title'));
110605             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) {
110606               d3_event.preventDefault();
110607               editCustom();
110608             }).call(svgIcon('#iD-icon-more'));
110609             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) {
110610               if (select(this).classed('disabled')) return;
110611               d3_event.preventDefault();
110612               d3_event.stopPropagation();
110613               dataLayer.fitZoom();
110614             }).call(svgIcon('#iD-icon-framed-dot', 'monochrome')); // Update
110615
110616             ul = ul.merge(ulEnter);
110617             ul.selectAll('.list-item-data').classed('active', showsData).selectAll('label').classed('deemphasize', !hasData).selectAll('input').property('disabled', !hasData).property('checked', showsData);
110618             ul.selectAll('button.zoom-to-data').classed('disabled', !hasData);
110619           }
110620
110621           function editCustom() {
110622             context.container().call(settingsCustomData);
110623           }
110624
110625           function customChanged(d) {
110626             var dataLayer = layers.layer('data');
110627
110628             if (d && d.url) {
110629               dataLayer.url(d.url);
110630             } else if (d && d.fileList) {
110631               dataLayer.fileList(d.fileList);
110632             }
110633           }
110634
110635           function drawPanelItems(selection) {
110636             var panelsListEnter = selection.selectAll('.md-extras-list').data([0]).enter().append('ul').attr('class', 'layer-list md-extras-list');
110637             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'));
110638             historyPanelLabelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event) {
110639               d3_event.preventDefault();
110640               context.ui().info.toggle('history');
110641             });
110642             historyPanelLabelEnter.append('span').call(_t.append('map_data.history_panel.title'));
110643             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'));
110644             measurementPanelLabelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event) {
110645               d3_event.preventDefault();
110646               context.ui().info.toggle('measurement');
110647             });
110648             measurementPanelLabelEnter.append('span').call(_t.append('map_data.measurement_panel.title'));
110649           }
110650
110651           context.layers().on('change.uiSectionDataLayers', section.reRender);
110652           context.map().on('move.uiSectionDataLayers', debounce(function () {
110653             // Detroit layers may have moved in or out of view
110654             window.requestIdleCallback(section.reRender);
110655           }, 1000));
110656           return section;
110657         }
110658
110659         function uiSectionMapFeatures(context) {
110660           var _features = context.features().keys();
110661
110662           var section = uiSection('map-features', context).label(_t.html('map_data.map_features')).disclosureContent(renderDisclosureContent).expandedByDefault(false);
110663
110664           function renderDisclosureContent(selection) {
110665             var container = selection.selectAll('.layer-feature-list-container').data([0]);
110666             var containerEnter = container.enter().append('div').attr('class', 'layer-feature-list-container');
110667             containerEnter.append('ul').attr('class', 'layer-list layer-feature-list');
110668             var footer = containerEnter.append('div').attr('class', 'feature-list-links section-footer');
110669             footer.append('a').attr('class', 'feature-list-link').attr('role', 'button').attr('href', '#').call(_t.append('issues.disable_all')).on('click', function (d3_event) {
110670               d3_event.preventDefault();
110671               context.features().disableAll();
110672             });
110673             footer.append('a').attr('class', 'feature-list-link').attr('role', 'button').attr('href', '#').call(_t.append('issues.enable_all')).on('click', function (d3_event) {
110674               d3_event.preventDefault();
110675               context.features().enableAll();
110676             }); // Update
110677
110678             container = container.merge(containerEnter);
110679             container.selectAll('.layer-feature-list').call(drawListItems, _features, 'checkbox', 'feature', clickFeature, showsFeature);
110680           }
110681
110682           function drawListItems(selection, data, type, name, change, active) {
110683             var items = selection.selectAll('li').data(data); // Exit
110684
110685             items.exit().remove(); // Enter
110686
110687             var enter = items.enter().append('li').call(uiTooltip().title(function (d) {
110688               var tip = _t.html(name + '.' + d + '.tooltip');
110689
110690               if (autoHiddenFeature(d)) {
110691                 var msg = showsLayer('osm') ? _t.html('map_data.autohidden') : _t.html('map_data.osmhidden');
110692                 tip += '<div>' + msg + '</div>';
110693               }
110694
110695               return tip;
110696             }).placement('top'));
110697             var label = enter.append('label');
110698             label.append('input').attr('type', type).attr('name', name).on('change', change);
110699             label.append('span').html(function (d) {
110700               return _t.html(name + '.' + d + '.description');
110701             }); // Update
110702
110703             items = items.merge(enter);
110704             items.classed('active', active).selectAll('input').property('checked', active).property('indeterminate', autoHiddenFeature);
110705           }
110706
110707           function autoHiddenFeature(d) {
110708             return context.features().autoHidden(d);
110709           }
110710
110711           function showsFeature(d) {
110712             return context.features().enabled(d);
110713           }
110714
110715           function clickFeature(d3_event, d) {
110716             context.features().toggle(d);
110717           }
110718
110719           function showsLayer(id) {
110720             var layer = context.layers().layer(id);
110721             return layer && layer.enabled();
110722           } // add listeners
110723
110724
110725           context.features().on('change.map_features', section.reRender);
110726           return section;
110727         }
110728
110729         function uiSectionMapStyleOptions(context) {
110730           var section = uiSection('fill-area', context).label(_t.html('map_data.style_options')).disclosureContent(renderDisclosureContent).expandedByDefault(false);
110731
110732           function renderDisclosureContent(selection) {
110733             var container = selection.selectAll('.layer-fill-list').data([0]);
110734             container.enter().append('ul').attr('class', 'layer-list layer-fill-list').merge(container).call(drawListItems, context.map().areaFillOptions, 'radio', 'area_fill', setFill, isActiveFill);
110735             var container2 = selection.selectAll('.layer-visual-diff-list').data([0]);
110736             container2.enter().append('ul').attr('class', 'layer-list layer-visual-diff-list').merge(container2).call(drawListItems, ['highlight_edits'], 'checkbox', 'visual_diff', toggleHighlightEdited, function () {
110737               return context.surface().classed('highlight-edited');
110738             });
110739           }
110740
110741           function drawListItems(selection, data, type, name, change, active) {
110742             var items = selection.selectAll('li').data(data); // Exit
110743
110744             items.exit().remove(); // Enter
110745
110746             var enter = items.enter().append('li').call(uiTooltip().title(function (d) {
110747               return _t.html(name + '.' + d + '.tooltip');
110748             }).keys(function (d) {
110749               var key = d === 'wireframe' ? _t('area_fill.wireframe.key') : null;
110750               if (d === 'highlight_edits') key = _t('map_data.highlight_edits.key');
110751               return key ? [key] : null;
110752             }).placement('top'));
110753             var label = enter.append('label');
110754             label.append('input').attr('type', type).attr('name', name).on('change', change);
110755             label.append('span').html(function (d) {
110756               return _t.html(name + '.' + d + '.description');
110757             }); // Update
110758
110759             items = items.merge(enter);
110760             items.classed('active', active).selectAll('input').property('checked', active).property('indeterminate', false);
110761           }
110762
110763           function isActiveFill(d) {
110764             return context.map().activeAreaFill() === d;
110765           }
110766
110767           function toggleHighlightEdited(d3_event) {
110768             d3_event.preventDefault();
110769             context.map().toggleHighlightEdited();
110770           }
110771
110772           function setFill(d3_event, d) {
110773             context.map().activeAreaFill(d);
110774           }
110775
110776           context.map().on('changeHighlighting.ui_style, changeAreaFill.ui_style', section.reRender);
110777           return section;
110778         }
110779
110780         function uiSectionPhotoOverlays(context) {
110781           var layers = context.layers();
110782           var section = uiSection('photo-overlays', context).label(_t.html('photo_overlays.title')).disclosureContent(renderDisclosureContent).expandedByDefault(false);
110783
110784           function renderDisclosureContent(selection) {
110785             var container = selection.selectAll('.photo-overlay-container').data([0]);
110786             container.enter().append('div').attr('class', 'photo-overlay-container').merge(container).call(drawPhotoItems).call(drawPhotoTypeItems).call(drawDateFilter).call(drawUsernameFilter);
110787           }
110788
110789           function drawPhotoItems(selection) {
110790             var photoKeys = context.photos().overlayLayerIDs();
110791             var photoLayers = layers.all().filter(function (obj) {
110792               return photoKeys.indexOf(obj.id) !== -1;
110793             });
110794             var data = photoLayers.filter(function (obj) {
110795               return obj.layer.supported();
110796             });
110797
110798             function layerSupported(d) {
110799               return d.layer && d.layer.supported();
110800             }
110801
110802             function layerEnabled(d) {
110803               return layerSupported(d) && d.layer.enabled();
110804             }
110805
110806             var ul = selection.selectAll('.layer-list-photos').data([0]);
110807             ul = ul.enter().append('ul').attr('class', 'layer-list layer-list-photos').merge(ul);
110808             var li = ul.selectAll('.list-item-photos').data(data);
110809             li.exit().remove();
110810             var liEnter = li.enter().append('li').attr('class', function (d) {
110811               var classes = 'list-item-photos list-item-' + d.id;
110812
110813               if (d.id === 'mapillary-signs' || d.id === 'mapillary-map-features') {
110814                 classes += ' indented';
110815               }
110816
110817               return classes;
110818             });
110819             var labelEnter = liEnter.append('label').each(function (d) {
110820               var titleID;
110821               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';
110822               select(this).call(uiTooltip().title(_t.html(titleID)).placement('top'));
110823             });
110824             labelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event, d) {
110825               toggleLayer(d.id);
110826             });
110827             labelEnter.append('span').html(function (d) {
110828               var id = d.id;
110829               if (id === 'mapillary-signs') id = 'photo_overlays.traffic_signs';
110830               return _t.html(id.replace(/-/g, '_') + '.title');
110831             }); // Update
110832
110833             li.merge(liEnter).classed('active', layerEnabled).selectAll('input').property('checked', layerEnabled);
110834           }
110835
110836           function drawPhotoTypeItems(selection) {
110837             var data = context.photos().allPhotoTypes();
110838
110839             function typeEnabled(d) {
110840               return context.photos().showsPhotoType(d);
110841             }
110842
110843             var ul = selection.selectAll('.layer-list-photo-types').data([0]);
110844             ul.exit().remove();
110845             ul = ul.enter().append('ul').attr('class', 'layer-list layer-list-photo-types').merge(ul);
110846             var li = ul.selectAll('.list-item-photo-types').data(context.photos().shouldFilterByPhotoType() ? data : []);
110847             li.exit().remove();
110848             var liEnter = li.enter().append('li').attr('class', function (d) {
110849               return 'list-item-photo-types list-item-' + d;
110850             });
110851             var labelEnter = liEnter.append('label').each(function (d) {
110852               select(this).call(uiTooltip().title(_t.html('photo_overlays.photo_type.' + d + '.tooltip')).placement('top'));
110853             });
110854             labelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event, d) {
110855               context.photos().togglePhotoType(d);
110856             });
110857             labelEnter.append('span').html(function (d) {
110858               return _t.html('photo_overlays.photo_type.' + d + '.title');
110859             }); // Update
110860
110861             li.merge(liEnter).classed('active', typeEnabled).selectAll('input').property('checked', typeEnabled);
110862           }
110863
110864           function drawDateFilter(selection) {
110865             var data = context.photos().dateFilters();
110866
110867             function filterEnabled(d) {
110868               return context.photos().dateFilterValue(d);
110869             }
110870
110871             var ul = selection.selectAll('.layer-list-date-filter').data([0]);
110872             ul.exit().remove();
110873             ul = ul.enter().append('ul').attr('class', 'layer-list layer-list-date-filter').merge(ul);
110874             var li = ul.selectAll('.list-item-date-filter').data(context.photos().shouldFilterByDate() ? data : []);
110875             li.exit().remove();
110876             var liEnter = li.enter().append('li').attr('class', 'list-item-date-filter');
110877             var labelEnter = liEnter.append('label').each(function (d) {
110878               select(this).call(uiTooltip().title(_t.html('photo_overlays.date_filter.' + d + '.tooltip')).placement('top'));
110879             });
110880             labelEnter.append('span').html(function (d) {
110881               return _t.html('photo_overlays.date_filter.' + d + '.title');
110882             });
110883             labelEnter.append('input').attr('type', 'date').attr('class', 'list-item-input').attr('placeholder', _t('units.year_month_day')).call(utilNoAuto).each(function (d) {
110884               utilGetSetValue(select(this), context.photos().dateFilterValue(d) || '');
110885             }).on('change', function (d3_event, d) {
110886               var value = utilGetSetValue(select(this)).trim();
110887               context.photos().setDateFilter(d, value, true); // reload the displayed dates
110888
110889               li.selectAll('input').each(function (d) {
110890                 utilGetSetValue(select(this), context.photos().dateFilterValue(d) || '');
110891               });
110892             });
110893             li = li.merge(liEnter).classed('active', filterEnabled);
110894           }
110895
110896           function drawUsernameFilter(selection) {
110897             function filterEnabled() {
110898               return context.photos().usernames();
110899             }
110900
110901             var ul = selection.selectAll('.layer-list-username-filter').data([0]);
110902             ul.exit().remove();
110903             ul = ul.enter().append('ul').attr('class', 'layer-list layer-list-username-filter').merge(ul);
110904             var li = ul.selectAll('.list-item-username-filter').data(context.photos().shouldFilterByUsername() ? ['username-filter'] : []);
110905             li.exit().remove();
110906             var liEnter = li.enter().append('li').attr('class', 'list-item-username-filter');
110907             var labelEnter = liEnter.append('label').each(function () {
110908               select(this).call(uiTooltip().title(_t.html('photo_overlays.username_filter.tooltip')).placement('top'));
110909             });
110910             labelEnter.append('span').call(_t.append('photo_overlays.username_filter.title'));
110911             labelEnter.append('input').attr('type', 'text').attr('class', 'list-item-input').call(utilNoAuto).property('value', usernameValue).on('change', function () {
110912               var value = select(this).property('value');
110913               context.photos().setUsernameFilter(value, true);
110914               select(this).property('value', usernameValue);
110915             });
110916             li.merge(liEnter).classed('active', filterEnabled);
110917
110918             function usernameValue() {
110919               var usernames = context.photos().usernames();
110920               if (usernames) return usernames.join('; ');
110921               return usernames;
110922             }
110923           }
110924
110925           function toggleLayer(which) {
110926             setLayer(which, !showsLayer(which));
110927           }
110928
110929           function showsLayer(which) {
110930             var layer = layers.layer(which);
110931
110932             if (layer) {
110933               return layer.enabled();
110934             }
110935
110936             return false;
110937           }
110938
110939           function setLayer(which, enabled) {
110940             var layer = layers.layer(which);
110941
110942             if (layer) {
110943               layer.enabled(enabled);
110944             }
110945           }
110946
110947           context.layers().on('change.uiSectionPhotoOverlays', section.reRender);
110948           context.photos().on('change.uiSectionPhotoOverlays', section.reRender);
110949           return section;
110950         }
110951
110952         function uiPaneMapData(context) {
110953           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)]);
110954           return mapDataPane;
110955         }
110956
110957         function uiPanePreferences(context) {
110958           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)]);
110959           return preferencesPane;
110960         }
110961
110962         function uiInit(context) {
110963           var _initCounter = 0;
110964           var _needWidth = {};
110965
110966           var _lastPointerType;
110967
110968           function render(container) {
110969             container.on('click.ui', function (d3_event) {
110970               // we're only concerned with the primary mouse button
110971               if (d3_event.button !== 0) return;
110972               if (!d3_event.composedPath) return; // some targets have default click events we don't want to override
110973
110974               var isOkayTarget = d3_event.composedPath().some(function (node) {
110975                 // we only care about element nodes
110976                 return node.nodeType === 1 && ( // clicking <input> focuses it and/or changes a value
110977                 node.nodeName === 'INPUT' || // clicking <label> affects its <input> by default
110978                 node.nodeName === 'LABEL' || // clicking <a> opens a hyperlink by default
110979                 node.nodeName === 'A');
110980               });
110981               if (isOkayTarget) return; // disable double-tap-to-zoom on touchscreens
110982
110983               d3_event.preventDefault();
110984             });
110985             var detected = utilDetect(); // only WebKit supports gesture events
110986
110987             if ('GestureEvent' in window && // Listening for gesture events on iOS 13.4+ breaks double-tapping,
110988             // but we only need to do this on desktop Safari anyway. – #7694
110989             !detected.isMobileWebKit) {
110990               // On iOS we disable pinch-to-zoom of the UI via the `touch-action`
110991               // CSS property, but on desktop Safari we need to manually cancel the
110992               // default gesture events.
110993               container.on('gesturestart.ui gesturechange.ui gestureend.ui', function (d3_event) {
110994                 // disable pinch-to-zoom of the UI via multitouch trackpads on macOS Safari
110995                 d3_event.preventDefault();
110996               });
110997             }
110998
110999             if ('PointerEvent' in window) {
111000               select(window).on('pointerdown.ui pointerup.ui', function (d3_event) {
111001                 var pointerType = d3_event.pointerType || 'mouse';
111002
111003                 if (_lastPointerType !== pointerType) {
111004                   _lastPointerType = pointerType;
111005                   container.attr('pointer', pointerType);
111006                 }
111007               }, true);
111008             } else {
111009               _lastPointerType = 'mouse';
111010               container.attr('pointer', 'mouse');
111011             }
111012
111013             container.attr('lang', _mainLocalizer.localeCode()).attr('dir', _mainLocalizer.textDirection()); // setup fullscreen keybindings (no button shown at this time)
111014
111015             container.call(uiFullScreen(context));
111016             var map = context.map();
111017             map.redrawEnable(false); // don't draw until we've set zoom/lat/long
111018
111019             map.on('hitMinZoom.ui', function () {
111020               ui.flash.iconName('#iD-icon-no').label(_t.html('cannot_zoom'))();
111021             });
111022             container.append('svg').attr('id', 'ideditor-defs').call(ui.svgDefs);
111023             container.append('div').attr('class', 'sidebar').call(ui.sidebar);
111024             var content = container.append('div').attr('class', 'main-content active'); // Top toolbar
111025
111026             content.append('div').attr('class', 'top-toolbar-wrap').append('div').attr('class', 'top-toolbar fillD').call(uiTopToolbar(context));
111027             content.append('div').attr('class', 'main-map').attr('dir', 'ltr').call(map);
111028             var overMap = content.append('div').attr('class', 'over-map'); // HACK: Mobile Safari 14 likes to select anything selectable when long-
111029             // pressing, even if it's not targeted. This conflicts with long-pressing
111030             // to show the edit menu. We add a selectable offscreen element as the first
111031             // child to trick Safari into not showing the selection UI.
111032
111033             overMap.append('div').attr('class', 'select-trap').text('t');
111034             overMap.call(uiMapInMap(context)).call(uiNotice(context));
111035             overMap.append('div').attr('class', 'spinner').call(uiSpinner(context)); // Map controls
111036
111037             var controlsWrap = overMap.append('div').attr('class', 'map-controls-wrap');
111038             var controls = controlsWrap.append('div').attr('class', 'map-controls');
111039             controls.append('div').attr('class', 'map-control zoombuttons').call(uiZoom(context));
111040             controls.append('div').attr('class', 'map-control zoom-to-selection-control').call(uiZoomToSelection(context));
111041             controls.append('div').attr('class', 'map-control geolocate-control').call(uiGeolocate(context));
111042             controlsWrap.on('wheel.mapControls', function (d3_event) {
111043               if (!d3_event.deltaX) {
111044                 controlsWrap.node().scrollTop += d3_event.deltaY;
111045               }
111046             }); // Add panes
111047             // This should happen after map is initialized, as some require surface()
111048
111049             var panes = overMap.append('div').attr('class', 'map-panes');
111050             var uiPanes = [uiPaneBackground(context), uiPaneMapData(context), uiPaneIssues(context), uiPanePreferences(context), uiPaneHelp(context)];
111051             uiPanes.forEach(function (pane) {
111052               controls.append('div').attr('class', 'map-control map-pane-control ' + pane.id + '-control').call(pane.renderToggleButton);
111053               panes.call(pane.renderPane);
111054             });
111055             ui.info = uiInfo(context);
111056             overMap.call(ui.info);
111057             overMap.append('div').attr('class', 'photoviewer').classed('al', true) // 'al'=left,  'ar'=right
111058             .classed('hide', true).call(ui.photoviewer);
111059             overMap.append('div').attr('class', 'attribution-wrap').attr('dir', 'ltr').call(uiAttribution(context)); // Add footer
111060
111061             var about = content.append('div').attr('class', 'map-footer');
111062             about.append('div').attr('class', 'api-status').call(uiStatus(context));
111063             var footer = about.append('div').attr('class', 'map-footer-bar fillD');
111064             footer.append('div').attr('class', 'flash-wrap footer-hide');
111065             var footerWrap = footer.append('div').attr('class', 'main-footer-wrap footer-show');
111066             footerWrap.append('div').attr('class', 'scale-block').call(uiScale(context));
111067             var aboutList = footerWrap.append('div').attr('class', 'info-block').append('ul').attr('class', 'map-footer-list');
111068             aboutList.append('li').attr('class', 'user-list').call(uiContributors(context));
111069             var apiConnections = context.apiConnections();
111070
111071             if (apiConnections && apiConnections.length > 1) {
111072               aboutList.append('li').attr('class', 'source-switch').call(uiSourceSwitch(context).keys(apiConnections));
111073             }
111074
111075             aboutList.append('li').attr('class', 'issues-info').call(uiIssuesInfo(context));
111076             aboutList.append('li').attr('class', 'feature-warning').call(uiFeatureInfo(context));
111077             var issueLinks = aboutList.append('li');
111078             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'));
111079             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'));
111080             aboutList.append('li').attr('class', 'version').call(uiVersion(context));
111081
111082             if (!context.embed()) {
111083               aboutList.call(uiAccount(context));
111084             } // Setup map dimensions and move map to initial center/zoom.
111085             // This should happen after .main-content and toolbars exist.
111086
111087
111088             ui.onResize();
111089             map.redrawEnable(true);
111090             ui.hash = behaviorHash(context);
111091             ui.hash();
111092
111093             if (!ui.hash.hadHash) {
111094               map.centerZoom([0, 0], 2);
111095             } // Bind events
111096
111097
111098             window.onbeforeunload = function () {
111099               return context.save();
111100             };
111101
111102             window.onunload = function () {
111103               context.history().unlock();
111104             };
111105
111106             select(window).on('resize.editor', function () {
111107               ui.onResize();
111108             });
111109             var panPixels = 80;
111110             context.keybinding().on('⌫', function (d3_event) {
111111               d3_event.preventDefault();
111112             }).on([_t('sidebar.key'), '`', '²', '@'], ui.sidebar.toggle) // #5663, #6864 - common QWERTY, AZERTY
111113             .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) {
111114               if (d3_event) {
111115                 d3_event.stopImmediatePropagation();
111116                 d3_event.preventDefault();
111117               }
111118
111119               var previousBackground = context.background().findSource(corePreferences('background-last-used-toggle'));
111120
111121               if (previousBackground) {
111122                 var currentBackground = context.background().baseLayerSource();
111123                 corePreferences('background-last-used-toggle', currentBackground.id);
111124                 corePreferences('background-last-used', previousBackground.id);
111125                 context.background().baseLayerSource(previousBackground);
111126               }
111127             }).on(_t('area_fill.wireframe.key'), function toggleWireframe(d3_event) {
111128               d3_event.preventDefault();
111129               d3_event.stopPropagation();
111130               context.map().toggleWireframe();
111131             }).on(uiCmd('⌥' + _t('area_fill.wireframe.key')), function toggleOsmData(d3_event) {
111132               d3_event.preventDefault();
111133               d3_event.stopPropagation(); // Don't allow layer changes while drawing - #6584
111134
111135               var mode = context.mode();
111136               if (mode && /^draw/.test(mode.id)) return;
111137               var layer = context.layers().layer('osm');
111138
111139               if (layer) {
111140                 layer.enabled(!layer.enabled());
111141
111142                 if (!layer.enabled()) {
111143                   context.enter(modeBrowse(context));
111144                 }
111145               }
111146             }).on(_t('map_data.highlight_edits.key'), function toggleHighlightEdited(d3_event) {
111147               d3_event.preventDefault();
111148               context.map().toggleHighlightEdited();
111149             });
111150             context.on('enter.editor', function (entered) {
111151               container.classed('mode-' + entered.id, true);
111152             }).on('exit.editor', function (exited) {
111153               container.classed('mode-' + exited.id, false);
111154             });
111155             context.enter(modeBrowse(context));
111156
111157             if (!_initCounter++) {
111158               if (!ui.hash.startWalkthrough) {
111159                 context.container().call(uiSplash(context)).call(uiRestore(context));
111160               }
111161
111162               context.container().call(ui.shortcuts);
111163             }
111164
111165             var osm = context.connection();
111166             var auth = uiLoading(context).message(_t.html('loading_auth')).blocking(true);
111167
111168             if (osm && auth) {
111169               osm.on('authLoading.ui', function () {
111170                 context.container().call(auth);
111171               }).on('authDone.ui', function () {
111172                 auth.close();
111173               });
111174             }
111175
111176             _initCounter++;
111177
111178             if (ui.hash.startWalkthrough) {
111179               ui.hash.startWalkthrough = false;
111180               context.container().call(uiIntro(context));
111181             }
111182
111183             function pan(d) {
111184               return function (d3_event) {
111185                 if (d3_event.shiftKey) return;
111186                 if (context.container().select('.combobox').size()) return;
111187                 d3_event.preventDefault();
111188                 context.map().pan(d, 100);
111189               };
111190             }
111191           }
111192
111193           var ui = {};
111194
111195           var _loadPromise; // renders the iD interface into the container node
111196
111197
111198           ui.ensureLoaded = function () {
111199             if (_loadPromise) return _loadPromise;
111200             return _loadPromise = Promise.all([// must have strings and presets before loading the UI
111201             _mainLocalizer.ensureLoaded(), _mainPresetIndex.ensureLoaded()]).then(function () {
111202               if (!context.container().empty()) render(context.container());
111203             })["catch"](function (err) {
111204               return console.error(err);
111205             }); // eslint-disable-line
111206           }; // `ui.restart()` will destroy and rebuild the entire iD interface,
111207           // for example to switch the locale while iD is running.
111208
111209
111210           ui.restart = function () {
111211             context.keybinding().clear();
111212             _loadPromise = null;
111213             context.container().selectAll('*').remove();
111214             ui.ensureLoaded();
111215           };
111216
111217           ui.lastPointerType = function () {
111218             return _lastPointerType;
111219           };
111220
111221           ui.svgDefs = svgDefs(context);
111222           ui.flash = uiFlash(context);
111223           ui.sidebar = uiSidebar(context);
111224           ui.photoviewer = uiPhotoviewer(context);
111225           ui.shortcuts = uiShortcuts(context);
111226
111227           ui.onResize = function (withPan) {
111228             var map = context.map(); // Recalc dimensions of map and sidebar.. (`true` = force recalc)
111229             // This will call `getBoundingClientRect` and trigger reflow,
111230             //  but the values will be cached for later use.
111231
111232             var mapDimensions = utilGetDimensions(context.container().select('.main-content'), true);
111233             utilGetDimensions(context.container().select('.sidebar'), true);
111234
111235             if (withPan !== undefined) {
111236               map.redrawEnable(false);
111237               map.pan(withPan);
111238               map.redrawEnable(true);
111239             }
111240
111241             map.dimensions(mapDimensions);
111242             ui.photoviewer.onMapResize(); // check if header or footer have overflowed
111243
111244             ui.checkOverflow('.top-toolbar');
111245             ui.checkOverflow('.map-footer-bar'); // Use outdated code so it works on Explorer
111246
111247             var resizeWindowEvent = document.createEvent('Event');
111248             resizeWindowEvent.initEvent('resizeWindow', true, true);
111249             document.dispatchEvent(resizeWindowEvent);
111250           }; // Call checkOverflow when resizing or whenever the contents change.
111251
111252
111253           ui.checkOverflow = function (selector, reset) {
111254             if (reset) {
111255               delete _needWidth[selector];
111256             }
111257
111258             var selection = context.container().select(selector);
111259             if (selection.empty()) return;
111260             var scrollWidth = selection.property('scrollWidth');
111261             var clientWidth = selection.property('clientWidth');
111262             var needed = _needWidth[selector] || scrollWidth;
111263
111264             if (scrollWidth > clientWidth) {
111265               // overflow happening
111266               selection.classed('narrow', true);
111267
111268               if (!_needWidth[selector]) {
111269                 _needWidth[selector] = scrollWidth;
111270               }
111271             } else if (scrollWidth >= needed) {
111272               selection.classed('narrow', false);
111273             }
111274           };
111275
111276           ui.togglePanes = function (showPane) {
111277             var hidePanes = context.container().selectAll('.map-pane.shown');
111278             var side = _mainLocalizer.textDirection() === 'ltr' ? 'right' : 'left';
111279             hidePanes.classed('shown', false).classed('hide', true);
111280             context.container().selectAll('.map-pane-control button').classed('active', false);
111281
111282             if (showPane) {
111283               hidePanes.classed('shown', false).classed('hide', true).style(side, '-500px');
111284               context.container().selectAll('.' + showPane.attr('pane') + '-control button').classed('active', true);
111285               showPane.classed('shown', true).classed('hide', false);
111286
111287               if (hidePanes.empty()) {
111288                 showPane.style(side, '-500px').transition().duration(200).style(side, '0px');
111289               } else {
111290                 showPane.style(side, '0px');
111291               }
111292             } else {
111293               hidePanes.classed('shown', true).classed('hide', false).style(side, '0px').transition().duration(200).style(side, '-500px').on('end', function () {
111294                 select(this).classed('shown', false).classed('hide', true);
111295               });
111296             }
111297           };
111298
111299           var _editMenu = uiEditMenu(context);
111300
111301           ui.editMenu = function () {
111302             return _editMenu;
111303           };
111304
111305           ui.showEditMenu = function (anchorPoint, triggerType, operations) {
111306             // remove any displayed menu
111307             ui.closeEditMenu();
111308             if (!operations && context.mode().operations) operations = context.mode().operations();
111309             if (!operations || !operations.length) return; // disable menu if in wide selection, for example
111310
111311             if (!context.map().editableDataEnabled()) return;
111312             var surfaceNode = context.surface().node();
111313
111314             if (surfaceNode.focus) {
111315               // FF doesn't support it
111316               // focus the surface or else clicking off the menu may not trigger modeBrowse
111317               surfaceNode.focus();
111318             }
111319
111320             operations.forEach(function (operation) {
111321               if (operation.point) operation.point(anchorPoint);
111322             });
111323
111324             _editMenu.anchorLoc(anchorPoint).triggerType(triggerType).operations(operations); // render the menu
111325
111326
111327             context.map().supersurface.call(_editMenu);
111328           };
111329
111330           ui.closeEditMenu = function () {
111331             // remove any existing menu no matter how it was added
111332             context.map().supersurface.select('.edit-menu').remove();
111333           };
111334
111335           var _saveLoading = select(null);
111336
111337           context.uploader().on('saveStarted.ui', function () {
111338             _saveLoading = uiLoading(context).message(_t.html('save.uploading')).blocking(true);
111339             context.container().call(_saveLoading); // block input during upload
111340           }).on('saveEnded.ui', function () {
111341             _saveLoading.close();
111342
111343             _saveLoading = select(null);
111344           });
111345           return ui;
111346         }
111347
111348         function coreContext() {
111349           var _this = this;
111350
111351           var dispatch = dispatch$8('enter', 'exit', 'change');
111352           var context = utilRebind({}, dispatch, 'on');
111353
111354           var _deferred = new Set();
111355
111356           context.version = '2.20.3';
111357           context.privacyVersion = '20201202'; // iD will alter the hash so cache the parameters intended to setup the session
111358
111359           context.initialHashParams = window.location.hash ? utilStringQs(window.location.hash) : {};
111360           /* Changeset */
111361           // An osmChangeset object. Not loaded until needed.
111362
111363           context.changeset = null;
111364           var _defaultChangesetComment = context.initialHashParams.comment;
111365           var _defaultChangesetSource = context.initialHashParams.source;
111366           var _defaultChangesetHashtags = context.initialHashParams.hashtags;
111367
111368           context.defaultChangesetComment = function (val) {
111369             if (!arguments.length) return _defaultChangesetComment;
111370             _defaultChangesetComment = val;
111371             return context;
111372           };
111373
111374           context.defaultChangesetSource = function (val) {
111375             if (!arguments.length) return _defaultChangesetSource;
111376             _defaultChangesetSource = val;
111377             return context;
111378           };
111379
111380           context.defaultChangesetHashtags = function (val) {
111381             if (!arguments.length) return _defaultChangesetHashtags;
111382             _defaultChangesetHashtags = val;
111383             return context;
111384           };
111385           /* Document title */
111386
111387           /* (typically shown as the label for the browser window/tab) */
111388           // If true, iD will update the title based on what the user is doing
111389
111390
111391           var _setsDocumentTitle = true;
111392
111393           context.setsDocumentTitle = function (val) {
111394             if (!arguments.length) return _setsDocumentTitle;
111395             _setsDocumentTitle = val;
111396             return context;
111397           }; // The part of the title that is always the same
111398
111399
111400           var _documentTitleBase = document.title;
111401
111402           context.documentTitleBase = function (val) {
111403             if (!arguments.length) return _documentTitleBase;
111404             _documentTitleBase = val;
111405             return context;
111406           };
111407           /* User interface and keybinding */
111408
111409
111410           var _ui;
111411
111412           context.ui = function () {
111413             return _ui;
111414           };
111415
111416           context.lastPointerType = function () {
111417             return _ui.lastPointerType();
111418           };
111419
111420           var _keybinding = utilKeybinding('context');
111421
111422           context.keybinding = function () {
111423             return _keybinding;
111424           };
111425
111426           select(document).call(_keybinding);
111427           /* Straight accessors. Avoid using these if you can. */
111428           // Instantiate the connection here because it doesn't require passing in
111429           // `context` and it's needed for pre-init calls like `preauth`
111430
111431           var _connection = services.osm;
111432
111433           var _history;
111434
111435           var _validator;
111436
111437           var _uploader;
111438
111439           context.connection = function () {
111440             return _connection;
111441           };
111442
111443           context.history = function () {
111444             return _history;
111445           };
111446
111447           context.validator = function () {
111448             return _validator;
111449           };
111450
111451           context.uploader = function () {
111452             return _uploader;
111453           };
111454           /* Connection */
111455
111456
111457           context.preauth = function (options) {
111458             if (_connection) {
111459               _connection["switch"](options);
111460             }
111461
111462             return context;
111463           };
111464           /* connection options for source switcher (optional) */
111465
111466
111467           var _apiConnections;
111468
111469           context.apiConnections = function (val) {
111470             if (!arguments.length) return _apiConnections;
111471             _apiConnections = val;
111472             return context;
111473           }; // A string or array or locale codes to prefer over the browser's settings
111474
111475
111476           context.locale = function (locale) {
111477             if (!arguments.length) return _mainLocalizer.localeCode();
111478             _mainLocalizer.preferredLocaleCodes(locale);
111479             return context;
111480           };
111481
111482           function afterLoad(cid, callback) {
111483             return function (err, result) {
111484               if (err) {
111485                 // 400 Bad Request, 401 Unauthorized, 403 Forbidden..
111486                 if (err.status === 400 || err.status === 401 || err.status === 403) {
111487                   if (_connection) {
111488                     _connection.logout();
111489                   }
111490                 }
111491
111492                 if (typeof callback === 'function') {
111493                   callback(err);
111494                 }
111495
111496                 return;
111497               } else if (_connection && _connection.getConnectionId() !== cid) {
111498                 if (typeof callback === 'function') {
111499                   callback({
111500                     message: 'Connection Switched',
111501                     status: -1
111502                   });
111503                 }
111504
111505                 return;
111506               } else {
111507                 _history.merge(result.data, result.extent);
111508
111509                 if (typeof callback === 'function') {
111510                   callback(err, result);
111511                 }
111512
111513                 return;
111514               }
111515             };
111516           }
111517
111518           context.loadTiles = function (projection, callback) {
111519             var handle = window.requestIdleCallback(function () {
111520               _deferred["delete"](handle);
111521
111522               if (_connection && context.editableDataEnabled()) {
111523                 var cid = _connection.getConnectionId();
111524
111525                 _connection.loadTiles(projection, afterLoad(cid, callback));
111526               }
111527             });
111528
111529             _deferred.add(handle);
111530           };
111531
111532           context.loadTileAtLoc = function (loc, callback) {
111533             var handle = window.requestIdleCallback(function () {
111534               _deferred["delete"](handle);
111535
111536               if (_connection && context.editableDataEnabled()) {
111537                 var cid = _connection.getConnectionId();
111538
111539                 _connection.loadTileAtLoc(loc, afterLoad(cid, callback));
111540               }
111541             });
111542
111543             _deferred.add(handle);
111544           }; // Download the full entity and its parent relations. The callback may be called multiple times.
111545
111546
111547           context.loadEntity = function (entityID, callback) {
111548             if (_connection) {
111549               var cid = _connection.getConnectionId();
111550
111551               _connection.loadEntity(entityID, afterLoad(cid, callback)); // We need to fetch the parent relations separately.
111552
111553
111554               _connection.loadEntityRelations(entityID, afterLoad(cid, callback));
111555             }
111556           };
111557
111558           context.zoomToEntity = function (entityID, zoomTo) {
111559             // be sure to load the entity even if we're not going to zoom to it
111560             context.loadEntity(entityID, function (err, result) {
111561               if (err) return;
111562
111563               if (zoomTo !== false) {
111564                 var entity = result.data.find(function (e) {
111565                   return e.id === entityID;
111566                 });
111567
111568                 if (entity) {
111569                   _map.zoomTo(entity);
111570                 }
111571               }
111572             });
111573
111574             _map.on('drawn.zoomToEntity', function () {
111575               if (!context.hasEntity(entityID)) return;
111576
111577               _map.on('drawn.zoomToEntity', null);
111578
111579               context.on('enter.zoomToEntity', null);
111580               context.enter(modeSelect(context, [entityID]));
111581             });
111582
111583             context.on('enter.zoomToEntity', function () {
111584               if (_mode.id !== 'browse') {
111585                 _map.on('drawn.zoomToEntity', null);
111586
111587                 context.on('enter.zoomToEntity', null);
111588               }
111589             });
111590           };
111591
111592           var _minEditableZoom = 16;
111593
111594           context.minEditableZoom = function (val) {
111595             if (!arguments.length) return _minEditableZoom;
111596             _minEditableZoom = val;
111597
111598             if (_connection) {
111599               _connection.tileZoom(val);
111600             }
111601
111602             return context;
111603           }; // String length limits in Unicode characters, not JavaScript UTF-16 code units
111604
111605
111606           context.maxCharsForTagKey = function () {
111607             return 255;
111608           };
111609
111610           context.maxCharsForTagValue = function () {
111611             return 255;
111612           };
111613
111614           context.maxCharsForRelationRole = function () {
111615             return 255;
111616           };
111617
111618           function cleanOsmString(val, maxChars) {
111619             // be lenient with input
111620             if (val === undefined || val === null) {
111621               val = '';
111622             } else {
111623               val = val.toString();
111624             } // remove whitespace
111625
111626
111627             val = val.trim(); // use the canonical form of the string
111628
111629             if (val.normalize) val = val.normalize('NFC'); // trim to the number of allowed characters
111630
111631             return utilUnicodeCharsTruncated(val, maxChars);
111632           }
111633
111634           context.cleanTagKey = function (val) {
111635             return cleanOsmString(val, context.maxCharsForTagKey());
111636           };
111637
111638           context.cleanTagValue = function (val) {
111639             return cleanOsmString(val, context.maxCharsForTagValue());
111640           };
111641
111642           context.cleanRelationRole = function (val) {
111643             return cleanOsmString(val, context.maxCharsForRelationRole());
111644           };
111645           /* History */
111646
111647
111648           var _inIntro = false;
111649
111650           context.inIntro = function (val) {
111651             if (!arguments.length) return _inIntro;
111652             _inIntro = val;
111653             return context;
111654           }; // Immediately save the user's history to localstorage, if possible
111655           // This is called someteimes, but also on the `window.onbeforeunload` handler
111656
111657
111658           context.save = function () {
111659             // no history save, no message onbeforeunload
111660             if (_inIntro || context.container().select('.modal').size()) return;
111661             var canSave;
111662
111663             if (_mode && _mode.id === 'save') {
111664               canSave = false; // Attempt to prevent user from creating duplicate changes - see #5200
111665
111666               if (services.osm && services.osm.isChangesetInflight()) {
111667                 _history.clearSaved();
111668
111669                 return;
111670               }
111671             } else {
111672               canSave = context.selectedIDs().every(function (id) {
111673                 var entity = context.hasEntity(id);
111674                 return entity && !entity.isDegenerate();
111675               });
111676             }
111677
111678             if (canSave) {
111679               _history.save();
111680             }
111681
111682             if (_history.hasChanges()) {
111683               return _t('save.unsaved_changes');
111684             }
111685           }; // Debounce save, since it's a synchronous localStorage write,
111686           // and history changes can happen frequently (e.g. when dragging).
111687
111688
111689           context.debouncedSave = debounce(context.save, 350);
111690
111691           function withDebouncedSave(fn) {
111692             return function () {
111693               var result = fn.apply(_history, arguments);
111694               context.debouncedSave();
111695               return result;
111696             };
111697           }
111698           /* Graph */
111699
111700
111701           context.hasEntity = function (id) {
111702             return _history.graph().hasEntity(id);
111703           };
111704
111705           context.entity = function (id) {
111706             return _history.graph().entity(id);
111707           };
111708           /* Modes */
111709
111710
111711           var _mode;
111712
111713           context.mode = function () {
111714             return _mode;
111715           };
111716
111717           context.enter = function (newMode) {
111718             if (_mode) {
111719               _mode.exit();
111720
111721               dispatch.call('exit', _this, _mode);
111722             }
111723
111724             _mode = newMode;
111725
111726             _mode.enter();
111727
111728             dispatch.call('enter', _this, _mode);
111729           };
111730
111731           context.selectedIDs = function () {
111732             return _mode && _mode.selectedIDs && _mode.selectedIDs() || [];
111733           };
111734
111735           context.activeID = function () {
111736             return _mode && _mode.activeID && _mode.activeID();
111737           };
111738
111739           var _selectedNoteID;
111740
111741           context.selectedNoteID = function (noteID) {
111742             if (!arguments.length) return _selectedNoteID;
111743             _selectedNoteID = noteID;
111744             return context;
111745           }; // NOTE: Don't change the name of this until UI v3 is merged
111746
111747
111748           var _selectedErrorID;
111749
111750           context.selectedErrorID = function (errorID) {
111751             if (!arguments.length) return _selectedErrorID;
111752             _selectedErrorID = errorID;
111753             return context;
111754           };
111755           /* Behaviors */
111756
111757
111758           context.install = function (behavior) {
111759             return context.surface().call(behavior);
111760           };
111761
111762           context.uninstall = function (behavior) {
111763             return context.surface().call(behavior.off);
111764           };
111765           /* Copy/Paste */
111766
111767
111768           var _copyGraph;
111769
111770           context.copyGraph = function () {
111771             return _copyGraph;
111772           };
111773
111774           var _copyIDs = [];
111775
111776           context.copyIDs = function (val) {
111777             if (!arguments.length) return _copyIDs;
111778             _copyIDs = val;
111779             _copyGraph = _history.graph();
111780             return context;
111781           };
111782
111783           var _copyLonLat;
111784
111785           context.copyLonLat = function (val) {
111786             if (!arguments.length) return _copyLonLat;
111787             _copyLonLat = val;
111788             return context;
111789           };
111790           /* Background */
111791
111792
111793           var _background;
111794
111795           context.background = function () {
111796             return _background;
111797           };
111798           /* Features */
111799
111800
111801           var _features;
111802
111803           context.features = function () {
111804             return _features;
111805           };
111806
111807           context.hasHiddenConnections = function (id) {
111808             var graph = _history.graph();
111809
111810             var entity = graph.entity(id);
111811             return _features.hasHiddenConnections(entity, graph);
111812           };
111813           /* Photos */
111814
111815
111816           var _photos;
111817
111818           context.photos = function () {
111819             return _photos;
111820           };
111821           /* Map */
111822
111823
111824           var _map;
111825
111826           context.map = function () {
111827             return _map;
111828           };
111829
111830           context.layers = function () {
111831             return _map.layers();
111832           };
111833
111834           context.surface = function () {
111835             return _map.surface;
111836           };
111837
111838           context.editableDataEnabled = function () {
111839             return _map.editableDataEnabled();
111840           };
111841
111842           context.surfaceRect = function () {
111843             return _map.surface.node().getBoundingClientRect();
111844           };
111845
111846           context.editable = function () {
111847             // don't allow editing during save
111848             var mode = context.mode();
111849             if (!mode || mode.id === 'save') return false;
111850             return _map.editableDataEnabled();
111851           };
111852           /* Debug */
111853
111854
111855           var _debugFlags = {
111856             tile: false,
111857             // tile boundaries
111858             collision: false,
111859             // label collision bounding boxes
111860             imagery: false,
111861             // imagery bounding polygons
111862             target: false,
111863             // touch targets
111864             downloaded: false // downloaded data from osm
111865
111866           };
111867
111868           context.debugFlags = function () {
111869             return _debugFlags;
111870           };
111871
111872           context.getDebug = function (flag) {
111873             return flag && _debugFlags[flag];
111874           };
111875
111876           context.setDebug = function (flag, val) {
111877             if (arguments.length === 1) val = true;
111878             _debugFlags[flag] = val;
111879             dispatch.call('change');
111880             return context;
111881           };
111882           /* Container */
111883
111884
111885           var _container = select(null);
111886
111887           context.container = function (val) {
111888             if (!arguments.length) return _container;
111889             _container = val;
111890
111891             _container.classed('ideditor', true);
111892
111893             return context;
111894           };
111895
111896           context.containerNode = function (val) {
111897             if (!arguments.length) return context.container().node();
111898             context.container(select(val));
111899             return context;
111900           };
111901
111902           var _embed;
111903
111904           context.embed = function (val) {
111905             if (!arguments.length) return _embed;
111906             _embed = val;
111907             return context;
111908           };
111909           /* Assets */
111910
111911
111912           var _assetPath = '';
111913
111914           context.assetPath = function (val) {
111915             if (!arguments.length) return _assetPath;
111916             _assetPath = val;
111917             _mainFileFetcher.assetPath(val);
111918             return context;
111919           };
111920
111921           var _assetMap = {};
111922
111923           context.assetMap = function (val) {
111924             if (!arguments.length) return _assetMap;
111925             _assetMap = val;
111926             _mainFileFetcher.assetMap(val);
111927             return context;
111928           };
111929
111930           context.asset = function (val) {
111931             if (/^http(s)?:\/\//i.test(val)) return val;
111932             var filename = _assetPath + val;
111933             return _assetMap[filename] || filename;
111934           };
111935
111936           context.imagePath = function (val) {
111937             return context.asset("img/".concat(val));
111938           };
111939           /* reset (aka flush) */
111940
111941
111942           context.reset = context.flush = function () {
111943             context.debouncedSave.cancel();
111944             Array.from(_deferred).forEach(function (handle) {
111945               window.cancelIdleCallback(handle);
111946
111947               _deferred["delete"](handle);
111948             });
111949             Object.values(services).forEach(function (service) {
111950               if (service && typeof service.reset === 'function') {
111951                 service.reset(context);
111952               }
111953             });
111954             context.changeset = null;
111955
111956             _validator.reset();
111957
111958             _features.reset();
111959
111960             _history.reset();
111961
111962             _uploader.reset(); // don't leave stale state in the inspector
111963
111964
111965             context.container().select('.inspector-wrap *').remove();
111966             return context;
111967           };
111968           /* Projections */
111969
111970
111971           context.projection = geoRawMercator();
111972           context.curtainProjection = geoRawMercator();
111973           /* Init */
111974
111975           context.init = function () {
111976             instantiateInternal();
111977             initializeDependents();
111978             return context; // Load variables and properties. No property of `context` should be accessed
111979             // until this is complete since load statuses are indeterminate. The order
111980             // of instantiation shouldn't matter.
111981
111982             function instantiateInternal() {
111983               _history = coreHistory(context);
111984               context.graph = _history.graph;
111985               context.pauseChangeDispatch = _history.pauseChangeDispatch;
111986               context.resumeChangeDispatch = _history.resumeChangeDispatch;
111987               context.perform = withDebouncedSave(_history.perform);
111988               context.replace = withDebouncedSave(_history.replace);
111989               context.pop = withDebouncedSave(_history.pop);
111990               context.overwrite = withDebouncedSave(_history.overwrite);
111991               context.undo = withDebouncedSave(_history.undo);
111992               context.redo = withDebouncedSave(_history.redo);
111993               _validator = coreValidator(context);
111994               _uploader = coreUploader(context);
111995               _background = rendererBackground(context);
111996               _features = rendererFeatures(context);
111997               _map = rendererMap(context);
111998               _photos = rendererPhotos(context);
111999               _ui = uiInit(context);
112000             } // Set up objects that might need to access properties of `context`. The order
112001             // might matter if dependents make calls to each other. Be wary of async calls.
112002
112003
112004             function initializeDependents() {
112005               if (context.initialHashParams.presets) {
112006                 _mainPresetIndex.addablePresetIDs(new Set(context.initialHashParams.presets.split(',')));
112007               }
112008
112009               if (context.initialHashParams.locale) {
112010                 _mainLocalizer.preferredLocaleCodes(context.initialHashParams.locale);
112011               } // kick off some async work
112012
112013
112014               _mainLocalizer.ensureLoaded();
112015
112016               _background.ensureLoaded();
112017
112018               _mainPresetIndex.ensureLoaded();
112019               Object.values(services).forEach(function (service) {
112020                 if (service && typeof service.init === 'function') {
112021                   service.init();
112022                 }
112023               });
112024
112025               _map.init();
112026
112027               _validator.init();
112028
112029               _features.init();
112030
112031               if (services.maprules && context.initialHashParams.maprules) {
112032                 d3_json(context.initialHashParams.maprules).then(function (mapcss) {
112033                   services.maprules.init();
112034                   mapcss.forEach(function (mapcssSelector) {
112035                     return services.maprules.addRule(mapcssSelector);
112036                   });
112037                 })["catch"](function () {
112038                   /* ignore */
112039                 });
112040               } // if the container isn't available, e.g. when testing, don't load the UI
112041
112042
112043               if (!context.container().empty()) {
112044                 _ui.ensureLoaded().then(function () {
112045                   _photos.init();
112046                 });
112047               }
112048             }
112049           };
112050
112051           return context;
112052         }
112053
112054         // NSI contains the most correct tagging for many commonly mapped features.
112055         // See https://github.com/osmlab/name-suggestion-index  and  https://nsi.guide
112056         // DATA
112057
112058         var _nsiStatus = 'loading'; // 'loading', 'ok', 'failed'
112059
112060         var _nsi = {}; // Sometimes we can upgrade a feature tagged like `building=yes` to a better tag.
112061
112062         var buildingPreset = {
112063           'building/commercial': true,
112064           'building/government': true,
112065           'building/hotel': true,
112066           'building/retail': true,
112067           'building/office': true,
112068           'building/supermarket': true,
112069           'building/yes': true
112070         }; // Exceptions to the namelike regexes.
112071         // Usually a tag suffix contains a language code like `name:en`, `name:ru`
112072         // but we want to exclude things like `operator:type`, `name:etymology`, etc..
112073
112074         var notNames = /:(colou?r|type|forward|backward|left|right|etymology|pronunciation|wikipedia)$/i; // Exceptions to the branchlike regexes
112075
112076         var notBranches = /(coop|express|wireless|factory|outlet)/i; // PRIVATE FUNCTIONS
112077         // `setNsiSources()`
112078         // Adds the sources to iD's filemap so we can start downloading data.
112079         //
112080
112081         function setNsiSources() {
112082           var nsiVersion = packageJSON.devDependencies['name-suggestion-index'];
112083           var v = parseVersion(nsiVersion);
112084           var vMinor = "".concat(v.major, ".").concat(v.minor);
112085           var sources = {
112086             'nsi_data': "https://cdn.jsdelivr.net/npm/name-suggestion-index@".concat(vMinor, "/dist/nsi.min.json"),
112087             'nsi_dissolved': "https://cdn.jsdelivr.net/npm/name-suggestion-index@".concat(vMinor, "/dist/dissolved.min.json"),
112088             'nsi_features': "https://cdn.jsdelivr.net/npm/name-suggestion-index@".concat(vMinor, "/dist/featureCollection.min.json"),
112089             'nsi_generics': "https://cdn.jsdelivr.net/npm/name-suggestion-index@".concat(vMinor, "/dist/genericWords.min.json"),
112090             'nsi_presets': "https://cdn.jsdelivr.net/npm/name-suggestion-index@".concat(vMinor, "/dist/presets/nsi-id-presets.min.json"),
112091             'nsi_replacements': "https://cdn.jsdelivr.net/npm/name-suggestion-index@".concat(vMinor, "/dist/replacements.min.json"),
112092             'nsi_trees': "https://cdn.jsdelivr.net/npm/name-suggestion-index@".concat(vMinor, "/dist/trees.min.json")
112093           };
112094           var fileMap = _mainFileFetcher.fileMap();
112095
112096           for (var k in sources) {
112097             if (!fileMap[k]) fileMap[k] = sources[k];
112098           }
112099         } // `loadNsiPresets()`
112100         //  Returns a Promise fulfilled when the presets have been downloaded and merged into iD.
112101         //
112102
112103
112104         function loadNsiPresets() {
112105           return Promise.all([_mainFileFetcher.get('nsi_presets'), _mainFileFetcher.get('nsi_features')]).then(function (vals) {
112106             // Add `suggestion=true` to all the nsi presets
112107             // The preset json schema doesn't include it, but the iD code still uses it
112108             Object.values(vals[0].presets).forEach(function (preset) {
112109               return preset.suggestion = true;
112110             });
112111             _mainPresetIndex.merge({
112112               presets: vals[0].presets,
112113               featureCollection: vals[1]
112114             });
112115           });
112116         } // `loadNsiData()`
112117         //  Returns a Promise fulfilled when the other data have been downloaded and processed
112118         //
112119
112120
112121         function loadNsiData() {
112122           return Promise.all([_mainFileFetcher.get('nsi_data'), _mainFileFetcher.get('nsi_dissolved'), _mainFileFetcher.get('nsi_replacements'), _mainFileFetcher.get('nsi_trees')]).then(function (vals) {
112123             _nsi = {
112124               data: vals[0].nsi,
112125               // the raw name-suggestion-index data
112126               dissolved: vals[1].dissolved,
112127               // list of dissolved items
112128               replacements: vals[2].replacements,
112129               // trivial old->new qid replacements
112130               trees: vals[3].trees,
112131               // metadata about trees, main tags
112132               kvt: new Map(),
112133               // Map (k -> Map (v -> t) )
112134               qids: new Map(),
112135               // Map (wd/wp tag values -> qids)
112136               ids: new Map() // Map (id -> NSI item)
112137
112138             };
112139             _nsi.matcher = new Matcher();
112140
112141             _nsi.matcher.buildMatchIndex(_nsi.data);
112142
112143             _nsi.matcher.buildLocationIndex(_nsi.data, _mainLocations.loco());
112144
112145             Object.keys(_nsi.data).forEach(function (tkv) {
112146               var category = _nsi.data[tkv];
112147               var parts = tkv.split('/', 3); // tkv = "tree/key/value"
112148
112149               var t = parts[0];
112150               var k = parts[1];
112151               var v = parts[2]; // Build a reverse index of keys -> values -> trees present in the name-suggestion-index
112152               // Collect primary keys  (e.g. "amenity", "craft", "shop", "man_made", "route", etc)
112153               // "amenity": {
112154               //   "restaurant": "brands"
112155               // }
112156
112157               var vmap = _nsi.kvt.get(k);
112158
112159               if (!vmap) {
112160                 vmap = new Map();
112161
112162                 _nsi.kvt.set(k, vmap);
112163               }
112164
112165               vmap.set(v, t);
112166               var tree = _nsi.trees[t]; // e.g. "brands", "operators"
112167
112168               var mainTag = tree.mainTag; // e.g. "brand:wikidata", "operator:wikidata", etc
112169
112170               var items = category.items || [];
112171               items.forEach(function (item) {
112172                 // Remember some useful things for later, cache NSI id -> item
112173                 item.tkv = tkv;
112174                 item.mainTag = mainTag;
112175
112176                 _nsi.ids.set(item.id, item); // Cache Wikidata/Wikipedia values -> qid, for #6416
112177
112178
112179                 var wd = item.tags[mainTag];
112180                 var wp = item.tags[mainTag.replace('wikidata', 'wikipedia')];
112181                 if (wd) _nsi.qids.set(wd, wd);
112182                 if (wp && wd) _nsi.qids.set(wp, wd);
112183               });
112184             });
112185           });
112186         } // `gatherKVs()`
112187         // Gather all the k/v pairs that we will run through the NSI matcher.
112188         // An OSM tags object can contain anything, but only a few tags will be interesting to NSI.
112189         //
112190         // This function will return the interesting tag pairs like:
112191         //   "amenity/restaurant", "man_made/flagpole"
112192         // and fallbacks like
112193         //   "amenity/yes"
112194         // excluding things like
112195         //   "tiger:reviewed", "surface", "ref", etc.
112196         //
112197         // Arguments
112198         //   `tags`: `Object` containing the feature's OSM tags
112199         // Returns
112200         //   `Object` containing kv pairs to test:
112201         //   {
112202         //     'primary': Set(),
112203         //     'alternate': Set()
112204         //   }
112205         //
112206
112207
112208         function gatherKVs(tags) {
112209           var primary = new Set();
112210           var alternate = new Set();
112211           Object.keys(tags).forEach(function (osmkey) {
112212             var osmvalue = tags[osmkey];
112213             if (!osmvalue) return; // Match a 'route_master' as if it were a 'route' - name-suggestion-index#5184
112214
112215             if (osmkey === 'route_master') osmkey = 'route';
112216
112217             var vmap = _nsi.kvt.get(osmkey);
112218
112219             if (!vmap) return; // not an interesting key
112220
112221             if (vmap.get(osmvalue)) {
112222               // Matched a category in NSI
112223               primary.add("".concat(osmkey, "/").concat(osmvalue)); // interesting key/value
112224             } else if (osmvalue === 'yes') {
112225               alternate.add("".concat(osmkey, "/").concat(osmvalue)); // fallback key/yes
112226             }
112227           }); // Can we try a generic building fallback match? - See #6122, #7197
112228           // Only try this if we do a preset match and find nothing else remarkable about that building.
112229           // For example, a way with `building=yes` + `name=Westfield` may be a Westfield department store.
112230           // But a way with `building=yes` + `name=Westfield` + `public_transport=station` is a train station for a town named "Westfield"
112231
112232           var preset = _mainPresetIndex.matchTags(tags, 'area');
112233
112234           if (buildingPreset[preset.id]) {
112235             alternate.add('building/yes');
112236           }
112237
112238           return {
112239             primary: primary,
112240             alternate: alternate
112241           };
112242         } // `identifyTree()`
112243         // NSI has a concept of trees: "brands", "operators", "flags", "transit".
112244         // The tree determines things like which tags are namelike, and which tags hold important wikidata.
112245         // This takes an Object of tags and tries to identify what tree to use.
112246         //
112247         // Arguments
112248         //   `tags`: `Object` containing the feature's OSM tags
112249         // Returns
112250         //   `string` the name of the tree if known
112251         //   or 'unknown' if it could match several trees (e.g. amenity/yes)
112252         //   or null if no match
112253         //
112254
112255
112256         function identifyTree(tags) {
112257           var unknown;
112258           var t; // Check all tags
112259
112260           Object.keys(tags).forEach(function (osmkey) {
112261             if (t) return; // found already
112262
112263             var osmvalue = tags[osmkey];
112264             if (!osmvalue) return; // Match a 'route_master' as if it were a 'route' - name-suggestion-index#5184
112265
112266             if (osmkey === 'route_master') osmkey = 'route';
112267
112268             var vmap = _nsi.kvt.get(osmkey);
112269
112270             if (!vmap) return; // this key is not in nsi
112271
112272             if (osmvalue === 'yes') {
112273               unknown = 'unknown';
112274             } else {
112275               t = vmap.get(osmvalue);
112276             }
112277           });
112278           return t || unknown || null;
112279         } // `gatherNames()`
112280         // Gather all the namelike values that we will run through the NSI matcher.
112281         // It will gather values primarily from tags `name`, `name:ru`, `flag:name`
112282         //  and fallback to alternate tags like `brand`, `brand:ru`, `alt_name`
112283         //
112284         // Arguments
112285         //   `tags`: `Object` containing the feature's OSM tags
112286         // Returns
112287         //   `Object` containing namelike values to test:
112288         //   {
112289         //     'primary': Set(),
112290         //     'fallbacks': Set()
112291         //   }
112292         //
112293
112294
112295         function gatherNames(tags) {
112296           var empty = {
112297             primary: new Set(),
112298             alternate: new Set()
112299           };
112300           var primary = new Set();
112301           var alternate = new Set();
112302           var foundSemi = false;
112303           var testNameFragments = false;
112304           var patterns; // Patterns for matching OSM keys that might contain namelike values.
112305           // These roughly correspond to the "trees" concept in name-suggestion-index,
112306
112307           var t = identifyTree(tags);
112308           if (!t) return empty;
112309
112310           if (t === 'transit') {
112311             patterns = {
112312               primary: /^network$/i,
112313               alternate: /^(operator|operator:\w+|network:\w+|\w+_name|\w+_name:\w+)$/i
112314             };
112315           } else if (t === 'flags') {
112316             patterns = {
112317               primary: /^(flag:name|flag:name:\w+)$/i,
112318               alternate: /^(flag|flag:\w+|subject|subject:\w+)$/i // note: no `country`, we special-case it below
112319
112320             };
112321           } else if (t === 'brands') {
112322             testNameFragments = true;
112323             patterns = {
112324               primary: /^(name|name:\w+)$/i,
112325               alternate: /^(brand|brand:\w+|operator|operator:\w+|\w+_name|\w+_name:\w+)/i
112326             };
112327           } else if (t === 'operators') {
112328             testNameFragments = true;
112329             patterns = {
112330               primary: /^(name|name:\w+|operator|operator:\w+)$/i,
112331               alternate: /^(brand|brand:\w+|\w+_name|\w+_name:\w+)/i
112332             };
112333           } else {
112334             // unknown/multiple
112335             testNameFragments = true;
112336             patterns = {
112337               primary: /^(name|name:\w+)$/i,
112338               alternate: /^(brand|brand:\w+|network|network:\w+|operator|operator:\w+|\w+_name|\w+_name:\w+)/i
112339             };
112340           } // Test `name` fragments, longest to shortest, to fit them into a "Name Branch" pattern.
112341           // e.g. "TUI ReiseCenter - Neuss Innenstadt" -> ["TUI", "ReiseCenter", "Neuss", "Innenstadt"]
112342
112343
112344           if (tags.name && testNameFragments) {
112345             var nameParts = tags.name.split(/[\s\-\/,.]/);
112346
112347             for (var split = nameParts.length; split > 0; split--) {
112348               var name = nameParts.slice(0, split).join(' '); // e.g. "TUI ReiseCenter"
112349
112350               primary.add(name);
112351             }
112352           } // Check all tags
112353
112354
112355           Object.keys(tags).forEach(function (osmkey) {
112356             var osmvalue = tags[osmkey];
112357             if (!osmvalue) return;
112358
112359             if (isNamelike(osmkey, 'primary')) {
112360               if (/;/.test(osmvalue)) {
112361                 foundSemi = true;
112362               } else {
112363                 primary.add(osmvalue);
112364                 alternate["delete"](osmvalue);
112365               }
112366             } else if (!primary.has(osmvalue) && isNamelike(osmkey, 'alternate')) {
112367               if (/;/.test(osmvalue)) {
112368                 foundSemi = true;
112369               } else {
112370                 alternate.add(osmvalue);
112371               }
112372             }
112373           }); // For flags only, fallback to `country` tag only if no other namelike values were found.
112374           // See https://github.com/openstreetmap/iD/pull/8305#issuecomment-769174070
112375
112376           if (tags.man_made === 'flagpole' && !primary.size && !alternate.size && !!tags.country) {
112377             var osmvalue = tags.country;
112378
112379             if (/;/.test(osmvalue)) {
112380               foundSemi = true;
112381             } else {
112382               alternate.add(osmvalue);
112383             }
112384           } // If any namelike value contained a semicolon, return empty set and don't try matching anything.
112385
112386
112387           if (foundSemi) {
112388             return empty;
112389           } else {
112390             return {
112391               primary: primary,
112392               alternate: alternate
112393             };
112394           }
112395
112396           function isNamelike(osmkey, which) {
112397             if (osmkey === 'old_name') return false;
112398             return patterns[which].test(osmkey) && !notNames.test(osmkey);
112399           }
112400         } // `gatherTuples()`
112401         // Generate all combinations of [key,value,name] that we want to test.
112402         // This prioritizes them so that the primary name and k/v pairs go first
112403         //
112404         // Arguments
112405         //   `tryKVs`: `Object` containing primary and alternate k/v pairs to test
112406         //   `tryNames`: `Object` containing primary and alternate names to test
112407         // Returns
112408         //   `Array`: tuple objects ordered by priority
112409         //
112410
112411
112412         function gatherTuples(tryKVs, tryNames) {
112413           var tuples = [];
112414           ['primary', 'alternate'].forEach(function (whichName) {
112415             // test names longest to shortest
112416             var arr = Array.from(tryNames[whichName]).sort(function (a, b) {
112417               return b.length - a.length;
112418             });
112419             arr.forEach(function (n) {
112420               ['primary', 'alternate'].forEach(function (whichKV) {
112421                 tryKVs[whichKV].forEach(function (kv) {
112422                   var parts = kv.split('/', 2);
112423                   var k = parts[0];
112424                   var v = parts[1];
112425                   tuples.push({
112426                     k: k,
112427                     v: v,
112428                     n: n
112429                   });
112430                 });
112431               });
112432             });
112433           });
112434           return tuples;
112435         } // `_upgradeTags()`
112436         // Try to match a feature to a canonical record in name-suggestion-index
112437         // and upgrade the tags to match.
112438         //
112439         // Arguments
112440         //   `tags`: `Object` containing the feature's OSM tags
112441         //   `loc`: Location where this feature exists, as a [lon, lat]
112442         // Returns
112443         //   `Object` containing the result, or `null` if no changes needed:
112444         //   {
112445         //     'newTags': `Object` - The tags the the feature should have
112446         //     'matched': `Object` - The matched item
112447         //   }
112448         //
112449
112450
112451         function _upgradeTags(tags, loc) {
112452           var newTags = Object.assign({}, tags); // shallow copy
112453
112454           var changed = false; // Before anything, perform trivial Wikipedia/Wikidata replacements
112455
112456           Object.keys(newTags).forEach(function (osmkey) {
112457             var matchTag = osmkey.match(/^(\w+:)?wikidata$/);
112458
112459             if (matchTag) {
112460               // Look at '*:wikidata' tags
112461               var prefix = matchTag[1] || '';
112462               var wd = newTags[osmkey];
112463               var replace = _nsi.replacements[wd]; // If it matches a QID in the replacement list...
112464
112465               if (replace && replace.wikidata !== undefined) {
112466                 // replace or delete `*:wikidata` tag
112467                 changed = true;
112468
112469                 if (replace.wikidata) {
112470                   newTags[osmkey] = replace.wikidata;
112471                 } else {
112472                   delete newTags[osmkey];
112473                 }
112474               }
112475
112476               if (replace && replace.wikipedia !== undefined) {
112477                 // replace or delete `*:wikipedia` tag
112478                 changed = true;
112479                 var wpkey = "".concat(prefix, "wikipedia");
112480
112481                 if (replace.wikipedia) {
112482                   newTags[wpkey] = replace.wikipedia;
112483                 } else {
112484                   delete newTags[wpkey];
112485                 }
112486               }
112487             }
112488           }); // Match a 'route_master' as if it were a 'route' - name-suggestion-index#5184
112489
112490           var isRouteMaster = tags.type === 'route_master'; // Gather key/value tag pairs to try to match
112491
112492           var tryKVs = gatherKVs(tags);
112493
112494           if (!tryKVs.primary.size && !tryKVs.alternate.size) {
112495             return changed ? {
112496               newTags: newTags,
112497               matched: null
112498             } : null;
112499           } // Gather namelike tag values to try to match
112500
112501
112502           var tryNames = gatherNames(tags); // Do `wikidata=*` or `wikipedia=*` tags identify this entity as a chain? - See #6416
112503           // If so, these tags can be swapped to e.g. `brand:wikidata`/`brand:wikipedia`.
112504
112505           var foundQID = _nsi.qids.get(tags.wikidata) || _nsi.qids.get(tags.wikipedia);
112506
112507           if (foundQID) tryNames.primary.add(foundQID); // matcher will recognize the Wikidata QID as name too
112508
112509           if (!tryNames.primary.size && !tryNames.alternate.size) {
112510             return changed ? {
112511               newTags: newTags,
112512               matched: null
112513             } : null;
112514           } // Order the [key,value,name] tuples - test primary names before alternate names
112515
112516
112517           var tuples = gatherTuples(tryKVs, tryNames);
112518           var foundPrimary = false;
112519           var bestItem; // Test [key,value,name] tuples against the NSI matcher until we get a primary match or exhaust all options.
112520
112521           for (var i = 0; i < tuples.length && !foundPrimary; i++) {
112522             var tuple = tuples[i];
112523
112524             var hits = _nsi.matcher.match(tuple.k, tuple.v, tuple.n, loc); // Attempt to match an item in NSI
112525
112526
112527             if (!hits || !hits.length) continue; // no match, try next tuple
112528
112529             if (hits[0].match !== 'primary' && hits[0].match !== 'alternate') break; // a generic match, stop looking
112530             // A match may contain multiple results, the first one is likely the best one for this location
112531             // e.g. `['pfk-a54c14', 'kfc-1ff19c', 'kfc-658eea']`
112532
112533             for (var j = 0; j < hits.length; j++) {
112534               var hit = hits[j];
112535               var isPrimary = hits[j].match === 'primary';
112536               var itemID = hit.itemID;
112537               if (_nsi.dissolved[itemID]) continue; // Don't upgrade to a dissolved item
112538
112539               var item = _nsi.ids.get(itemID);
112540
112541               if (!item) continue;
112542               var mainTag = item.mainTag; // e.g. `brand:wikidata`
112543
112544               var itemQID = item.tags[mainTag]; // e.g. `brand:wikidata` qid
112545
112546               var notQID = newTags["not:".concat(mainTag)]; // e.g. `not:brand:wikidata` qid
112547
112548               if ( // Exceptions, skip this hit
112549               !itemQID || itemQID === notQID || // No `*:wikidata` or matched a `not:*:wikidata`
112550               newTags.office && !item.tags.office // feature may be a corporate office for a brand? - #6416
112551               ) {
112552                 continue; // continue looking
112553               } // If we get here, the hit is good..
112554
112555
112556               if (!bestItem || isPrimary) {
112557                 bestItem = item;
112558
112559                 if (isPrimary) {
112560                   foundPrimary = true;
112561                 }
112562
112563                 break; // can ignore the rest of the hits from this match
112564               }
112565             }
112566           } // At this point we have matched a canonical item and can suggest tag upgrades..
112567
112568
112569           if (bestItem) {
112570             var _ret = function () {
112571               var itemID = bestItem.id;
112572               var item = JSON.parse(JSON.stringify(bestItem)); // deep copy
112573
112574               var tkv = item.tkv;
112575               var parts = tkv.split('/', 3); // tkv = "tree/key/value"
112576
112577               var k = parts[1];
112578               var v = parts[2];
112579               var category = _nsi.data[tkv];
112580               var properties = category.properties || {}; // Preserve some tags that we specifically don't want NSI to overwrite. ('^name', sometimes)
112581
112582               var preserveTags = item.preserveTags || properties.preserveTags || []; // These tags can be toplevel tags -or- attributes - so we generally want to preserve existing values - #8615
112583               // We'll only _replace_ the tag value if this tag is the toplevel/defining tag for the matched item (`k`)
112584
112585               ['building', 'emergency', 'internet_access', 'takeaway'].forEach(function (osmkey) {
112586                 if (k !== osmkey) preserveTags.push("^".concat(osmkey, "$"));
112587               });
112588               var regexes = preserveTags.map(function (s) {
112589                 return new RegExp(s, 'i');
112590               });
112591               var keepTags = {};
112592               Object.keys(newTags).forEach(function (osmkey) {
112593                 if (regexes.some(function (regex) {
112594                   return regex.test(osmkey);
112595                 })) {
112596                   keepTags[osmkey] = newTags[osmkey];
112597                 }
112598               }); // Remove any primary tags ("amenity", "craft", "shop", "man_made", "route", etc) that have a
112599               // value like `amenity=yes` or `shop=yes` (exceptions have already been added to `keepTags` above)
112600
112601               _nsi.kvt.forEach(function (vmap, k) {
112602                 if (newTags[k] === 'yes') delete newTags[k];
112603               }); // Replace mistagged `wikidata`/`wikipedia` with e.g. `brand:wikidata`/`brand:wikipedia`
112604
112605
112606               if (foundQID) {
112607                 delete newTags.wikipedia;
112608                 delete newTags.wikidata;
112609               } // Do the tag upgrade
112610
112611
112612               Object.assign(newTags, item.tags, keepTags); // Swap `route` back to `route_master` - name-suggestion-index#5184
112613
112614               if (isRouteMaster) {
112615                 newTags.route_master = newTags.route;
112616                 delete newTags.route;
112617               } // Special `branch` splitting rules - IF..
112618               // - NSI is suggesting to replace `name`, AND
112619               // - `branch` doesn't already contain something, AND
112620               // - original name has not moved to an alternate name (e.g. "Dunkin' Donuts" -> "Dunkin'"), AND
112621               // - original name is "some name" + "some stuff", THEN
112622               // consider splitting `name` into `name`/`branch`..
112623
112624
112625               var origName = tags.name;
112626               var newName = newTags.name;
112627
112628               if (newName && origName && newName !== origName && !newTags.branch) {
112629                 var newNames = gatherNames(newTags);
112630                 var newSet = new Set([].concat(_toConsumableArray(newNames.primary), _toConsumableArray(newNames.alternate)));
112631                 var isMoved = newSet.has(origName); // another tag holds the original name now
112632
112633                 if (!isMoved) {
112634                   // Test name fragments, longest to shortest, to fit them into a "Name Branch" pattern.
112635                   // e.g. "TUI ReiseCenter - Neuss Innenstadt" -> ["TUI", "ReiseCenter", "Neuss", "Innenstadt"]
112636                   var nameParts = origName.split(/[\s\-\/,.]/);
112637
112638                   for (var split = nameParts.length; split > 0; split--) {
112639                     var name = nameParts.slice(0, split).join(' '); // e.g. "TUI ReiseCenter"
112640
112641                     var branch = nameParts.slice(split).join(' '); // e.g. "Neuss Innenstadt"
112642
112643                     var nameHits = _nsi.matcher.match(k, v, name, loc);
112644
112645                     if (!nameHits || !nameHits.length) continue; // no match, try next name fragment
112646
112647                     if (nameHits.some(function (hit) {
112648                       return hit.itemID === itemID;
112649                     })) {
112650                       // matched the name fragment to the same itemID above
112651                       if (branch) {
112652                         if (notBranches.test(branch)) {
112653                           // "branch" was detected but is noise ("factory outlet", etc)
112654                           newTags.name = origName; // Leave `name` alone, this part of the name may be significant..
112655                         } else {
112656                           var branchHits = _nsi.matcher.match(k, v, branch, loc);
112657
112658                           if (branchHits && branchHits.length) {
112659                             // if "branch" matched something else in NSI..
112660                             if (branchHits[0].match === 'primary' || branchHits[0].match === 'alternate') {
112661                               // if another brand! (e.g. "KFC - Taco Bell"?)
112662                               return {
112663                                 v: null
112664                               }; //   bail out - can't suggest tags in this case
112665                             } // else a generic (e.g. "gas", "cafe") - ignore
112666
112667                           } else {
112668                             // "branch" is not noise and not something in NSI
112669                             newTags.branch = branch; // Stick it in the `branch` tag..
112670                           }
112671                         }
112672                       }
112673
112674                       break;
112675                     }
112676                   }
112677                 }
112678               }
112679
112680               return {
112681                 v: {
112682                   newTags: newTags,
112683                   matched: item
112684                 }
112685               };
112686             }();
112687
112688             if (_typeof(_ret) === "object") return _ret.v;
112689           }
112690
112691           return changed ? {
112692             newTags: newTags,
112693             matched: null
112694           } : null;
112695         } // `_isGenericName()`
112696         // Is the `name` tag generic?
112697         //
112698         // Arguments
112699         //   `tags`: `Object` containing the feature's OSM tags
112700         // Returns
112701         //   `true` if it is generic, `false` if not
112702         //
112703
112704
112705         function _isGenericName(tags) {
112706           var n = tags.name;
112707           if (!n) return false; // tryNames just contains the `name` tag value and nothing else
112708
112709           var tryNames = {
112710             primary: new Set([n]),
112711             alternate: new Set()
112712           }; // Gather key/value tag pairs to try to match
112713
112714           var tryKVs = gatherKVs(tags);
112715           if (!tryKVs.primary.size && !tryKVs.alternate.size) return false; // Order the [key,value,name] tuples - test primary before alternate
112716
112717           var tuples = gatherTuples(tryKVs, tryNames);
112718
112719           for (var i = 0; i < tuples.length; i++) {
112720             var tuple = tuples[i];
112721
112722             var hits = _nsi.matcher.match(tuple.k, tuple.v, tuple.n); // Attempt to match an item in NSI
112723             // If we get a `excludeGeneric` hit, this is a generic name.
112724
112725
112726             if (hits && hits.length && hits[0].match === 'excludeGeneric') return true;
112727           }
112728
112729           return false;
112730         } // PUBLIC INTERFACE
112731
112732
112733         var serviceNsi = {
112734           // `init()`
112735           // On init, start preparing the name-suggestion-index
112736           //
112737           init: function init() {
112738             // Note: service.init is called immediately after the presetManager has started loading its data.
112739             // We expect to chain onto an unfulfilled promise here.
112740             setNsiSources();
112741             _mainPresetIndex.ensureLoaded().then(function () {
112742               return loadNsiPresets();
112743             }).then(function () {
112744               return delay(100);
112745             }) // wait briefly for locationSets to enter the locationManager queue
112746             .then(function () {
112747               return _mainLocations.mergeLocationSets([]);
112748             }) // wait for locationSets to resolve
112749             .then(function () {
112750               return loadNsiData();
112751             }).then(function () {
112752               return _nsiStatus = 'ok';
112753             })["catch"](function () {
112754               return _nsiStatus = 'failed';
112755             });
112756
112757             function delay(msec) {
112758               return new Promise(function (resolve) {
112759                 window.setTimeout(resolve, msec);
112760               });
112761             }
112762           },
112763           // `reset()`
112764           // Reset is called when user saves data to OSM (does nothing here)
112765           //
112766           reset: function reset() {},
112767           // `status()`
112768           // To let other code know how it's going...
112769           //
112770           // Returns
112771           //   `String`: 'loading', 'ok', 'failed'
112772           //
112773           status: function status() {
112774             return _nsiStatus;
112775           },
112776           // `isGenericName()`
112777           // Is the `name` tag generic?
112778           //
112779           // Arguments
112780           //   `tags`: `Object` containing the feature's OSM tags
112781           // Returns
112782           //   `true` if it is generic, `false` if not
112783           //
112784           isGenericName: function isGenericName(tags) {
112785             return _isGenericName(tags);
112786           },
112787           // `upgradeTags()`
112788           // Suggest tag upgrades.
112789           // This function will not modify the input tags, it makes a copy.
112790           //
112791           // Arguments
112792           //   `tags`: `Object` containing the feature's OSM tags
112793           //   `loc`: Location where this feature exists, as a [lon, lat]
112794           // Returns
112795           //   `Object` containing the result, or `null` if no changes needed:
112796           //   {
112797           //     'newTags': `Object` - The tags the the feature should have
112798           //     'matched': `Object` - The matched item
112799           //   }
112800           //
112801           upgradeTags: function upgradeTags(tags, loc) {
112802             return _upgradeTags(tags, loc);
112803           },
112804           // `cache()`
112805           // Direct access to the NSI cache, useful for testing or breaking things
112806           //
112807           // Returns
112808           //   `Object`: the internal NSI cache
112809           //
112810           cache: function cache() {
112811             return _nsi;
112812           }
112813         };
112814
112815         var apibase$1 = 'https://kartaview.org';
112816         var maxResults$1 = 1000;
112817         var tileZoom$1 = 14;
112818         var tiler$3 = utilTiler().zoomExtent([tileZoom$1, tileZoom$1]).skipNullIsland(true);
112819         var dispatch$3 = dispatch$8('loadedImages');
112820         var imgZoom = d3_zoom().extent([[0, 0], [320, 240]]).translateExtent([[0, 0], [320, 240]]).scaleExtent([1, 15]);
112821
112822         var _oscCache;
112823
112824         var _oscSelectedImage;
112825
112826         var _loadViewerPromise$1;
112827
112828         function abortRequest$3(controller) {
112829           controller.abort();
112830         }
112831
112832         function maxPageAtZoom(z) {
112833           if (z < 15) return 2;
112834           if (z === 15) return 5;
112835           if (z === 16) return 10;
112836           if (z === 17) return 20;
112837           if (z === 18) return 40;
112838           if (z > 18) return 80;
112839         }
112840
112841         function loadTiles$1(which, url, projection) {
112842           var currZoom = Math.floor(geoScaleToZoom(projection.scale()));
112843           var tiles = tiler$3.getTiles(projection); // abort inflight requests that are no longer needed
112844
112845           var cache = _oscCache[which];
112846           Object.keys(cache.inflight).forEach(function (k) {
112847             var wanted = tiles.find(function (tile) {
112848               return k.indexOf(tile.id + ',') === 0;
112849             });
112850
112851             if (!wanted) {
112852               abortRequest$3(cache.inflight[k]);
112853               delete cache.inflight[k];
112854             }
112855           });
112856           tiles.forEach(function (tile) {
112857             loadNextTilePage$1(which, currZoom, url, tile);
112858           });
112859         }
112860
112861         function loadNextTilePage$1(which, currZoom, url, tile) {
112862           var cache = _oscCache[which];
112863           var bbox = tile.extent.bbox();
112864           var maxPages = maxPageAtZoom(currZoom);
112865           var nextPage = cache.nextPage[tile.id] || 1;
112866           var params = utilQsString({
112867             ipp: maxResults$1,
112868             page: nextPage,
112869             // client_id: clientId,
112870             bbTopLeft: [bbox.maxY, bbox.minX].join(','),
112871             bbBottomRight: [bbox.minY, bbox.maxX].join(',')
112872           }, true);
112873           if (nextPage > maxPages) return;
112874           var id = tile.id + ',' + String(nextPage);
112875           if (cache.loaded[id] || cache.inflight[id]) return;
112876           var controller = new AbortController();
112877           cache.inflight[id] = controller;
112878           var options = {
112879             method: 'POST',
112880             signal: controller.signal,
112881             body: params,
112882             headers: {
112883               'Content-Type': 'application/x-www-form-urlencoded'
112884             }
112885           };
112886           d3_json(url, options).then(function (data) {
112887             cache.loaded[id] = true;
112888             delete cache.inflight[id];
112889
112890             if (!data || !data.currentPageItems || !data.currentPageItems.length) {
112891               throw new Error('No Data');
112892             }
112893
112894             var features = data.currentPageItems.map(function (item) {
112895               var loc = [+item.lng, +item.lat];
112896               var d;
112897
112898               if (which === 'images') {
112899                 d = {
112900                   loc: loc,
112901                   key: item.id,
112902                   ca: +item.heading,
112903                   captured_at: item.shot_date || item.date_added,
112904                   captured_by: item.username,
112905                   imagePath: item.lth_name,
112906                   sequence_id: item.sequence_id,
112907                   sequence_index: +item.sequence_index
112908                 }; // cache sequence info
112909
112910                 var seq = _oscCache.sequences[d.sequence_id];
112911
112912                 if (!seq) {
112913                   seq = {
112914                     rotation: 0,
112915                     images: []
112916                   };
112917                   _oscCache.sequences[d.sequence_id] = seq;
112918                 }
112919
112920                 seq.images[d.sequence_index] = d;
112921                 _oscCache.images.forImageKey[d.key] = d; // cache imageKey -> image
112922               }
112923
112924               return {
112925                 minX: loc[0],
112926                 minY: loc[1],
112927                 maxX: loc[0],
112928                 maxY: loc[1],
112929                 data: d
112930               };
112931             });
112932             cache.rtree.load(features);
112933
112934             if (data.currentPageItems.length === maxResults$1) {
112935               // more pages to load
112936               cache.nextPage[tile.id] = nextPage + 1;
112937               loadNextTilePage$1(which, currZoom, url, tile);
112938             } else {
112939               cache.nextPage[tile.id] = Infinity; // no more pages to load
112940             }
112941
112942             if (which === 'images') {
112943               dispatch$3.call('loadedImages');
112944             }
112945           })["catch"](function () {
112946             cache.loaded[id] = true;
112947             delete cache.inflight[id];
112948           });
112949         } // partition viewport into higher zoom tiles
112950
112951
112952         function partitionViewport$1(projection) {
112953           var z = geoScaleToZoom(projection.scale());
112954           var z2 = Math.ceil(z * 2) / 2 + 2.5; // round to next 0.5 and add 2.5
112955
112956           var tiler = utilTiler().zoomExtent([z2, z2]);
112957           return tiler.getTiles(projection).map(function (tile) {
112958             return tile.extent;
112959           });
112960         } // no more than `limit` results per partition.
112961
112962
112963         function searchLimited$1(limit, projection, rtree) {
112964           limit = limit || 5;
112965           return partitionViewport$1(projection).reduce(function (result, extent) {
112966             var found = rtree.search(extent.bbox()).slice(0, limit).map(function (d) {
112967               return d.data;
112968             });
112969             return found.length ? result.concat(found) : result;
112970           }, []);
112971         }
112972
112973         var serviceKartaview = {
112974           init: function init() {
112975             if (!_oscCache) {
112976               this.reset();
112977             }
112978
112979             this.event = utilRebind(this, dispatch$3, 'on');
112980           },
112981           reset: function reset() {
112982             if (_oscCache) {
112983               Object.values(_oscCache.images.inflight).forEach(abortRequest$3);
112984             }
112985
112986             _oscCache = {
112987               images: {
112988                 inflight: {},
112989                 loaded: {},
112990                 nextPage: {},
112991                 rtree: new RBush(),
112992                 forImageKey: {}
112993               },
112994               sequences: {}
112995             };
112996             _oscSelectedImage = null;
112997           },
112998           images: function images(projection) {
112999             var limit = 5;
113000             return searchLimited$1(limit, projection, _oscCache.images.rtree);
113001           },
113002           sequences: function sequences(projection) {
113003             var viewport = projection.clipExtent();
113004             var min = [viewport[0][0], viewport[1][1]];
113005             var max = [viewport[1][0], viewport[0][1]];
113006             var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();
113007             var sequenceKeys = {}; // all sequences for images in viewport
113008
113009             _oscCache.images.rtree.search(bbox).forEach(function (d) {
113010               sequenceKeys[d.data.sequence_id] = true;
113011             }); // make linestrings from those sequences
113012
113013
113014             var lineStrings = [];
113015             Object.keys(sequenceKeys).forEach(function (sequenceKey) {
113016               var seq = _oscCache.sequences[sequenceKey];
113017               var images = seq && seq.images;
113018
113019               if (images) {
113020                 lineStrings.push({
113021                   type: 'LineString',
113022                   coordinates: images.map(function (d) {
113023                     return d.loc;
113024                   }).filter(Boolean),
113025                   properties: {
113026                     captured_at: images[0] ? images[0].captured_at : null,
113027                     captured_by: images[0] ? images[0].captured_by : null,
113028                     key: sequenceKey
113029                   }
113030                 });
113031               }
113032             });
113033             return lineStrings;
113034           },
113035           cachedImage: function cachedImage(imageKey) {
113036             return _oscCache.images.forImageKey[imageKey];
113037           },
113038           loadImages: function loadImages(projection) {
113039             var url = apibase$1 + '/1.0/list/nearby-photos/';
113040             loadTiles$1('images', url, projection);
113041           },
113042           ensureViewerLoaded: function ensureViewerLoaded(context) {
113043             if (_loadViewerPromise$1) return _loadViewerPromise$1; // add kartaview-wrapper
113044
113045             var wrap = context.container().select('.photoviewer').selectAll('.kartaview-wrapper').data([0]);
113046             var that = this;
113047             var wrapEnter = wrap.enter().append('div').attr('class', 'photo-wrapper kartaview-wrapper').classed('hide', true).call(imgZoom.on('zoom', zoomPan)).on('dblclick.zoom', null);
113048             wrapEnter.append('div').attr('class', 'photo-attribution fillD');
113049             var controlsEnter = wrapEnter.append('div').attr('class', 'photo-controls-wrap').append('div').attr('class', 'photo-controls');
113050             controlsEnter.append('button').on('click.back', step(-1)).text('◄');
113051             controlsEnter.append('button').on('click.rotate-ccw', rotate(-90)).text('⤿');
113052             controlsEnter.append('button').on('click.rotate-cw', rotate(90)).text('⤾');
113053             controlsEnter.append('button').on('click.forward', step(1)).text('►');
113054             wrapEnter.append('div').attr('class', 'kartaview-image-wrap'); // Register viewer resize handler
113055
113056             context.ui().photoviewer.on('resize.kartaview', function (dimensions) {
113057               imgZoom = d3_zoom().extent([[0, 0], dimensions]).translateExtent([[0, 0], dimensions]).scaleExtent([1, 15]).on('zoom', zoomPan);
113058             });
113059
113060             function zoomPan(d3_event) {
113061               var t = d3_event.transform;
113062               context.container().select('.photoviewer .kartaview-image-wrap').call(utilSetTransform, t.x, t.y, t.k);
113063             }
113064
113065             function rotate(deg) {
113066               return function () {
113067                 if (!_oscSelectedImage) return;
113068                 var sequenceKey = _oscSelectedImage.sequence_id;
113069                 var sequence = _oscCache.sequences[sequenceKey];
113070                 if (!sequence) return;
113071                 var r = sequence.rotation || 0;
113072                 r += deg;
113073                 if (r > 180) r -= 360;
113074                 if (r < -180) r += 360;
113075                 sequence.rotation = r;
113076                 var wrap = context.container().select('.photoviewer .kartaview-wrapper');
113077                 wrap.transition().duration(100).call(imgZoom.transform, identity$2);
113078                 wrap.selectAll('.kartaview-image').transition().duration(100).style('transform', 'rotate(' + r + 'deg)');
113079               };
113080             }
113081
113082             function step(stepBy) {
113083               return function () {
113084                 if (!_oscSelectedImage) return;
113085                 var sequenceKey = _oscSelectedImage.sequence_id;
113086                 var sequence = _oscCache.sequences[sequenceKey];
113087                 if (!sequence) return;
113088                 var nextIndex = _oscSelectedImage.sequence_index + stepBy;
113089                 var nextImage = sequence.images[nextIndex];
113090                 if (!nextImage) return;
113091                 context.map().centerEase(nextImage.loc);
113092                 that.selectImage(context, nextImage.key);
113093               };
113094             } // don't need any async loading so resolve immediately
113095
113096
113097             _loadViewerPromise$1 = Promise.resolve();
113098             return _loadViewerPromise$1;
113099           },
113100           showViewer: function showViewer(context) {
113101             var viewer = context.container().select('.photoviewer').classed('hide', false);
113102             var isHidden = viewer.selectAll('.photo-wrapper.kartaview-wrapper.hide').size();
113103
113104             if (isHidden) {
113105               viewer.selectAll('.photo-wrapper:not(.kartaview-wrapper)').classed('hide', true);
113106               viewer.selectAll('.photo-wrapper.kartaview-wrapper').classed('hide', false);
113107             }
113108
113109             return this;
113110           },
113111           hideViewer: function hideViewer(context) {
113112             _oscSelectedImage = null;
113113             this.updateUrlImage(null);
113114             var viewer = context.container().select('.photoviewer');
113115             if (!viewer.empty()) viewer.datum(null);
113116             viewer.classed('hide', true).selectAll('.photo-wrapper').classed('hide', true);
113117             context.container().selectAll('.viewfield-group, .sequence, .icon-sign').classed('currentView', false);
113118             return this.setStyles(context, null, true);
113119           },
113120           selectImage: function selectImage(context, imageKey) {
113121             var d = this.cachedImage(imageKey);
113122             _oscSelectedImage = d;
113123             this.updateUrlImage(imageKey);
113124             var viewer = context.container().select('.photoviewer');
113125             if (!viewer.empty()) viewer.datum(d);
113126             this.setStyles(context, null, true);
113127             context.container().selectAll('.icon-sign').classed('currentView', false);
113128             if (!d) return this;
113129             var wrap = context.container().select('.photoviewer .kartaview-wrapper');
113130             var imageWrap = wrap.selectAll('.kartaview-image-wrap');
113131             var attribution = wrap.selectAll('.photo-attribution').text('');
113132             wrap.transition().duration(100).call(imgZoom.transform, identity$2);
113133             imageWrap.selectAll('.kartaview-image').remove();
113134
113135             if (d) {
113136               var sequence = _oscCache.sequences[d.sequence_id];
113137               var r = sequence && sequence.rotation || 0;
113138               imageWrap.append('img').attr('class', 'kartaview-image').attr('src', apibase$1 + '/' + d.imagePath).style('transform', 'rotate(' + r + 'deg)');
113139
113140               if (d.captured_by) {
113141                 attribution.append('a').attr('class', 'captured_by').attr('target', '_blank').attr('href', 'https://kartaview.org/user/' + encodeURIComponent(d.captured_by)).text('@' + d.captured_by);
113142                 attribution.append('span').text('|');
113143               }
113144
113145               if (d.captured_at) {
113146                 attribution.append('span').attr('class', 'captured_at').text(localeDateString(d.captured_at));
113147                 attribution.append('span').text('|');
113148               }
113149
113150               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');
113151             }
113152
113153             return this;
113154
113155             function localeDateString(s) {
113156               if (!s) return null;
113157               var options = {
113158                 day: 'numeric',
113159                 month: 'short',
113160                 year: 'numeric'
113161               };
113162               var d = new Date(s);
113163               if (isNaN(d.getTime())) return null;
113164               return d.toLocaleDateString(_mainLocalizer.localeCode(), options);
113165             }
113166           },
113167           getSelectedImage: function getSelectedImage() {
113168             return _oscSelectedImage;
113169           },
113170           getSequenceKeyForImage: function getSequenceKeyForImage(d) {
113171             return d && d.sequence_id;
113172           },
113173           // Updates the currently highlighted sequence and selected bubble.
113174           // Reset is only necessary when interacting with the viewport because
113175           // this implicitly changes the currently selected bubble/sequence
113176           setStyles: function setStyles(context, hovered, reset) {
113177             if (reset) {
113178               // reset all layers
113179               context.container().selectAll('.viewfield-group').classed('highlighted', false).classed('hovered', false).classed('currentView', false);
113180               context.container().selectAll('.sequence').classed('highlighted', false).classed('currentView', false);
113181             }
113182
113183             var hoveredImageKey = hovered && hovered.key;
113184             var hoveredSequenceKey = this.getSequenceKeyForImage(hovered);
113185             var hoveredSequence = hoveredSequenceKey && _oscCache.sequences[hoveredSequenceKey];
113186             var hoveredImageKeys = hoveredSequence && hoveredSequence.images.map(function (d) {
113187               return d.key;
113188             }) || [];
113189             var viewer = context.container().select('.photoviewer');
113190             var selected = viewer.empty() ? undefined : viewer.datum();
113191             var selectedImageKey = selected && selected.key;
113192             var selectedSequenceKey = this.getSequenceKeyForImage(selected);
113193             var selectedSequence = selectedSequenceKey && _oscCache.sequences[selectedSequenceKey];
113194             var selectedImageKeys = selectedSequence && selectedSequence.images.map(function (d) {
113195               return d.key;
113196             }) || []; // highlight sibling viewfields on either the selected or the hovered sequences
113197
113198             var highlightedImageKeys = utilArrayUnion(hoveredImageKeys, selectedImageKeys);
113199             context.container().selectAll('.layer-kartaview .viewfield-group').classed('highlighted', function (d) {
113200               return highlightedImageKeys.indexOf(d.key) !== -1;
113201             }).classed('hovered', function (d) {
113202               return d.key === hoveredImageKey;
113203             }).classed('currentView', function (d) {
113204               return d.key === selectedImageKey;
113205             });
113206             context.container().selectAll('.layer-kartaview .sequence').classed('highlighted', function (d) {
113207               return d.properties.key === hoveredSequenceKey;
113208             }).classed('currentView', function (d) {
113209               return d.properties.key === selectedSequenceKey;
113210             }); // update viewfields if needed
113211
113212             context.container().selectAll('.layer-kartaview .viewfield-group .viewfield').attr('d', viewfieldPath);
113213
113214             function viewfieldPath() {
113215               var d = this.parentNode.__data__;
113216
113217               if (d.pano && d.key !== selectedImageKey) {
113218                 return 'M 8,13 m -10,0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0';
113219               } else {
113220                 return 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z';
113221               }
113222             }
113223
113224             return this;
113225           },
113226           updateUrlImage: function updateUrlImage(imageKey) {
113227             if (!window.mocha) {
113228               var hash = utilStringQs(window.location.hash);
113229
113230               if (imageKey) {
113231                 hash.photo = 'kartaview/' + imageKey;
113232               } else {
113233                 delete hash.photo;
113234               }
113235
113236               window.location.replace('#' + utilQsString(hash, true));
113237             }
113238           },
113239           cache: function cache() {
113240             return _oscCache;
113241           }
113242         };
113243
113244         var hashes$1 = {exports: {}};
113245
113246         (function (module, exports) {
113247           (function () {
113248             var Hashes;
113249
113250             function utf8Encode(str) {
113251               var x,
113252                   y,
113253                   output = '',
113254                   i = -1,
113255                   l;
113256
113257               if (str && str.length) {
113258                 l = str.length;
113259
113260                 while ((i += 1) < l) {
113261                   /* Decode utf-16 surrogate pairs */
113262                   x = str.charCodeAt(i);
113263                   y = i + 1 < l ? str.charCodeAt(i + 1) : 0;
113264
113265                   if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) {
113266                     x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
113267                     i += 1;
113268                   }
113269                   /* Encode output as utf-8 */
113270
113271
113272                   if (x <= 0x7F) {
113273                     output += String.fromCharCode(x);
113274                   } else if (x <= 0x7FF) {
113275                     output += String.fromCharCode(0xC0 | x >>> 6 & 0x1F, 0x80 | x & 0x3F);
113276                   } else if (x <= 0xFFFF) {
113277                     output += String.fromCharCode(0xE0 | x >>> 12 & 0x0F, 0x80 | x >>> 6 & 0x3F, 0x80 | x & 0x3F);
113278                   } else if (x <= 0x1FFFFF) {
113279                     output += String.fromCharCode(0xF0 | x >>> 18 & 0x07, 0x80 | x >>> 12 & 0x3F, 0x80 | x >>> 6 & 0x3F, 0x80 | x & 0x3F);
113280                   }
113281                 }
113282               }
113283
113284               return output;
113285             }
113286
113287             function utf8Decode(str) {
113288               var i,
113289                   ac,
113290                   c1,
113291                   c2,
113292                   c3,
113293                   arr = [],
113294                   l;
113295               i = ac = c1 = c2 = c3 = 0;
113296
113297               if (str && str.length) {
113298                 l = str.length;
113299                 str += '';
113300
113301                 while (i < l) {
113302                   c1 = str.charCodeAt(i);
113303                   ac += 1;
113304
113305                   if (c1 < 128) {
113306                     arr[ac] = String.fromCharCode(c1);
113307                     i += 1;
113308                   } else if (c1 > 191 && c1 < 224) {
113309                     c2 = str.charCodeAt(i + 1);
113310                     arr[ac] = String.fromCharCode((c1 & 31) << 6 | c2 & 63);
113311                     i += 2;
113312                   } else {
113313                     c2 = str.charCodeAt(i + 1);
113314                     c3 = str.charCodeAt(i + 2);
113315                     arr[ac] = String.fromCharCode((c1 & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
113316                     i += 3;
113317                   }
113318                 }
113319               }
113320
113321               return arr.join('');
113322             }
113323             /**
113324              * Add integers, wrapping at 2^32. This uses 16-bit operations internally
113325              * to work around bugs in some JS interpreters.
113326              */
113327
113328
113329             function safe_add(x, y) {
113330               var lsw = (x & 0xFFFF) + (y & 0xFFFF),
113331                   msw = (x >> 16) + (y >> 16) + (lsw >> 16);
113332               return msw << 16 | lsw & 0xFFFF;
113333             }
113334             /**
113335              * Bitwise rotate a 32-bit number to the left.
113336              */
113337
113338
113339             function bit_rol(num, cnt) {
113340               return num << cnt | num >>> 32 - cnt;
113341             }
113342             /**
113343              * Convert a raw string to a hex string
113344              */
113345
113346
113347             function rstr2hex(input, hexcase) {
113348               var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef',
113349                   output = '',
113350                   x,
113351                   i = 0,
113352                   l = input.length;
113353
113354               for (; i < l; i += 1) {
113355                 x = input.charCodeAt(i);
113356                 output += hex_tab.charAt(x >>> 4 & 0x0F) + hex_tab.charAt(x & 0x0F);
113357               }
113358
113359               return output;
113360             }
113361             /**
113362              * Convert an array of big-endian words to a string
113363              */
113364
113365
113366             function binb2rstr(input) {
113367               var i,
113368                   l = input.length * 32,
113369                   output = '';
113370
113371               for (i = 0; i < l; i += 8) {
113372                 output += String.fromCharCode(input[i >> 5] >>> 24 - i % 32 & 0xFF);
113373               }
113374
113375               return output;
113376             }
113377             /**
113378              * Convert an array of little-endian words to a string
113379              */
113380
113381
113382             function binl2rstr(input) {
113383               var i,
113384                   l = input.length * 32,
113385                   output = '';
113386
113387               for (i = 0; i < l; i += 8) {
113388                 output += String.fromCharCode(input[i >> 5] >>> i % 32 & 0xFF);
113389               }
113390
113391               return output;
113392             }
113393             /**
113394              * Convert a raw string to an array of little-endian words
113395              * Characters >255 have their high-byte silently ignored.
113396              */
113397
113398
113399             function rstr2binl(input) {
113400               var i,
113401                   l = input.length * 8,
113402                   output = Array(input.length >> 2),
113403                   lo = output.length;
113404
113405               for (i = 0; i < lo; i += 1) {
113406                 output[i] = 0;
113407               }
113408
113409               for (i = 0; i < l; i += 8) {
113410                 output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << i % 32;
113411               }
113412
113413               return output;
113414             }
113415             /**
113416              * Convert a raw string to an array of big-endian words
113417              * Characters >255 have their high-byte silently ignored.
113418              */
113419
113420
113421             function rstr2binb(input) {
113422               var i,
113423                   l = input.length * 8,
113424                   output = Array(input.length >> 2),
113425                   lo = output.length;
113426
113427               for (i = 0; i < lo; i += 1) {
113428                 output[i] = 0;
113429               }
113430
113431               for (i = 0; i < l; i += 8) {
113432                 output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << 24 - i % 32;
113433               }
113434
113435               return output;
113436             }
113437             /**
113438              * Convert a raw string to an arbitrary string encoding
113439              */
113440
113441
113442             function rstr2any(input, encoding) {
113443               var divisor = encoding.length,
113444                   remainders = Array(),
113445                   i,
113446                   q,
113447                   x,
113448                   ld,
113449                   quotient,
113450                   dividend,
113451                   output,
113452                   full_length;
113453               /* Convert to an array of 16-bit big-endian values, forming the dividend */
113454
113455               dividend = Array(Math.ceil(input.length / 2));
113456               ld = dividend.length;
113457
113458               for (i = 0; i < ld; i += 1) {
113459                 dividend[i] = input.charCodeAt(i * 2) << 8 | input.charCodeAt(i * 2 + 1);
113460               }
113461               /**
113462                * Repeatedly perform a long division. The binary array forms the dividend,
113463                * the length of the encoding is the divisor. Once computed, the quotient
113464                * forms the dividend for the next step. We stop when the dividend is zerHashes.
113465                * All remainders are stored for later use.
113466                */
113467
113468
113469               while (dividend.length > 0) {
113470                 quotient = Array();
113471                 x = 0;
113472
113473                 for (i = 0; i < dividend.length; i += 1) {
113474                   x = (x << 16) + dividend[i];
113475                   q = Math.floor(x / divisor);
113476                   x -= q * divisor;
113477
113478                   if (quotient.length > 0 || q > 0) {
113479                     quotient[quotient.length] = q;
113480                   }
113481                 }
113482
113483                 remainders[remainders.length] = x;
113484                 dividend = quotient;
113485               }
113486               /* Convert the remainders to the output string */
113487
113488
113489               output = '';
113490
113491               for (i = remainders.length - 1; i >= 0; i--) {
113492                 output += encoding.charAt(remainders[i]);
113493               }
113494               /* Append leading zero equivalents */
113495
113496
113497               full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2)));
113498
113499               for (i = output.length; i < full_length; i += 1) {
113500                 output = encoding[0] + output;
113501               }
113502
113503               return output;
113504             }
113505             /**
113506              * Convert a raw string to a base-64 string
113507              */
113508
113509
113510             function rstr2b64(input, b64pad) {
113511               var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
113512                   output = '',
113513                   len = input.length,
113514                   i,
113515                   j,
113516                   triplet;
113517               b64pad = b64pad || '=';
113518
113519               for (i = 0; i < len; i += 3) {
113520                 triplet = input.charCodeAt(i) << 16 | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
113521
113522                 for (j = 0; j < 4; j += 1) {
113523                   if (i * 8 + j * 6 > input.length * 8) {
113524                     output += b64pad;
113525                   } else {
113526                     output += tab.charAt(triplet >>> 6 * (3 - j) & 0x3F);
113527                   }
113528                 }
113529               }
113530
113531               return output;
113532             }
113533
113534             Hashes = {
113535               /**
113536                * @property {String} version
113537                * @readonly
113538                */
113539               VERSION: '1.0.6',
113540
113541               /**
113542                * @member Hashes
113543                * @class Base64
113544                * @constructor
113545                */
113546               Base64: function Base64() {
113547                 // private properties
113548                 var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
113549                     pad = '=',
113550                     // URL encoding support @todo
113551                 utf8 = true; // by default enable UTF-8 support encoding
113552                 // public method for encoding
113553
113554                 this.encode = function (input) {
113555                   var i,
113556                       j,
113557                       triplet,
113558                       output = '',
113559                       len = input.length;
113560                   pad = pad || '=';
113561                   input = utf8 ? utf8Encode(input) : input;
113562
113563                   for (i = 0; i < len; i += 3) {
113564                     triplet = input.charCodeAt(i) << 16 | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
113565
113566                     for (j = 0; j < 4; j += 1) {
113567                       if (i * 8 + j * 6 > len * 8) {
113568                         output += pad;
113569                       } else {
113570                         output += tab.charAt(triplet >>> 6 * (3 - j) & 0x3F);
113571                       }
113572                     }
113573                   }
113574
113575                   return output;
113576                 }; // public method for decoding
113577
113578
113579                 this.decode = function (input) {
113580                   // var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
113581                   var i,
113582                       o1,
113583                       o2,
113584                       o3,
113585                       h1,
113586                       h2,
113587                       h3,
113588                       h4,
113589                       bits,
113590                       ac,
113591                       dec = '',
113592                       arr = [];
113593
113594                   if (!input) {
113595                     return input;
113596                   }
113597
113598                   i = ac = 0;
113599                   input = input.replace(new RegExp('\\' + pad, 'gi'), ''); // use '='
113600                   //input += '';
113601
113602                   do {
113603                     // unpack four hexets into three octets using index points in b64
113604                     h1 = tab.indexOf(input.charAt(i += 1));
113605                     h2 = tab.indexOf(input.charAt(i += 1));
113606                     h3 = tab.indexOf(input.charAt(i += 1));
113607                     h4 = tab.indexOf(input.charAt(i += 1));
113608                     bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
113609                     o1 = bits >> 16 & 0xff;
113610                     o2 = bits >> 8 & 0xff;
113611                     o3 = bits & 0xff;
113612                     ac += 1;
113613
113614                     if (h3 === 64) {
113615                       arr[ac] = String.fromCharCode(o1);
113616                     } else if (h4 === 64) {
113617                       arr[ac] = String.fromCharCode(o1, o2);
113618                     } else {
113619                       arr[ac] = String.fromCharCode(o1, o2, o3);
113620                     }
113621                   } while (i < input.length);
113622
113623                   dec = arr.join('');
113624                   dec = utf8 ? utf8Decode(dec) : dec;
113625                   return dec;
113626                 }; // set custom pad string
113627
113628
113629                 this.setPad = function (str) {
113630                   pad = str || pad;
113631                   return this;
113632                 }; // set custom tab string characters
113633
113634
113635                 this.setTab = function (str) {
113636                   tab = str || tab;
113637                   return this;
113638                 };
113639
113640                 this.setUTF8 = function (bool) {
113641                   if (typeof bool === 'boolean') {
113642                     utf8 = bool;
113643                   }
113644
113645                   return this;
113646                 };
113647               },
113648
113649               /**
113650                * CRC-32 calculation
113651                * @member Hashes
113652                * @method CRC32
113653                * @static
113654                * @param {String} str Input String
113655                * @return {String}
113656                */
113657               CRC32: function CRC32(str) {
113658                 var crc = 0,
113659                     x = 0,
113660                     y = 0,
113661                     table,
113662                     i,
113663                     iTop;
113664                 str = utf8Encode(str);
113665                 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('');
113666                 crc = crc ^ -1;
113667
113668                 for (i = 0, iTop = str.length; i < iTop; i += 1) {
113669                   y = (crc ^ str.charCodeAt(i)) & 0xFF;
113670                   x = '0x' + table.substr(y * 9, 8);
113671                   crc = crc >>> 8 ^ x;
113672                 } // always return a positive number (that's what >>> 0 does)
113673
113674
113675                 return (crc ^ -1) >>> 0;
113676               },
113677
113678               /**
113679                * @member Hashes
113680                * @class MD5
113681                * @constructor
113682                * @param {Object} [config]
113683                *
113684                * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
113685                * Digest Algorithm, as defined in RFC 1321.
113686                * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
113687                * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
113688                * See <http://pajhome.org.uk/crypt/md5> for more infHashes.
113689                */
113690               MD5: function MD5(options) {
113691                 /**
113692                  * Private config properties. You may need to tweak these to be compatible with
113693                  * the server-side, but the defaults work in most cases.
113694                  * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
113695                  */
113696                 var hexcase = options && typeof options.uppercase === 'boolean' ? options.uppercase : false,
113697                     // hexadecimal output case format. false - lowercase; true - uppercase
113698                 b64pad = options && typeof options.pad === 'string' ? options.pad : '=',
113699                     // base-64 pad character. Defaults to '=' for strict RFC compliance
113700                 utf8 = options && typeof options.utf8 === 'boolean' ? options.utf8 : true; // enable/disable utf8 encoding
113701                 // privileged (public) methods
113702
113703                 this.hex = function (s) {
113704                   return rstr2hex(rstr(s), hexcase);
113705                 };
113706
113707                 this.b64 = function (s) {
113708                   return rstr2b64(rstr(s), b64pad);
113709                 };
113710
113711                 this.any = function (s, e) {
113712                   return rstr2any(rstr(s), e);
113713                 };
113714
113715                 this.raw = function (s) {
113716                   return rstr(s);
113717                 };
113718
113719                 this.hex_hmac = function (k, d) {
113720                   return rstr2hex(rstr_hmac(k, d), hexcase);
113721                 };
113722
113723                 this.b64_hmac = function (k, d) {
113724                   return rstr2b64(rstr_hmac(k, d), b64pad);
113725                 };
113726
113727                 this.any_hmac = function (k, d, e) {
113728                   return rstr2any(rstr_hmac(k, d), e);
113729                 };
113730                 /**
113731                  * Perform a simple self-test to see if the VM is working
113732                  * @return {String} Hexadecimal hash sample
113733                  */
113734
113735
113736                 this.vm_test = function () {
113737                   return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
113738                 };
113739                 /**
113740                  * Enable/disable uppercase hexadecimal returned string
113741                  * @param {Boolean}
113742                  * @return {Object} this
113743                  */
113744
113745
113746                 this.setUpperCase = function (a) {
113747                   if (typeof a === 'boolean') {
113748                     hexcase = a;
113749                   }
113750
113751                   return this;
113752                 };
113753                 /**
113754                  * Defines a base64 pad string
113755                  * @param {String} Pad
113756                  * @return {Object} this
113757                  */
113758
113759
113760                 this.setPad = function (a) {
113761                   b64pad = a || b64pad;
113762                   return this;
113763                 };
113764                 /**
113765                  * Defines a base64 pad string
113766                  * @param {Boolean}
113767                  * @return {Object} [this]
113768                  */
113769
113770
113771                 this.setUTF8 = function (a) {
113772                   if (typeof a === 'boolean') {
113773                     utf8 = a;
113774                   }
113775
113776                   return this;
113777                 }; // private methods
113778
113779                 /**
113780                  * Calculate the MD5 of a raw string
113781                  */
113782
113783
113784                 function rstr(s) {
113785                   s = utf8 ? utf8Encode(s) : s;
113786                   return binl2rstr(binl(rstr2binl(s), s.length * 8));
113787                 }
113788                 /**
113789                  * Calculate the HMAC-MD5, of a key and some data (raw strings)
113790                  */
113791
113792
113793                 function rstr_hmac(key, data) {
113794                   var bkey, ipad, opad, hash, i;
113795                   key = utf8 ? utf8Encode(key) : key;
113796                   data = utf8 ? utf8Encode(data) : data;
113797                   bkey = rstr2binl(key);
113798
113799                   if (bkey.length > 16) {
113800                     bkey = binl(bkey, key.length * 8);
113801                   }
113802
113803                   ipad = Array(16), opad = Array(16);
113804
113805                   for (i = 0; i < 16; i += 1) {
113806                     ipad[i] = bkey[i] ^ 0x36363636;
113807                     opad[i] = bkey[i] ^ 0x5C5C5C5C;
113808                   }
113809
113810                   hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
113811                   return binl2rstr(binl(opad.concat(hash), 512 + 128));
113812                 }
113813                 /**
113814                  * Calculate the MD5 of an array of little-endian words, and a bit length.
113815                  */
113816
113817
113818                 function binl(x, len) {
113819                   var i,
113820                       olda,
113821                       oldb,
113822                       oldc,
113823                       oldd,
113824                       a = 1732584193,
113825                       b = -271733879,
113826                       c = -1732584194,
113827                       d = 271733878;
113828                   /* append padding */
113829
113830                   x[len >> 5] |= 0x80 << len % 32;
113831                   x[(len + 64 >>> 9 << 4) + 14] = len;
113832
113833                   for (i = 0; i < x.length; i += 16) {
113834                     olda = a;
113835                     oldb = b;
113836                     oldc = c;
113837                     oldd = d;
113838                     a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936);
113839                     d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
113840                     c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
113841                     b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
113842                     a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
113843                     d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
113844                     c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
113845                     b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
113846                     a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
113847                     d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
113848                     c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
113849                     b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
113850                     a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
113851                     d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
113852                     c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
113853                     b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
113854                     a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
113855                     d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
113856                     c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
113857                     b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302);
113858                     a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
113859                     d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
113860                     c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
113861                     b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
113862                     a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
113863                     d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
113864                     c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
113865                     b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
113866                     a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
113867                     d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
113868                     c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
113869                     b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
113870                     a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
113871                     d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
113872                     c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
113873                     b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
113874                     a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
113875                     d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
113876                     c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
113877                     b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
113878                     a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
113879                     d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222);
113880                     c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
113881                     b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
113882                     a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
113883                     d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
113884                     c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
113885                     b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
113886                     a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844);
113887                     d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
113888                     c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
113889                     b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
113890                     a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
113891                     d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
113892                     c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
113893                     b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
113894                     a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
113895                     d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
113896                     c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
113897                     b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
113898                     a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
113899                     d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
113900                     c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
113901                     b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
113902                     a = safe_add(a, olda);
113903                     b = safe_add(b, oldb);
113904                     c = safe_add(c, oldc);
113905                     d = safe_add(d, oldd);
113906                   }
113907
113908                   return Array(a, b, c, d);
113909                 }
113910                 /**
113911                  * These functions implement the four basic operations the algorithm uses.
113912                  */
113913
113914
113915                 function md5_cmn(q, a, b, x, s, t) {
113916                   return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
113917                 }
113918
113919                 function md5_ff(a, b, c, d, x, s, t) {
113920                   return md5_cmn(b & c | ~b & d, a, b, x, s, t);
113921                 }
113922
113923                 function md5_gg(a, b, c, d, x, s, t) {
113924                   return md5_cmn(b & d | c & ~d, a, b, x, s, t);
113925                 }
113926
113927                 function md5_hh(a, b, c, d, x, s, t) {
113928                   return md5_cmn(b ^ c ^ d, a, b, x, s, t);
113929                 }
113930
113931                 function md5_ii(a, b, c, d, x, s, t) {
113932                   return md5_cmn(c ^ (b | ~d), a, b, x, s, t);
113933                 }
113934               },
113935
113936               /**
113937                * @member Hashes
113938                * @class Hashes.SHA1
113939                * @param {Object} [config]
113940                * @constructor
113941                *
113942                * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1
113943                * Version 2.2 Copyright Paul Johnston 2000 - 2009.
113944                * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
113945                * See http://pajhome.org.uk/crypt/md5 for details.
113946                */
113947               SHA1: function SHA1(options) {
113948                 /**
113949                  * Private config properties. You may need to tweak these to be compatible with
113950                  * the server-side, but the defaults work in most cases.
113951                  * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
113952                  */
113953                 var hexcase = options && typeof options.uppercase === 'boolean' ? options.uppercase : false,
113954                     // hexadecimal output case format. false - lowercase; true - uppercase
113955                 b64pad = options && typeof options.pad === 'string' ? options.pad : '=',
113956                     // base-64 pad character. Defaults to '=' for strict RFC compliance
113957                 utf8 = options && typeof options.utf8 === 'boolean' ? options.utf8 : true; // enable/disable utf8 encoding
113958                 // public methods
113959
113960                 this.hex = function (s) {
113961                   return rstr2hex(rstr(s), hexcase);
113962                 };
113963
113964                 this.b64 = function (s) {
113965                   return rstr2b64(rstr(s), b64pad);
113966                 };
113967
113968                 this.any = function (s, e) {
113969                   return rstr2any(rstr(s), e);
113970                 };
113971
113972                 this.raw = function (s) {
113973                   return rstr(s);
113974                 };
113975
113976                 this.hex_hmac = function (k, d) {
113977                   return rstr2hex(rstr_hmac(k, d));
113978                 };
113979
113980                 this.b64_hmac = function (k, d) {
113981                   return rstr2b64(rstr_hmac(k, d), b64pad);
113982                 };
113983
113984                 this.any_hmac = function (k, d, e) {
113985                   return rstr2any(rstr_hmac(k, d), e);
113986                 };
113987                 /**
113988                  * Perform a simple self-test to see if the VM is working
113989                  * @return {String} Hexadecimal hash sample
113990                  * @public
113991                  */
113992
113993
113994                 this.vm_test = function () {
113995                   return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
113996                 };
113997                 /**
113998                  * @description Enable/disable uppercase hexadecimal returned string
113999                  * @param {boolean}
114000                  * @return {Object} this
114001                  * @public
114002                  */
114003
114004
114005                 this.setUpperCase = function (a) {
114006                   if (typeof a === 'boolean') {
114007                     hexcase = a;
114008                   }
114009
114010                   return this;
114011                 };
114012                 /**
114013                  * @description Defines a base64 pad string
114014                  * @param {string} Pad
114015                  * @return {Object} this
114016                  * @public
114017                  */
114018
114019
114020                 this.setPad = function (a) {
114021                   b64pad = a || b64pad;
114022                   return this;
114023                 };
114024                 /**
114025                  * @description Defines a base64 pad string
114026                  * @param {boolean}
114027                  * @return {Object} this
114028                  * @public
114029                  */
114030
114031
114032                 this.setUTF8 = function (a) {
114033                   if (typeof a === 'boolean') {
114034                     utf8 = a;
114035                   }
114036
114037                   return this;
114038                 }; // private methods
114039
114040                 /**
114041                  * Calculate the SHA-512 of a raw string
114042                  */
114043
114044
114045                 function rstr(s) {
114046                   s = utf8 ? utf8Encode(s) : s;
114047                   return binb2rstr(binb(rstr2binb(s), s.length * 8));
114048                 }
114049                 /**
114050                  * Calculate the HMAC-SHA1 of a key and some data (raw strings)
114051                  */
114052
114053
114054                 function rstr_hmac(key, data) {
114055                   var bkey, ipad, opad, i, hash;
114056                   key = utf8 ? utf8Encode(key) : key;
114057                   data = utf8 ? utf8Encode(data) : data;
114058                   bkey = rstr2binb(key);
114059
114060                   if (bkey.length > 16) {
114061                     bkey = binb(bkey, key.length * 8);
114062                   }
114063
114064                   ipad = Array(16), opad = Array(16);
114065
114066                   for (i = 0; i < 16; i += 1) {
114067                     ipad[i] = bkey[i] ^ 0x36363636;
114068                     opad[i] = bkey[i] ^ 0x5C5C5C5C;
114069                   }
114070
114071                   hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
114072                   return binb2rstr(binb(opad.concat(hash), 512 + 160));
114073                 }
114074                 /**
114075                  * Calculate the SHA-1 of an array of big-endian words, and a bit length
114076                  */
114077
114078
114079                 function binb(x, len) {
114080                   var i,
114081                       j,
114082                       t,
114083                       olda,
114084                       oldb,
114085                       oldc,
114086                       oldd,
114087                       olde,
114088                       w = Array(80),
114089                       a = 1732584193,
114090                       b = -271733879,
114091                       c = -1732584194,
114092                       d = 271733878,
114093                       e = -1009589776;
114094                   /* append padding */
114095
114096                   x[len >> 5] |= 0x80 << 24 - len % 32;
114097                   x[(len + 64 >> 9 << 4) + 15] = len;
114098
114099                   for (i = 0; i < x.length; i += 16) {
114100                     olda = a;
114101                     oldb = b;
114102                     oldc = c;
114103                     oldd = d;
114104                     olde = e;
114105
114106                     for (j = 0; j < 80; j += 1) {
114107                       if (j < 16) {
114108                         w[j] = x[i + j];
114109                       } else {
114110                         w[j] = bit_rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
114111                       }
114112
114113                       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)));
114114                       e = d;
114115                       d = c;
114116                       c = bit_rol(b, 30);
114117                       b = a;
114118                       a = t;
114119                     }
114120
114121                     a = safe_add(a, olda);
114122                     b = safe_add(b, oldb);
114123                     c = safe_add(c, oldc);
114124                     d = safe_add(d, oldd);
114125                     e = safe_add(e, olde);
114126                   }
114127
114128                   return Array(a, b, c, d, e);
114129                 }
114130                 /**
114131                  * Perform the appropriate triplet combination function for the current
114132                  * iteration
114133                  */
114134
114135
114136                 function sha1_ft(t, b, c, d) {
114137                   if (t < 20) {
114138                     return b & c | ~b & d;
114139                   }
114140
114141                   if (t < 40) {
114142                     return b ^ c ^ d;
114143                   }
114144
114145                   if (t < 60) {
114146                     return b & c | b & d | c & d;
114147                   }
114148
114149                   return b ^ c ^ d;
114150                 }
114151                 /**
114152                  * Determine the appropriate additive constant for the current iteration
114153                  */
114154
114155
114156                 function sha1_kt(t) {
114157                   return t < 20 ? 1518500249 : t < 40 ? 1859775393 : t < 60 ? -1894007588 : -899497514;
114158                 }
114159               },
114160
114161               /**
114162                * @class Hashes.SHA256
114163                * @param {config}
114164                *
114165                * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined in FIPS 180-2
114166                * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009.
114167                * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
114168                * See http://pajhome.org.uk/crypt/md5 for details.
114169                * Also http://anmar.eu.org/projects/jssha2/
114170                */
114171               SHA256: function SHA256(options) {
114172                 /**
114173                  * Private properties configuration variables. You may need to tweak these to be compatible with
114174                  * the server-side, but the defaults work in most cases.
114175                  * @see this.setUpperCase() method
114176                  * @see this.setPad() method
114177                  */
114178                 options && typeof options.uppercase === 'boolean' ? options.uppercase : false;
114179                     var // hexadecimal output case format. false - lowercase; true - uppercase  */
114180                 b64pad = options && typeof options.pad === 'string' ? options.pad : '=',
114181
114182                 /* base-64 pad character. Default '=' for strict RFC compliance   */
114183                 utf8 = options && typeof options.utf8 === 'boolean' ? options.utf8 : true,
114184
114185                 /* enable/disable utf8 encoding */
114186                 sha256_K;
114187                 /* privileged (public) methods */
114188
114189                 this.hex = function (s) {
114190                   return rstr2hex(rstr(s, utf8));
114191                 };
114192
114193                 this.b64 = function (s) {
114194                   return rstr2b64(rstr(s, utf8), b64pad);
114195                 };
114196
114197                 this.any = function (s, e) {
114198                   return rstr2any(rstr(s, utf8), e);
114199                 };
114200
114201                 this.raw = function (s) {
114202                   return rstr(s, utf8);
114203                 };
114204
114205                 this.hex_hmac = function (k, d) {
114206                   return rstr2hex(rstr_hmac(k, d));
114207                 };
114208
114209                 this.b64_hmac = function (k, d) {
114210                   return rstr2b64(rstr_hmac(k, d), b64pad);
114211                 };
114212
114213                 this.any_hmac = function (k, d, e) {
114214                   return rstr2any(rstr_hmac(k, d), e);
114215                 };
114216                 /**
114217                  * Perform a simple self-test to see if the VM is working
114218                  * @return {String} Hexadecimal hash sample
114219                  * @public
114220                  */
114221
114222
114223                 this.vm_test = function () {
114224                   return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
114225                 };
114226                 /**
114227                  * Enable/disable uppercase hexadecimal returned string
114228                  * @param {boolean}
114229                  * @return {Object} this
114230                  * @public
114231                  */
114232
114233
114234                 this.setUpperCase = function (a) {
114235
114236                   return this;
114237                 };
114238                 /**
114239                  * @description Defines a base64 pad string
114240                  * @param {string} Pad
114241                  * @return {Object} this
114242                  * @public
114243                  */
114244
114245
114246                 this.setPad = function (a) {
114247                   b64pad = a || b64pad;
114248                   return this;
114249                 };
114250                 /**
114251                  * Defines a base64 pad string
114252                  * @param {boolean}
114253                  * @return {Object} this
114254                  * @public
114255                  */
114256
114257
114258                 this.setUTF8 = function (a) {
114259                   if (typeof a === 'boolean') {
114260                     utf8 = a;
114261                   }
114262
114263                   return this;
114264                 }; // private methods
114265
114266                 /**
114267                  * Calculate the SHA-512 of a raw string
114268                  */
114269
114270
114271                 function rstr(s, utf8) {
114272                   s = utf8 ? utf8Encode(s) : s;
114273                   return binb2rstr(binb(rstr2binb(s), s.length * 8));
114274                 }
114275                 /**
114276                  * Calculate the HMAC-sha256 of a key and some data (raw strings)
114277                  */
114278
114279
114280                 function rstr_hmac(key, data) {
114281                   key = utf8 ? utf8Encode(key) : key;
114282                   data = utf8 ? utf8Encode(data) : data;
114283                   var hash,
114284                       i = 0,
114285                       bkey = rstr2binb(key),
114286                       ipad = Array(16),
114287                       opad = Array(16);
114288
114289                   if (bkey.length > 16) {
114290                     bkey = binb(bkey, key.length * 8);
114291                   }
114292
114293                   for (; i < 16; i += 1) {
114294                     ipad[i] = bkey[i] ^ 0x36363636;
114295                     opad[i] = bkey[i] ^ 0x5C5C5C5C;
114296                   }
114297
114298                   hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
114299                   return binb2rstr(binb(opad.concat(hash), 512 + 256));
114300                 }
114301                 /*
114302                  * Main sha256 function, with its support functions
114303                  */
114304
114305
114306                 function sha256_S(X, n) {
114307                   return X >>> n | X << 32 - n;
114308                 }
114309
114310                 function sha256_R(X, n) {
114311                   return X >>> n;
114312                 }
114313
114314                 function sha256_Ch(x, y, z) {
114315                   return x & y ^ ~x & z;
114316                 }
114317
114318                 function sha256_Maj(x, y, z) {
114319                   return x & y ^ x & z ^ y & z;
114320                 }
114321
114322                 function sha256_Sigma0256(x) {
114323                   return sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22);
114324                 }
114325
114326                 function sha256_Sigma1256(x) {
114327                   return sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25);
114328                 }
114329
114330                 function sha256_Gamma0256(x) {
114331                   return sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3);
114332                 }
114333
114334                 function sha256_Gamma1256(x) {
114335                   return sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10);
114336                 }
114337
114338                 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];
114339
114340                 function binb(m, l) {
114341                   var HASH = [1779033703, -1150833019, 1013904242, -1521486534, 1359893119, -1694144372, 528734635, 1541459225];
114342                   var W = new Array(64);
114343                   var a, b, c, d, e, f, g, h;
114344                   var i, j, T1, T2;
114345                   /* append padding */
114346
114347                   m[l >> 5] |= 0x80 << 24 - l % 32;
114348                   m[(l + 64 >> 9 << 4) + 15] = l;
114349
114350                   for (i = 0; i < m.length; i += 16) {
114351                     a = HASH[0];
114352                     b = HASH[1];
114353                     c = HASH[2];
114354                     d = HASH[3];
114355                     e = HASH[4];
114356                     f = HASH[5];
114357                     g = HASH[6];
114358                     h = HASH[7];
114359
114360                     for (j = 0; j < 64; j += 1) {
114361                       if (j < 16) {
114362                         W[j] = m[j + i];
114363                       } else {
114364                         W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]), sha256_Gamma0256(W[j - 15])), W[j - 16]);
114365                       }
114366
114367                       T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)), sha256_K[j]), W[j]);
114368                       T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));
114369                       h = g;
114370                       g = f;
114371                       f = e;
114372                       e = safe_add(d, T1);
114373                       d = c;
114374                       c = b;
114375                       b = a;
114376                       a = safe_add(T1, T2);
114377                     }
114378
114379                     HASH[0] = safe_add(a, HASH[0]);
114380                     HASH[1] = safe_add(b, HASH[1]);
114381                     HASH[2] = safe_add(c, HASH[2]);
114382                     HASH[3] = safe_add(d, HASH[3]);
114383                     HASH[4] = safe_add(e, HASH[4]);
114384                     HASH[5] = safe_add(f, HASH[5]);
114385                     HASH[6] = safe_add(g, HASH[6]);
114386                     HASH[7] = safe_add(h, HASH[7]);
114387                   }
114388
114389                   return HASH;
114390                 }
114391               },
114392
114393               /**
114394                * @class Hashes.SHA512
114395                * @param {config}
114396                *
114397                * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined in FIPS 180-2
114398                * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009.
114399                * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
114400                * See http://pajhome.org.uk/crypt/md5 for details.
114401                */
114402               SHA512: function SHA512(options) {
114403                 /**
114404                  * Private properties configuration variables. You may need to tweak these to be compatible with
114405                  * the server-side, but the defaults work in most cases.
114406                  * @see this.setUpperCase() method
114407                  * @see this.setPad() method
114408                  */
114409                 options && typeof options.uppercase === 'boolean' ? options.uppercase : false;
114410
114411                 var /* hexadecimal output case format. false - lowercase; true - uppercase  */
114412                 b64pad = options && typeof options.pad === 'string' ? options.pad : '=',
114413
114414                 /* base-64 pad character. Default '=' for strict RFC compliance   */
114415                 utf8 = options && typeof options.utf8 === 'boolean' ? options.utf8 : true,
114416
114417                 /* enable/disable utf8 encoding */
114418                 sha512_k;
114419                 /* privileged (public) methods */
114420
114421                 this.hex = function (s) {
114422                   return rstr2hex(rstr(s));
114423                 };
114424
114425                 this.b64 = function (s) {
114426                   return rstr2b64(rstr(s), b64pad);
114427                 };
114428
114429                 this.any = function (s, e) {
114430                   return rstr2any(rstr(s), e);
114431                 };
114432
114433                 this.raw = function (s) {
114434                   return rstr(s);
114435                 };
114436
114437                 this.hex_hmac = function (k, d) {
114438                   return rstr2hex(rstr_hmac(k, d));
114439                 };
114440
114441                 this.b64_hmac = function (k, d) {
114442                   return rstr2b64(rstr_hmac(k, d), b64pad);
114443                 };
114444
114445                 this.any_hmac = function (k, d, e) {
114446                   return rstr2any(rstr_hmac(k, d), e);
114447                 };
114448                 /**
114449                  * Perform a simple self-test to see if the VM is working
114450                  * @return {String} Hexadecimal hash sample
114451                  * @public
114452                  */
114453
114454
114455                 this.vm_test = function () {
114456                   return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
114457                 };
114458                 /**
114459                  * @description Enable/disable uppercase hexadecimal returned string
114460                  * @param {boolean}
114461                  * @return {Object} this
114462                  * @public
114463                  */
114464
114465
114466                 this.setUpperCase = function (a) {
114467
114468                   return this;
114469                 };
114470                 /**
114471                  * @description Defines a base64 pad string
114472                  * @param {string} Pad
114473                  * @return {Object} this
114474                  * @public
114475                  */
114476
114477
114478                 this.setPad = function (a) {
114479                   b64pad = a || b64pad;
114480                   return this;
114481                 };
114482                 /**
114483                  * @description Defines a base64 pad string
114484                  * @param {boolean}
114485                  * @return {Object} this
114486                  * @public
114487                  */
114488
114489
114490                 this.setUTF8 = function (a) {
114491                   if (typeof a === 'boolean') {
114492                     utf8 = a;
114493                   }
114494
114495                   return this;
114496                 };
114497                 /* private methods */
114498
114499                 /**
114500                  * Calculate the SHA-512 of a raw string
114501                  */
114502
114503
114504                 function rstr(s) {
114505                   s = utf8 ? utf8Encode(s) : s;
114506                   return binb2rstr(binb(rstr2binb(s), s.length * 8));
114507                 }
114508                 /*
114509                  * Calculate the HMAC-SHA-512 of a key and some data (raw strings)
114510                  */
114511
114512
114513                 function rstr_hmac(key, data) {
114514                   key = utf8 ? utf8Encode(key) : key;
114515                   data = utf8 ? utf8Encode(data) : data;
114516                   var hash,
114517                       i = 0,
114518                       bkey = rstr2binb(key),
114519                       ipad = Array(32),
114520                       opad = Array(32);
114521
114522                   if (bkey.length > 32) {
114523                     bkey = binb(bkey, key.length * 8);
114524                   }
114525
114526                   for (; i < 32; i += 1) {
114527                     ipad[i] = bkey[i] ^ 0x36363636;
114528                     opad[i] = bkey[i] ^ 0x5C5C5C5C;
114529                   }
114530
114531                   hash = binb(ipad.concat(rstr2binb(data)), 1024 + data.length * 8);
114532                   return binb2rstr(binb(opad.concat(hash), 1024 + 512));
114533                 }
114534                 /**
114535                  * Calculate the SHA-512 of an array of big-endian dwords, and a bit length
114536                  */
114537
114538
114539                 function binb(x, len) {
114540                   var j,
114541                       i,
114542                       l,
114543                       W = new Array(80),
114544                       hash = new Array(16),
114545                       //Initial hash values
114546                   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)],
114547                       T1 = new int64(0, 0),
114548                       T2 = new int64(0, 0),
114549                       a = new int64(0, 0),
114550                       b = new int64(0, 0),
114551                       c = new int64(0, 0),
114552                       d = new int64(0, 0),
114553                       e = new int64(0, 0),
114554                       f = new int64(0, 0),
114555                       g = new int64(0, 0),
114556                       h = new int64(0, 0),
114557                       //Temporary variables not specified by the document
114558                   s0 = new int64(0, 0),
114559                       s1 = new int64(0, 0),
114560                       Ch = new int64(0, 0),
114561                       Maj = new int64(0, 0),
114562                       r1 = new int64(0, 0),
114563                       r2 = new int64(0, 0),
114564                       r3 = new int64(0, 0);
114565
114566                   if (sha512_k === undefined) {
114567                     //SHA512 constants
114568                     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)];
114569                   }
114570
114571                   for (i = 0; i < 80; i += 1) {
114572                     W[i] = new int64(0, 0);
114573                   } // append padding to the source string. The format is described in the FIPS.
114574
114575
114576                   x[len >> 5] |= 0x80 << 24 - (len & 0x1f);
114577                   x[(len + 128 >> 10 << 5) + 31] = len;
114578                   l = x.length;
114579
114580                   for (i = 0; i < l; i += 32) {
114581                     //32 dwords is the block size
114582                     int64copy(a, H[0]);
114583                     int64copy(b, H[1]);
114584                     int64copy(c, H[2]);
114585                     int64copy(d, H[3]);
114586                     int64copy(e, H[4]);
114587                     int64copy(f, H[5]);
114588                     int64copy(g, H[6]);
114589                     int64copy(h, H[7]);
114590
114591                     for (j = 0; j < 16; j += 1) {
114592                       W[j].h = x[i + 2 * j];
114593                       W[j].l = x[i + 2 * j + 1];
114594                     }
114595
114596                     for (j = 16; j < 80; j += 1) {
114597                       //sigma1
114598                       int64rrot(r1, W[j - 2], 19);
114599                       int64revrrot(r2, W[j - 2], 29);
114600                       int64shr(r3, W[j - 2], 6);
114601                       s1.l = r1.l ^ r2.l ^ r3.l;
114602                       s1.h = r1.h ^ r2.h ^ r3.h; //sigma0
114603
114604                       int64rrot(r1, W[j - 15], 1);
114605                       int64rrot(r2, W[j - 15], 8);
114606                       int64shr(r3, W[j - 15], 7);
114607                       s0.l = r1.l ^ r2.l ^ r3.l;
114608                       s0.h = r1.h ^ r2.h ^ r3.h;
114609                       int64add4(W[j], s1, W[j - 7], s0, W[j - 16]);
114610                     }
114611
114612                     for (j = 0; j < 80; j += 1) {
114613                       //Ch
114614                       Ch.l = e.l & f.l ^ ~e.l & g.l;
114615                       Ch.h = e.h & f.h ^ ~e.h & g.h; //Sigma1
114616
114617                       int64rrot(r1, e, 14);
114618                       int64rrot(r2, e, 18);
114619                       int64revrrot(r3, e, 9);
114620                       s1.l = r1.l ^ r2.l ^ r3.l;
114621                       s1.h = r1.h ^ r2.h ^ r3.h; //Sigma0
114622
114623                       int64rrot(r1, a, 28);
114624                       int64revrrot(r2, a, 2);
114625                       int64revrrot(r3, a, 7);
114626                       s0.l = r1.l ^ r2.l ^ r3.l;
114627                       s0.h = r1.h ^ r2.h ^ r3.h; //Maj
114628
114629                       Maj.l = a.l & b.l ^ a.l & c.l ^ b.l & c.l;
114630                       Maj.h = a.h & b.h ^ a.h & c.h ^ b.h & c.h;
114631                       int64add5(T1, h, s1, Ch, sha512_k[j], W[j]);
114632                       int64add(T2, s0, Maj);
114633                       int64copy(h, g);
114634                       int64copy(g, f);
114635                       int64copy(f, e);
114636                       int64add(e, d, T1);
114637                       int64copy(d, c);
114638                       int64copy(c, b);
114639                       int64copy(b, a);
114640                       int64add(a, T1, T2);
114641                     }
114642
114643                     int64add(H[0], H[0], a);
114644                     int64add(H[1], H[1], b);
114645                     int64add(H[2], H[2], c);
114646                     int64add(H[3], H[3], d);
114647                     int64add(H[4], H[4], e);
114648                     int64add(H[5], H[5], f);
114649                     int64add(H[6], H[6], g);
114650                     int64add(H[7], H[7], h);
114651                   } //represent the hash as an array of 32-bit dwords
114652
114653
114654                   for (i = 0; i < 8; i += 1) {
114655                     hash[2 * i] = H[i].h;
114656                     hash[2 * i + 1] = H[i].l;
114657                   }
114658
114659                   return hash;
114660                 } //A constructor for 64-bit numbers
114661
114662
114663                 function int64(h, l) {
114664                   this.h = h;
114665                   this.l = l; //this.toString = int64toString;
114666                 } //Copies src into dst, assuming both are 64-bit numbers
114667
114668
114669                 function int64copy(dst, src) {
114670                   dst.h = src.h;
114671                   dst.l = src.l;
114672                 } //Right-rotates a 64-bit number by shift
114673                 //Won't handle cases of shift>=32
114674                 //The function revrrot() is for that
114675
114676
114677                 function int64rrot(dst, x, shift) {
114678                   dst.l = x.l >>> shift | x.h << 32 - shift;
114679                   dst.h = x.h >>> shift | x.l << 32 - shift;
114680                 } //Reverses the dwords of the source and then rotates right by shift.
114681                 //This is equivalent to rotation by 32+shift
114682
114683
114684                 function int64revrrot(dst, x, shift) {
114685                   dst.l = x.h >>> shift | x.l << 32 - shift;
114686                   dst.h = x.l >>> shift | x.h << 32 - shift;
114687                 } //Bitwise-shifts right a 64-bit number by shift
114688                 //Won't handle shift>=32, but it's never needed in SHA512
114689
114690
114691                 function int64shr(dst, x, shift) {
114692                   dst.l = x.l >>> shift | x.h << 32 - shift;
114693                   dst.h = x.h >>> shift;
114694                 } //Adds two 64-bit numbers
114695                 //Like the original implementation, does not rely on 32-bit operations
114696
114697
114698                 function int64add(dst, x, y) {
114699                   var w0 = (x.l & 0xffff) + (y.l & 0xffff);
114700                   var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16);
114701                   var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16);
114702                   var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16);
114703                   dst.l = w0 & 0xffff | w1 << 16;
114704                   dst.h = w2 & 0xffff | w3 << 16;
114705                 } //Same, except with 4 addends. Works faster than adding them one by one.
114706
114707
114708                 function int64add4(dst, a, b, c, d) {
114709                   var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff);
114710                   var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16);
114711                   var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16);
114712                   var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16);
114713                   dst.l = w0 & 0xffff | w1 << 16;
114714                   dst.h = w2 & 0xffff | w3 << 16;
114715                 } //Same, except with 5 addends
114716
114717
114718                 function int64add5(dst, a, b, c, d, e) {
114719                   var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff),
114720                       w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16),
114721                       w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16),
114722                       w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16);
114723                   dst.l = w0 & 0xffff | w1 << 16;
114724                   dst.h = w2 & 0xffff | w3 << 16;
114725                 }
114726               },
114727
114728               /**
114729                * @class Hashes.RMD160
114730                * @constructor
114731                * @param {Object} [config]
114732                *
114733                * A JavaScript implementation of the RIPEMD-160 Algorithm
114734                * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009.
114735                * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
114736                * See http://pajhome.org.uk/crypt/md5 for details.
114737                * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/
114738                */
114739               RMD160: function RMD160(options) {
114740                 /**
114741                  * Private properties configuration variables. You may need to tweak these to be compatible with
114742                  * the server-side, but the defaults work in most cases.
114743                  * @see this.setUpperCase() method
114744                  * @see this.setPad() method
114745                  */
114746                 options && typeof options.uppercase === 'boolean' ? options.uppercase : false;
114747
114748                 var /* hexadecimal output case format. false - lowercase; true - uppercase  */
114749                 b64pad = options && typeof options.pad === 'string' ? options.pa : '=',
114750
114751                 /* base-64 pad character. Default '=' for strict RFC compliance   */
114752                 utf8 = options && typeof options.utf8 === 'boolean' ? options.utf8 : true,
114753
114754                 /* enable/disable utf8 encoding */
114755                 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],
114756                     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],
114757                     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],
114758                     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];
114759                 /* privileged (public) methods */
114760
114761                 this.hex = function (s) {
114762                   return rstr2hex(rstr(s));
114763                 };
114764
114765                 this.b64 = function (s) {
114766                   return rstr2b64(rstr(s), b64pad);
114767                 };
114768
114769                 this.any = function (s, e) {
114770                   return rstr2any(rstr(s), e);
114771                 };
114772
114773                 this.raw = function (s) {
114774                   return rstr(s);
114775                 };
114776
114777                 this.hex_hmac = function (k, d) {
114778                   return rstr2hex(rstr_hmac(k, d));
114779                 };
114780
114781                 this.b64_hmac = function (k, d) {
114782                   return rstr2b64(rstr_hmac(k, d), b64pad);
114783                 };
114784
114785                 this.any_hmac = function (k, d, e) {
114786                   return rstr2any(rstr_hmac(k, d), e);
114787                 };
114788                 /**
114789                  * Perform a simple self-test to see if the VM is working
114790                  * @return {String} Hexadecimal hash sample
114791                  * @public
114792                  */
114793
114794
114795                 this.vm_test = function () {
114796                   return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
114797                 };
114798                 /**
114799                  * @description Enable/disable uppercase hexadecimal returned string
114800                  * @param {boolean}
114801                  * @return {Object} this
114802                  * @public
114803                  */
114804
114805
114806                 this.setUpperCase = function (a) {
114807
114808                   return this;
114809                 };
114810                 /**
114811                  * @description Defines a base64 pad string
114812                  * @param {string} Pad
114813                  * @return {Object} this
114814                  * @public
114815                  */
114816
114817
114818                 this.setPad = function (a) {
114819                   if (typeof a !== 'undefined') {
114820                     b64pad = a;
114821                   }
114822
114823                   return this;
114824                 };
114825                 /**
114826                  * @description Defines a base64 pad string
114827                  * @param {boolean}
114828                  * @return {Object} this
114829                  * @public
114830                  */
114831
114832
114833                 this.setUTF8 = function (a) {
114834                   if (typeof a === 'boolean') {
114835                     utf8 = a;
114836                   }
114837
114838                   return this;
114839                 };
114840                 /* private methods */
114841
114842                 /**
114843                  * Calculate the rmd160 of a raw string
114844                  */
114845
114846
114847                 function rstr(s) {
114848                   s = utf8 ? utf8Encode(s) : s;
114849                   return binl2rstr(binl(rstr2binl(s), s.length * 8));
114850                 }
114851                 /**
114852                  * Calculate the HMAC-rmd160 of a key and some data (raw strings)
114853                  */
114854
114855
114856                 function rstr_hmac(key, data) {
114857                   key = utf8 ? utf8Encode(key) : key;
114858                   data = utf8 ? utf8Encode(data) : data;
114859                   var i,
114860                       hash,
114861                       bkey = rstr2binl(key),
114862                       ipad = Array(16),
114863                       opad = Array(16);
114864
114865                   if (bkey.length > 16) {
114866                     bkey = binl(bkey, key.length * 8);
114867                   }
114868
114869                   for (i = 0; i < 16; i += 1) {
114870                     ipad[i] = bkey[i] ^ 0x36363636;
114871                     opad[i] = bkey[i] ^ 0x5C5C5C5C;
114872                   }
114873
114874                   hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
114875                   return binl2rstr(binl(opad.concat(hash), 512 + 160));
114876                 }
114877                 /**
114878                  * Convert an array of little-endian words to a string
114879                  */
114880
114881
114882                 function binl2rstr(input) {
114883                   var i,
114884                       output = '',
114885                       l = input.length * 32;
114886
114887                   for (i = 0; i < l; i += 8) {
114888                     output += String.fromCharCode(input[i >> 5] >>> i % 32 & 0xFF);
114889                   }
114890
114891                   return output;
114892                 }
114893                 /**
114894                  * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length.
114895                  */
114896
114897
114898                 function binl(x, len) {
114899                   var T,
114900                       j,
114901                       i,
114902                       l,
114903                       h0 = 0x67452301,
114904                       h1 = 0xefcdab89,
114905                       h2 = 0x98badcfe,
114906                       h3 = 0x10325476,
114907                       h4 = 0xc3d2e1f0,
114908                       A1,
114909                       B1,
114910                       C1,
114911                       D1,
114912                       E1,
114913                       A2,
114914                       B2,
114915                       C2,
114916                       D2,
114917                       E2;
114918                   /* append padding */
114919
114920                   x[len >> 5] |= 0x80 << len % 32;
114921                   x[(len + 64 >>> 9 << 4) + 14] = len;
114922                   l = x.length;
114923
114924                   for (i = 0; i < l; i += 16) {
114925                     A1 = A2 = h0;
114926                     B1 = B2 = h1;
114927                     C1 = C2 = h2;
114928                     D1 = D2 = h3;
114929                     E1 = E2 = h4;
114930
114931                     for (j = 0; j <= 79; j += 1) {
114932                       T = safe_add(A1, rmd160_f(j, B1, C1, D1));
114933                       T = safe_add(T, x[i + rmd160_r1[j]]);
114934                       T = safe_add(T, rmd160_K1(j));
114935                       T = safe_add(bit_rol(T, rmd160_s1[j]), E1);
114936                       A1 = E1;
114937                       E1 = D1;
114938                       D1 = bit_rol(C1, 10);
114939                       C1 = B1;
114940                       B1 = T;
114941                       T = safe_add(A2, rmd160_f(79 - j, B2, C2, D2));
114942                       T = safe_add(T, x[i + rmd160_r2[j]]);
114943                       T = safe_add(T, rmd160_K2(j));
114944                       T = safe_add(bit_rol(T, rmd160_s2[j]), E2);
114945                       A2 = E2;
114946                       E2 = D2;
114947                       D2 = bit_rol(C2, 10);
114948                       C2 = B2;
114949                       B2 = T;
114950                     }
114951
114952                     T = safe_add(h1, safe_add(C1, D2));
114953                     h1 = safe_add(h2, safe_add(D1, E2));
114954                     h2 = safe_add(h3, safe_add(E1, A2));
114955                     h3 = safe_add(h4, safe_add(A1, B2));
114956                     h4 = safe_add(h0, safe_add(B1, C2));
114957                     h0 = T;
114958                   }
114959
114960                   return [h0, h1, h2, h3, h4];
114961                 } // specific algorithm methods
114962
114963
114964                 function rmd160_f(j, x, y, z) {
114965                   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';
114966                 }
114967
114968                 function rmd160_K1(j) {
114969                   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';
114970                 }
114971
114972                 function rmd160_K2(j) {
114973                   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';
114974                 }
114975               }
114976             }; // exposes Hashes
114977
114978             (function (window, undefined$1) {
114979               var freeExports = false;
114980
114981               {
114982                 freeExports = exports;
114983
114984                 if (exports && _typeof(commonjsGlobal) === 'object' && commonjsGlobal && commonjsGlobal === commonjsGlobal.global) {
114985                   window = commonjsGlobal;
114986                 }
114987               }
114988
114989               if (typeof undefined$1 === 'function' && _typeof(undefined$1.amd) === 'object' && undefined$1.amd) {
114990                 // define as an anonymous module, so, through path mapping, it can be aliased
114991                 undefined$1(function () {
114992                   return Hashes;
114993                 });
114994               } else if (freeExports) {
114995                 // in Node.js or RingoJS v0.8.0+
114996                 if (module && module.exports === freeExports) {
114997                   module.exports = Hashes;
114998                 } // in Narwhal or RingoJS v0.7.0-
114999                 else {
115000                   freeExports.Hashes = Hashes;
115001                 }
115002               } else {
115003                 // in a browser or Rhino
115004                 window.Hashes = Hashes;
115005               }
115006             })(this);
115007           })(); // IIFE
115008
115009         })(hashes$1, hashes$1.exports);
115010
115011         var hashes = hashes$1.exports,
115012             sha1 = new hashes.SHA1(); // # xtend
115013
115014         var hasOwnProperty$1 = Object.prototype.hasOwnProperty;
115015
115016         function xtend$1() {
115017           var target = {};
115018
115019           for (var i = 0; i < arguments.length; i++) {
115020             var source = arguments[i];
115021
115022             for (var key in source) {
115023               if (hasOwnProperty$1.call(source, key)) {
115024                 target[key] = source[key];
115025               }
115026             }
115027           }
115028
115029           return target;
115030         }
115031
115032         var ohauth$1 = {};
115033
115034         ohauth$1.qsString = function (obj) {
115035           return Object.keys(obj).sort().map(function (key) {
115036             return ohauth$1.percentEncode(key) + '=' + ohauth$1.percentEncode(obj[key]);
115037           }).join('&');
115038         };
115039
115040         ohauth$1.stringQs = function (str) {
115041           return str.split('&').filter(function (pair) {
115042             return pair !== '';
115043           }).reduce(function (obj, pair) {
115044             var parts = pair.split('=');
115045             obj[decodeURIComponent(parts[0])] = null === parts[1] ? '' : decodeURIComponent(parts[1]);
115046             return obj;
115047           }, {});
115048         };
115049
115050         ohauth$1.rawxhr = function (method, url, data, headers, callback) {
115051           var xhr = new XMLHttpRequest(),
115052               twoHundred = /^20\d$/;
115053
115054           xhr.onreadystatechange = function () {
115055             if (4 === xhr.readyState && 0 !== xhr.status) {
115056               if (twoHundred.test(xhr.status)) callback(null, xhr);else return callback(xhr, null);
115057             }
115058           };
115059
115060           xhr.onerror = function (e) {
115061             return callback(e, null);
115062           };
115063
115064           xhr.open(method, url, true);
115065
115066           for (var h in headers) {
115067             xhr.setRequestHeader(h, headers[h]);
115068           }
115069
115070           xhr.send(data);
115071           return xhr;
115072         };
115073
115074         ohauth$1.xhr = function (method, url, auth, data, options, callback) {
115075           var headers = options && options.header || {
115076             'Content-Type': 'application/x-www-form-urlencoded'
115077           };
115078           headers.Authorization = 'OAuth ' + ohauth$1.authHeader(auth);
115079           return ohauth$1.rawxhr(method, url, data, headers, callback);
115080         };
115081
115082         ohauth$1.nonce = function () {
115083           for (var o = ''; o.length < 6;) {
115084             o += '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'[Math.floor(Math.random() * 61)];
115085           }
115086
115087           return o;
115088         };
115089
115090         ohauth$1.authHeader = function (obj) {
115091           return Object.keys(obj).sort().map(function (key) {
115092             return encodeURIComponent(key) + '="' + encodeURIComponent(obj[key]) + '"';
115093           }).join(', ');
115094         };
115095
115096         ohauth$1.timestamp = function () {
115097           return ~~(+new Date() / 1000);
115098         };
115099
115100         ohauth$1.percentEncode = function (s) {
115101           return encodeURIComponent(s).replace(/\!/g, '%21').replace(/\'/g, '%27').replace(/\*/g, '%2A').replace(/\(/g, '%28').replace(/\)/g, '%29');
115102         };
115103
115104         ohauth$1.baseString = function (method, url, params) {
115105           if (params.oauth_signature) delete params.oauth_signature;
115106           return [method, ohauth$1.percentEncode(url), ohauth$1.percentEncode(ohauth$1.qsString(params))].join('&');
115107         };
115108
115109         ohauth$1.signature = function (oauth_secret, token_secret, baseString) {
115110           return sha1.b64_hmac(ohauth$1.percentEncode(oauth_secret) + '&' + ohauth$1.percentEncode(token_secret), baseString);
115111         };
115112         /**
115113          * Takes an options object for configuration (consumer_key,
115114          * consumer_secret, version, signature_method, token, token_secret)
115115          * and returns a function that generates the Authorization header
115116          * for given data.
115117          *
115118          * The returned function takes these parameters:
115119          * - method: GET/POST/...
115120          * - uri: full URI with protocol, port, path and query string
115121          * - extra_params: any extra parameters (that are passed in the POST data),
115122          *   can be an object or a from-urlencoded string.
115123          *
115124          * Returned function returns full OAuth header with "OAuth" string in it.
115125          */
115126
115127
115128         ohauth$1.headerGenerator = function (options) {
115129           options = options || {};
115130           var consumer_key = options.consumer_key || '',
115131               consumer_secret = options.consumer_secret || '',
115132               signature_method = options.signature_method || 'HMAC-SHA1',
115133               version = options.version || '1.0',
115134               token = options.token || '',
115135               token_secret = options.token_secret || '';
115136           return function (method, uri, extra_params) {
115137             method = method.toUpperCase();
115138
115139             if (typeof extra_params === 'string' && extra_params.length > 0) {
115140               extra_params = ohauth$1.stringQs(extra_params);
115141             }
115142
115143             var uri_parts = uri.split('?', 2),
115144                 base_uri = uri_parts[0];
115145             var query_params = uri_parts.length === 2 ? ohauth$1.stringQs(uri_parts[1]) : {};
115146             var oauth_params = {
115147               oauth_consumer_key: consumer_key,
115148               oauth_signature_method: signature_method,
115149               oauth_version: version,
115150               oauth_timestamp: ohauth$1.timestamp(),
115151               oauth_nonce: ohauth$1.nonce()
115152             };
115153             if (token) oauth_params.oauth_token = token;
115154             var all_params = xtend$1({}, oauth_params, query_params, extra_params),
115155                 base_str = ohauth$1.baseString(method, base_uri, all_params);
115156             oauth_params.oauth_signature = ohauth$1.signature(consumer_secret, token_secret, base_str);
115157             return 'OAuth ' + ohauth$1.authHeader(oauth_params);
115158           };
115159         };
115160
115161         var ohauth_1 = ohauth$1;
115162
115163         var resolveUrl$1 = {exports: {}};
115164
115165         (function (module, exports) {
115166           // Copyright 2014 Simon Lydell
115167           // X11 (“MIT”) Licensed. (See LICENSE.)
115168           void function (root, factory) {
115169             {
115170               module.exports = factory();
115171             }
115172           }(commonjsGlobal, function () {
115173             function
115174               /* ...urls */
115175             resolveUrl() {
115176               var numUrls = arguments.length;
115177
115178               if (numUrls === 0) {
115179                 throw new Error("resolveUrl requires at least one argument; got none.");
115180               }
115181
115182               var base = document.createElement("base");
115183               base.href = arguments[0];
115184
115185               if (numUrls === 1) {
115186                 return base.href;
115187               }
115188
115189               var head = document.getElementsByTagName("head")[0];
115190               head.insertBefore(base, head.firstChild);
115191               var a = document.createElement("a");
115192               var resolved;
115193
115194               for (var index = 1; index < numUrls; index++) {
115195                 a.href = arguments[index];
115196                 resolved = a.href;
115197                 base.href = resolved;
115198               }
115199
115200               head.removeChild(base);
115201               return resolved;
115202             }
115203
115204             return resolveUrl;
115205           });
115206         })(resolveUrl$1);
115207
115208         var assign = make_assign();
115209         var create$1 = make_create();
115210         var trim$1 = make_trim();
115211         var Global$5 = typeof window !== 'undefined' ? window : commonjsGlobal;
115212         var util$6 = {
115213           assign: assign,
115214           create: create$1,
115215           trim: trim$1,
115216           bind: bind$1,
115217           slice: slice$1,
115218           each: each$7,
115219           map: map,
115220           pluck: pluck$1,
115221           isList: isList$1,
115222           isFunction: isFunction$1,
115223           isObject: isObject$1,
115224           Global: Global$5
115225         };
115226
115227         function make_assign() {
115228           if (Object.assign) {
115229             return Object.assign;
115230           } else {
115231             return function shimAssign(obj, props1, props2, etc) {
115232               for (var i = 1; i < arguments.length; i++) {
115233                 each$7(Object(arguments[i]), function (val, key) {
115234                   obj[key] = val;
115235                 });
115236               }
115237
115238               return obj;
115239             };
115240           }
115241         }
115242
115243         function make_create() {
115244           if (Object.create) {
115245             return function create(obj, assignProps1, assignProps2, etc) {
115246               var assignArgsList = slice$1(arguments, 1);
115247               return assign.apply(this, [Object.create(obj)].concat(assignArgsList));
115248             };
115249           } else {
115250             var F = function F() {}; // eslint-disable-line no-inner-declarations
115251
115252
115253             return function create(obj, assignProps1, assignProps2, etc) {
115254               var assignArgsList = slice$1(arguments, 1);
115255               F.prototype = obj;
115256               return assign.apply(this, [new F()].concat(assignArgsList));
115257             };
115258           }
115259         }
115260
115261         function make_trim() {
115262           if (String.prototype.trim) {
115263             return function trim(str) {
115264               return String.prototype.trim.call(str);
115265             };
115266           } else {
115267             return function trim(str) {
115268               return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
115269             };
115270           }
115271         }
115272
115273         function bind$1(obj, fn) {
115274           return function () {
115275             return fn.apply(obj, Array.prototype.slice.call(arguments, 0));
115276           };
115277         }
115278
115279         function slice$1(arr, index) {
115280           return Array.prototype.slice.call(arr, index || 0);
115281         }
115282
115283         function each$7(obj, fn) {
115284           pluck$1(obj, function (val, key) {
115285             fn(val, key);
115286             return false;
115287           });
115288         }
115289
115290         function map(obj, fn) {
115291           var res = isList$1(obj) ? [] : {};
115292           pluck$1(obj, function (v, k) {
115293             res[k] = fn(v, k);
115294             return false;
115295           });
115296           return res;
115297         }
115298
115299         function pluck$1(obj, fn) {
115300           if (isList$1(obj)) {
115301             for (var i = 0; i < obj.length; i++) {
115302               if (fn(obj[i], i)) {
115303                 return obj[i];
115304               }
115305             }
115306           } else {
115307             for (var key in obj) {
115308               if (obj.hasOwnProperty(key)) {
115309                 if (fn(obj[key], key)) {
115310                   return obj[key];
115311                 }
115312               }
115313             }
115314           }
115315         }
115316
115317         function isList$1(val) {
115318           return val != null && typeof val != 'function' && typeof val.length == 'number';
115319         }
115320
115321         function isFunction$1(val) {
115322           return val && {}.toString.call(val) === '[object Function]';
115323         }
115324
115325         function isObject$1(val) {
115326           return val && {}.toString.call(val) === '[object Object]';
115327         }
115328
115329         var util$5 = util$6;
115330         var slice = util$5.slice;
115331         var pluck = util$5.pluck;
115332         var each$6 = util$5.each;
115333         var bind = util$5.bind;
115334         var create = util$5.create;
115335         var isList = util$5.isList;
115336         var isFunction = util$5.isFunction;
115337         var isObject = util$5.isObject;
115338         var storeEngine = {
115339           createStore: _createStore
115340         };
115341         var storeAPI = {
115342           version: '2.0.12',
115343           enabled: false,
115344           // get returns the value of the given key. If that value
115345           // is undefined, it returns optionalDefaultValue instead.
115346           get: function get(key, optionalDefaultValue) {
115347             var data = this.storage.read(this._namespacePrefix + key);
115348             return this._deserialize(data, optionalDefaultValue);
115349           },
115350           // set will store the given value at key and returns value.
115351           // Calling set with value === undefined is equivalent to calling remove.
115352           set: function set(key, value) {
115353             if (value === undefined) {
115354               return this.remove(key);
115355             }
115356
115357             this.storage.write(this._namespacePrefix + key, this._serialize(value));
115358             return value;
115359           },
115360           // remove deletes the key and value stored at the given key.
115361           remove: function remove(key) {
115362             this.storage.remove(this._namespacePrefix + key);
115363           },
115364           // each will call the given callback once for each key-value pair
115365           // in this store.
115366           each: function each(callback) {
115367             var self = this;
115368             this.storage.each(function (val, namespacedKey) {
115369               callback.call(self, self._deserialize(val), (namespacedKey || '').replace(self._namespaceRegexp, ''));
115370             });
115371           },
115372           // clearAll will remove all the stored key-value pairs in this store.
115373           clearAll: function clearAll() {
115374             this.storage.clearAll();
115375           },
115376           // additional functionality that can't live in plugins
115377           // ---------------------------------------------------
115378           // hasNamespace returns true if this store instance has the given namespace.
115379           hasNamespace: function hasNamespace(namespace) {
115380             return this._namespacePrefix == '__storejs_' + namespace + '_';
115381           },
115382           // createStore creates a store.js instance with the first
115383           // functioning storage in the list of storage candidates,
115384           // and applies the the given mixins to the instance.
115385           createStore: function createStore() {
115386             return _createStore.apply(this, arguments);
115387           },
115388           addPlugin: function addPlugin(plugin) {
115389             this._addPlugin(plugin);
115390           },
115391           namespace: function namespace(_namespace) {
115392             return _createStore(this.storage, this.plugins, _namespace);
115393           }
115394         };
115395
115396         function _warn() {
115397           var _console = typeof console == 'undefined' ? null : console;
115398
115399           if (!_console) {
115400             return;
115401           }
115402
115403           var fn = _console.warn ? _console.warn : _console.log;
115404           fn.apply(_console, arguments);
115405         }
115406
115407         function _createStore(storages, plugins, namespace) {
115408           if (!namespace) {
115409             namespace = '';
115410           }
115411
115412           if (storages && !isList(storages)) {
115413             storages = [storages];
115414           }
115415
115416           if (plugins && !isList(plugins)) {
115417             plugins = [plugins];
115418           }
115419
115420           var namespacePrefix = namespace ? '__storejs_' + namespace + '_' : '';
115421           var namespaceRegexp = namespace ? new RegExp('^' + namespacePrefix) : null;
115422           var legalNamespaces = /^[a-zA-Z0-9_\-]*$/; // alpha-numeric + underscore and dash
115423
115424           if (!legalNamespaces.test(namespace)) {
115425             throw new Error('store.js namespaces can only have alphanumerics + underscores and dashes');
115426           }
115427
115428           var _privateStoreProps = {
115429             _namespacePrefix: namespacePrefix,
115430             _namespaceRegexp: namespaceRegexp,
115431             _testStorage: function _testStorage(storage) {
115432               try {
115433                 var testStr = '__storejs__test__';
115434                 storage.write(testStr, testStr);
115435                 var ok = storage.read(testStr) === testStr;
115436                 storage.remove(testStr);
115437                 return ok;
115438               } catch (e) {
115439                 return false;
115440               }
115441             },
115442             _assignPluginFnProp: function _assignPluginFnProp(pluginFnProp, propName) {
115443               var oldFn = this[propName];
115444
115445               this[propName] = function pluginFn() {
115446                 var args = slice(arguments, 0);
115447                 var self = this; // super_fn calls the old function which was overwritten by
115448                 // this mixin.
115449
115450                 function super_fn() {
115451                   if (!oldFn) {
115452                     return;
115453                   }
115454
115455                   each$6(arguments, function (arg, i) {
115456                     args[i] = arg;
115457                   });
115458                   return oldFn.apply(self, args);
115459                 } // Give mixing function access to super_fn by prefixing all mixin function
115460                 // arguments with super_fn.
115461
115462
115463                 var newFnArgs = [super_fn].concat(args);
115464                 return pluginFnProp.apply(self, newFnArgs);
115465               };
115466             },
115467             _serialize: function _serialize(obj) {
115468               return JSON.stringify(obj);
115469             },
115470             _deserialize: function _deserialize(strVal, defaultVal) {
115471               if (!strVal) {
115472                 return defaultVal;
115473               } // It is possible that a raw string value has been previously stored
115474               // in a storage without using store.js, meaning it will be a raw
115475               // string value instead of a JSON serialized string. By defaulting
115476               // to the raw string value in case of a JSON parse error, we allow
115477               // for past stored values to be forwards-compatible with store.js
115478
115479
115480               var val = '';
115481
115482               try {
115483                 val = JSON.parse(strVal);
115484               } catch (e) {
115485                 val = strVal;
115486               }
115487
115488               return val !== undefined ? val : defaultVal;
115489             },
115490             _addStorage: function _addStorage(storage) {
115491               if (this.enabled) {
115492                 return;
115493               }
115494
115495               if (this._testStorage(storage)) {
115496                 this.storage = storage;
115497                 this.enabled = true;
115498               }
115499             },
115500             _addPlugin: function _addPlugin(plugin) {
115501               var self = this; // If the plugin is an array, then add all plugins in the array.
115502               // This allows for a plugin to depend on other plugins.
115503
115504               if (isList(plugin)) {
115505                 each$6(plugin, function (plugin) {
115506                   self._addPlugin(plugin);
115507                 });
115508                 return;
115509               } // Keep track of all plugins we've seen so far, so that we
115510               // don't add any of them twice.
115511
115512
115513               var seenPlugin = pluck(this.plugins, function (seenPlugin) {
115514                 return plugin === seenPlugin;
115515               });
115516
115517               if (seenPlugin) {
115518                 return;
115519               }
115520
115521               this.plugins.push(plugin); // Check that the plugin is properly formed
115522
115523               if (!isFunction(plugin)) {
115524                 throw new Error('Plugins must be function values that return objects');
115525               }
115526
115527               var pluginProperties = plugin.call(this);
115528
115529               if (!isObject(pluginProperties)) {
115530                 throw new Error('Plugins must return an object of function properties');
115531               } // Add the plugin function properties to this store instance.
115532
115533
115534               each$6(pluginProperties, function (pluginFnProp, propName) {
115535                 if (!isFunction(pluginFnProp)) {
115536                   throw new Error('Bad plugin property: ' + propName + ' from plugin ' + plugin.name + '. Plugins should only return functions.');
115537                 }
115538
115539                 self._assignPluginFnProp(pluginFnProp, propName);
115540               });
115541             },
115542             // Put deprecated properties in the private API, so as to not expose it to accidential
115543             // discovery through inspection of the store object.
115544             // Deprecated: addStorage
115545             addStorage: function addStorage(storage) {
115546               _warn('store.addStorage(storage) is deprecated. Use createStore([storages])');
115547
115548               this._addStorage(storage);
115549             }
115550           };
115551           var store = create(_privateStoreProps, storeAPI, {
115552             plugins: []
115553           });
115554           store.raw = {};
115555           each$6(store, function (prop, propName) {
115556             if (isFunction(prop)) {
115557               store.raw[propName] = bind(store, prop);
115558             }
115559           });
115560           each$6(storages, function (storage) {
115561             store._addStorage(storage);
115562           });
115563           each$6(plugins, function (plugin) {
115564             store._addPlugin(plugin);
115565           });
115566           return store;
115567         }
115568
115569         var util$4 = util$6;
115570         var Global$4 = util$4.Global;
115571         var localStorage_1 = {
115572           name: 'localStorage',
115573           read: read$5,
115574           write: write$5,
115575           each: each$5,
115576           remove: remove$5,
115577           clearAll: clearAll$5
115578         };
115579
115580         function localStorage$1() {
115581           return Global$4.localStorage;
115582         }
115583
115584         function read$5(key) {
115585           return localStorage$1().getItem(key);
115586         }
115587
115588         function write$5(key, data) {
115589           return localStorage$1().setItem(key, data);
115590         }
115591
115592         function each$5(fn) {
115593           for (var i = localStorage$1().length - 1; i >= 0; i--) {
115594             var key = localStorage$1().key(i);
115595             fn(read$5(key), key);
115596           }
115597         }
115598
115599         function remove$5(key) {
115600           return localStorage$1().removeItem(key);
115601         }
115602
115603         function clearAll$5() {
115604           return localStorage$1().clear();
115605         }
115606
115607         // versions 6 and 7, where no localStorage, etc
115608         // is available.
115609
115610         var util$3 = util$6;
115611         var Global$3 = util$3.Global;
115612         var oldFFGlobalStorage = {
115613           name: 'oldFF-globalStorage',
115614           read: read$4,
115615           write: write$4,
115616           each: each$4,
115617           remove: remove$4,
115618           clearAll: clearAll$4
115619         };
115620         var globalStorage = Global$3.globalStorage;
115621
115622         function read$4(key) {
115623           return globalStorage[key];
115624         }
115625
115626         function write$4(key, data) {
115627           globalStorage[key] = data;
115628         }
115629
115630         function each$4(fn) {
115631           for (var i = globalStorage.length - 1; i >= 0; i--) {
115632             var key = globalStorage.key(i);
115633             fn(globalStorage[key], key);
115634           }
115635         }
115636
115637         function remove$4(key) {
115638           return globalStorage.removeItem(key);
115639         }
115640
115641         function clearAll$4() {
115642           each$4(function (key, _) {
115643             delete globalStorage[key];
115644           });
115645         }
115646
115647         // versions 6 and 7, where no localStorage, sessionStorage, etc
115648         // is available.
115649
115650         var util$2 = util$6;
115651         var Global$2 = util$2.Global;
115652         var oldIEUserDataStorage = {
115653           name: 'oldIE-userDataStorage',
115654           write: write$3,
115655           read: read$3,
115656           each: each$3,
115657           remove: remove$3,
115658           clearAll: clearAll$3
115659         };
115660         var storageName = 'storejs';
115661         var doc$1 = Global$2.document;
115662
115663         var _withStorageEl = _makeIEStorageElFunction();
115664
115665         var disable = (Global$2.navigator ? Global$2.navigator.userAgent : '').match(/ (MSIE 8|MSIE 9|MSIE 10)\./); // MSIE 9.x, MSIE 10.x
115666
115667         function write$3(unfixedKey, data) {
115668           if (disable) {
115669             return;
115670           }
115671
115672           var fixedKey = fixKey(unfixedKey);
115673
115674           _withStorageEl(function (storageEl) {
115675             storageEl.setAttribute(fixedKey, data);
115676             storageEl.save(storageName);
115677           });
115678         }
115679
115680         function read$3(unfixedKey) {
115681           if (disable) {
115682             return;
115683           }
115684
115685           var fixedKey = fixKey(unfixedKey);
115686           var res = null;
115687
115688           _withStorageEl(function (storageEl) {
115689             res = storageEl.getAttribute(fixedKey);
115690           });
115691
115692           return res;
115693         }
115694
115695         function each$3(callback) {
115696           _withStorageEl(function (storageEl) {
115697             var attributes = storageEl.XMLDocument.documentElement.attributes;
115698
115699             for (var i = attributes.length - 1; i >= 0; i--) {
115700               var attr = attributes[i];
115701               callback(storageEl.getAttribute(attr.name), attr.name);
115702             }
115703           });
115704         }
115705
115706         function remove$3(unfixedKey) {
115707           var fixedKey = fixKey(unfixedKey);
115708
115709           _withStorageEl(function (storageEl) {
115710             storageEl.removeAttribute(fixedKey);
115711             storageEl.save(storageName);
115712           });
115713         }
115714
115715         function clearAll$3() {
115716           _withStorageEl(function (storageEl) {
115717             var attributes = storageEl.XMLDocument.documentElement.attributes;
115718             storageEl.load(storageName);
115719
115720             for (var i = attributes.length - 1; i >= 0; i--) {
115721               storageEl.removeAttribute(attributes[i].name);
115722             }
115723
115724             storageEl.save(storageName);
115725           });
115726         } // Helpers
115727         //////////
115728         // In IE7, keys cannot start with a digit or contain certain chars.
115729         // See https://github.com/marcuswestin/store.js/issues/40
115730         // See https://github.com/marcuswestin/store.js/issues/83
115731
115732
115733         var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g");
115734
115735         function fixKey(key) {
115736           return key.replace(/^\d/, '___$&').replace(forbiddenCharsRegex, '___');
115737         }
115738
115739         function _makeIEStorageElFunction() {
115740           if (!doc$1 || !doc$1.documentElement || !doc$1.documentElement.addBehavior) {
115741             return null;
115742           }
115743
115744           var scriptTag = 'script',
115745               storageOwner,
115746               storageContainer,
115747               storageEl; // Since #userData storage applies only to specific paths, we need to
115748           // somehow link our data to a specific path.  We choose /favicon.ico
115749           // as a pretty safe option, since all browsers already make a request to
115750           // this URL anyway and being a 404 will not hurt us here.  We wrap an
115751           // iframe pointing to the favicon in an ActiveXObject(htmlfile) object
115752           // (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx)
115753           // since the iframe access rules appear to allow direct access and
115754           // manipulation of the document element, even for a 404 page.  This
115755           // document can be used instead of the current document (which would
115756           // have been limited to the current path) to perform #userData storage.
115757
115758           try {
115759             /* global ActiveXObject */
115760             storageContainer = new ActiveXObject('htmlfile');
115761             storageContainer.open();
115762             storageContainer.write('<' + scriptTag + '>document.w=window</' + scriptTag + '><iframe src="/favicon.ico"></iframe>');
115763             storageContainer.close();
115764             storageOwner = storageContainer.w.frames[0].document;
115765             storageEl = storageOwner.createElement('div');
115766           } catch (e) {
115767             // somehow ActiveXObject instantiation failed (perhaps some special
115768             // security settings or otherwse), fall back to per-path storage
115769             storageEl = doc$1.createElement('div');
115770             storageOwner = doc$1.body;
115771           }
115772
115773           return function (storeFunction) {
115774             var args = [].slice.call(arguments, 0);
115775             args.unshift(storageEl); // See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx
115776             // and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx
115777
115778             storageOwner.appendChild(storageEl);
115779             storageEl.addBehavior('#default#userData');
115780             storageEl.load(storageName);
115781             storeFunction.apply(this, args);
115782             storageOwner.removeChild(storageEl);
115783             return;
115784           };
115785         }
115786
115787         // doesn't work but cookies do. This implementation is adopted from
115788         // https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage
115789
115790         var util$1 = util$6;
115791         var Global$1 = util$1.Global;
115792         var trim = util$1.trim;
115793         var cookieStorage = {
115794           name: 'cookieStorage',
115795           read: read$2,
115796           write: write$2,
115797           each: each$2,
115798           remove: remove$2,
115799           clearAll: clearAll$2
115800         };
115801         var doc = Global$1.document;
115802
115803         function read$2(key) {
115804           if (!key || !_has(key)) {
115805             return null;
115806           }
115807
115808           var regexpStr = "(?:^|.*;\\s*)" + escape(key).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*((?:[^;](?!;))*[^;]?).*";
115809           return unescape(doc.cookie.replace(new RegExp(regexpStr), "$1"));
115810         }
115811
115812         function each$2(callback) {
115813           var cookies = doc.cookie.split(/; ?/g);
115814
115815           for (var i = cookies.length - 1; i >= 0; i--) {
115816             if (!trim(cookies[i])) {
115817               continue;
115818             }
115819
115820             var kvp = cookies[i].split('=');
115821             var key = unescape(kvp[0]);
115822             var val = unescape(kvp[1]);
115823             callback(val, key);
115824           }
115825         }
115826
115827         function write$2(key, data) {
115828           if (!key) {
115829             return;
115830           }
115831
115832           doc.cookie = escape(key) + "=" + escape(data) + "; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/";
115833         }
115834
115835         function remove$2(key) {
115836           if (!key || !_has(key)) {
115837             return;
115838           }
115839
115840           doc.cookie = escape(key) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/";
115841         }
115842
115843         function clearAll$2() {
115844           each$2(function (_, key) {
115845             remove$2(key);
115846           });
115847         }
115848
115849         function _has(key) {
115850           return new RegExp("(?:^|;\\s*)" + escape(key).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=").test(doc.cookie);
115851         }
115852
115853         var util = util$6;
115854         var Global = util.Global;
115855         var sessionStorage_1 = {
115856           name: 'sessionStorage',
115857           read: read$1,
115858           write: write$1,
115859           each: each$1,
115860           remove: remove$1,
115861           clearAll: clearAll$1
115862         };
115863
115864         function sessionStorage() {
115865           return Global.sessionStorage;
115866         }
115867
115868         function read$1(key) {
115869           return sessionStorage().getItem(key);
115870         }
115871
115872         function write$1(key, data) {
115873           return sessionStorage().setItem(key, data);
115874         }
115875
115876         function each$1(fn) {
115877           for (var i = sessionStorage().length - 1; i >= 0; i--) {
115878             var key = sessionStorage().key(i);
115879             fn(read$1(key), key);
115880           }
115881         }
115882
115883         function remove$1(key) {
115884           return sessionStorage().removeItem(key);
115885         }
115886
115887         function clearAll$1() {
115888           return sessionStorage().clear();
115889         }
115890
115891         // is functions (meaning store.get(), store.set(), etc will all function).
115892         // However, stored values will not persist when the browser navigates to
115893         // a new page or reloads the current page.
115894
115895         var memoryStorage_1 = {
115896           name: 'memoryStorage',
115897           read: read,
115898           write: write,
115899           each: each,
115900           remove: remove,
115901           clearAll: clearAll
115902         };
115903         var memoryStorage = {};
115904
115905         function read(key) {
115906           return memoryStorage[key];
115907         }
115908
115909         function write(key, data) {
115910           memoryStorage[key] = data;
115911         }
115912
115913         function each(callback) {
115914           for (var key in memoryStorage) {
115915             if (memoryStorage.hasOwnProperty(key)) {
115916               callback(memoryStorage[key], key);
115917             }
115918           }
115919         }
115920
115921         function remove(key) {
115922           delete memoryStorage[key];
115923         }
115924
115925         function clearAll(key) {
115926           memoryStorage = {};
115927         }
115928
115929         var all = [// Listed in order of usage preference
115930         localStorage_1, oldFFGlobalStorage, oldIEUserDataStorage, cookieStorage, sessionStorage_1, memoryStorage_1];
115931
115932         /* eslint-disable */
115933         //  json2.js
115934         //  2016-10-28
115935         //  Public Domain.
115936         //  NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
115937         //  See http://www.JSON.org/js.html
115938         //  This code should be minified before deployment.
115939         //  See http://javascript.crockford.com/jsmin.html
115940         //  USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
115941         //  NOT CONTROL.
115942         //  This file creates a global JSON object containing two methods: stringify
115943         //  and parse. This file provides the ES5 JSON capability to ES3 systems.
115944         //  If a project might run on IE8 or earlier, then this file should be included.
115945         //  This file does nothing on ES5 systems.
115946         //      JSON.stringify(value, replacer, space)
115947         //          value       any JavaScript value, usually an object or array.
115948         //          replacer    an optional parameter that determines how object
115949         //                      values are stringified for objects. It can be a
115950         //                      function or an array of strings.
115951         //          space       an optional parameter that specifies the indentation
115952         //                      of nested structures. If it is omitted, the text will
115953         //                      be packed without extra whitespace. If it is a number,
115954         //                      it will specify the number of spaces to indent at each
115955         //                      level. If it is a string (such as "\t" or "&nbsp;"),
115956         //                      it contains the characters used to indent at each level.
115957         //          This method produces a JSON text from a JavaScript value.
115958         //          When an object value is found, if the object contains a toJSON
115959         //          method, its toJSON method will be called and the result will be
115960         //          stringified. A toJSON method does not serialize: it returns the
115961         //          value represented by the name/value pair that should be serialized,
115962         //          or undefined if nothing should be serialized. The toJSON method
115963         //          will be passed the key associated with the value, and this will be
115964         //          bound to the value.
115965         //          For example, this would serialize Dates as ISO strings.
115966         //              Date.prototype.toJSON = function (key) {
115967         //                  function f(n) {
115968         //                      // Format integers to have at least two digits.
115969         //                      return (n < 10)
115970         //                          ? "0" + n
115971         //                          : n;
115972         //                  }
115973         //                  return this.getUTCFullYear()   + "-" +
115974         //                       f(this.getUTCMonth() + 1) + "-" +
115975         //                       f(this.getUTCDate())      + "T" +
115976         //                       f(this.getUTCHours())     + ":" +
115977         //                       f(this.getUTCMinutes())   + ":" +
115978         //                       f(this.getUTCSeconds())   + "Z";
115979         //              };
115980         //          You can provide an optional replacer method. It will be passed the
115981         //          key and value of each member, with this bound to the containing
115982         //          object. The value that is returned from your method will be
115983         //          serialized. If your method returns undefined, then the member will
115984         //          be excluded from the serialization.
115985         //          If the replacer parameter is an array of strings, then it will be
115986         //          used to select the members to be serialized. It filters the results
115987         //          such that only members with keys listed in the replacer array are
115988         //          stringified.
115989         //          Values that do not have JSON representations, such as undefined or
115990         //          functions, will not be serialized. Such values in objects will be
115991         //          dropped; in arrays they will be replaced with null. You can use
115992         //          a replacer function to replace those with JSON values.
115993         //          JSON.stringify(undefined) returns undefined.
115994         //          The optional space parameter produces a stringification of the
115995         //          value that is filled with line breaks and indentation to make it
115996         //          easier to read.
115997         //          If the space parameter is a non-empty string, then that string will
115998         //          be used for indentation. If the space parameter is a number, then
115999         //          the indentation will be that many spaces.
116000         //          Example:
116001         //          text = JSON.stringify(["e", {pluribus: "unum"}]);
116002         //          // text is '["e",{"pluribus":"unum"}]'
116003         //          text = JSON.stringify(["e", {pluribus: "unum"}], null, "\t");
116004         //          // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
116005         //          text = JSON.stringify([new Date()], function (key, value) {
116006         //              return this[key] instanceof Date
116007         //                  ? "Date(" + this[key] + ")"
116008         //                  : value;
116009         //          });
116010         //          // text is '["Date(---current time---)"]'
116011         //      JSON.parse(text, reviver)
116012         //          This method parses a JSON text to produce an object or array.
116013         //          It can throw a SyntaxError exception.
116014         //          The optional reviver parameter is a function that can filter and
116015         //          transform the results. It receives each of the keys and values,
116016         //          and its return value is used instead of the original value.
116017         //          If it returns what it received, then the structure is not modified.
116018         //          If it returns undefined then the member is deleted.
116019         //          Example:
116020         //          // Parse the text. Values that look like ISO date strings will
116021         //          // be converted to Date objects.
116022         //          myData = JSON.parse(text, function (key, value) {
116023         //              var a;
116024         //              if (typeof value === "string") {
116025         //                  a =
116026         //   /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
116027         //                  if (a) {
116028         //                      return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
116029         //                          +a[5], +a[6]));
116030         //                  }
116031         //              }
116032         //              return value;
116033         //          });
116034         //          myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
116035         //              var d;
116036         //              if (typeof value === "string" &&
116037         //                      value.slice(0, 5) === "Date(" &&
116038         //                      value.slice(-1) === ")") {
116039         //                  d = new Date(value.slice(5, -1));
116040         //                  if (d) {
116041         //                      return d;
116042         //                  }
116043         //              }
116044         //              return value;
116045         //          });
116046         //  This is a reference implementation. You are free to copy, modify, or
116047         //  redistribute.
116048
116049         /*jslint
116050             eval, for, this
116051         */
116052
116053         /*property
116054             JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
116055             getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
116056             lastIndex, length, parse, prototype, push, replace, slice, stringify,
116057             test, toJSON, toString, valueOf
116058         */
116059         // Create a JSON object only if one does not already exist. We create the
116060         // methods in a closure to avoid creating global variables.
116061         if ((typeof JSON === "undefined" ? "undefined" : _typeof(JSON)) !== "object") {
116062           JSON = {};
116063         }
116064
116065         (function () {
116066
116067           var rx_one = /^[\],:{}\s]*$/;
116068           var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
116069           var rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
116070           var rx_four = /(?:^|:|,)(?:\s*\[)+/g;
116071           var rx_escapable = /[\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
116072           var rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
116073
116074           function f(n) {
116075             // Format integers to have at least two digits.
116076             return n < 10 ? "0" + n : n;
116077           }
116078
116079           function this_value() {
116080             return this.valueOf();
116081           }
116082
116083           if (typeof Date.prototype.toJSON !== "function") {
116084             Date.prototype.toJSON = function () {
116085               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;
116086             };
116087
116088             Boolean.prototype.toJSON = this_value;
116089             Number.prototype.toJSON = this_value;
116090             String.prototype.toJSON = this_value;
116091           }
116092
116093           var gap;
116094           var indent;
116095           var meta;
116096           var rep;
116097
116098           function quote(string) {
116099             // If the string contains no control characters, no quote characters, and no
116100             // backslash characters, then we can safely slap some quotes around it.
116101             // Otherwise we must also replace the offending characters with safe escape
116102             // sequences.
116103             rx_escapable.lastIndex = 0;
116104             return rx_escapable.test(string) ? "\"" + string.replace(rx_escapable, function (a) {
116105               var c = meta[a];
116106               return typeof c === "string" ? c : "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
116107             }) + "\"" : "\"" + string + "\"";
116108           }
116109
116110           function str(key, holder) {
116111             // Produce a string from holder[key].
116112             var i; // The loop counter.
116113
116114             var k; // The member key.
116115
116116             var v; // The member value.
116117
116118             var length;
116119             var mind = gap;
116120             var partial;
116121             var value = holder[key]; // If the value has a toJSON method, call it to obtain a replacement value.
116122
116123             if (value && _typeof(value) === "object" && typeof value.toJSON === "function") {
116124               value = value.toJSON(key);
116125             } // If we were called with a replacer function, then call the replacer to
116126             // obtain a replacement value.
116127
116128
116129             if (typeof rep === "function") {
116130               value = rep.call(holder, key, value);
116131             } // What happens next depends on the value's type.
116132
116133
116134             switch (_typeof(value)) {
116135               case "string":
116136                 return quote(value);
116137
116138               case "number":
116139                 // JSON numbers must be finite. Encode non-finite numbers as null.
116140                 return isFinite(value) ? String(value) : "null";
116141
116142               case "boolean":
116143               case "null":
116144                 // If the value is a boolean or null, convert it to a string. Note:
116145                 // typeof null does not produce "null". The case is included here in
116146                 // the remote chance that this gets fixed someday.
116147                 return String(value);
116148               // If the type is "object", we might be dealing with an object or an array or
116149               // null.
116150
116151               case "object":
116152                 // Due to a specification blunder in ECMAScript, typeof null is "object",
116153                 // so watch out for that case.
116154                 if (!value) {
116155                   return "null";
116156                 } // Make an array to hold the partial results of stringifying this object value.
116157
116158
116159                 gap += indent;
116160                 partial = []; // Is the value an array?
116161
116162                 if (Object.prototype.toString.apply(value) === "[object Array]") {
116163                   // The value is an array. Stringify every element. Use null as a placeholder
116164                   // for non-JSON values.
116165                   length = value.length;
116166
116167                   for (i = 0; i < length; i += 1) {
116168                     partial[i] = str(i, value) || "null";
116169                   } // Join all of the elements together, separated with commas, and wrap them in
116170                   // brackets.
116171
116172
116173                   v = partial.length === 0 ? "[]" : gap ? "[\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "]" : "[" + partial.join(",") + "]";
116174                   gap = mind;
116175                   return v;
116176                 } // If the replacer is an array, use it to select the members to be stringified.
116177
116178
116179                 if (rep && _typeof(rep) === "object") {
116180                   length = rep.length;
116181
116182                   for (i = 0; i < length; i += 1) {
116183                     if (typeof rep[i] === "string") {
116184                       k = rep[i];
116185                       v = str(k, value);
116186
116187                       if (v) {
116188                         partial.push(quote(k) + (gap ? ": " : ":") + v);
116189                       }
116190                     }
116191                   }
116192                 } else {
116193                   // Otherwise, iterate through all of the keys in the object.
116194                   for (k in value) {
116195                     if (Object.prototype.hasOwnProperty.call(value, k)) {
116196                       v = str(k, value);
116197
116198                       if (v) {
116199                         partial.push(quote(k) + (gap ? ": " : ":") + v);
116200                       }
116201                     }
116202                   }
116203                 } // Join all of the member texts together, separated with commas,
116204                 // and wrap them in braces.
116205
116206
116207                 v = partial.length === 0 ? "{}" : gap ? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}" : "{" + partial.join(",") + "}";
116208                 gap = mind;
116209                 return v;
116210             }
116211           } // If the JSON object does not yet have a stringify method, give it one.
116212
116213
116214           if (typeof JSON.stringify !== "function") {
116215             meta = {
116216               // table of character substitutions
116217               "\b": "\\b",
116218               "\t": "\\t",
116219               "\n": "\\n",
116220               "\f": "\\f",
116221               "\r": "\\r",
116222               "\"": "\\\"",
116223               "\\": "\\\\"
116224             };
116225
116226             JSON.stringify = function (value, replacer, space) {
116227               // The stringify method takes a value and an optional replacer, and an optional
116228               // space parameter, and returns a JSON text. The replacer can be a function
116229               // that can replace values, or an array of strings that will select the keys.
116230               // A default replacer method can be provided. Use of the space parameter can
116231               // produce text that is more easily readable.
116232               var i;
116233               gap = "";
116234               indent = ""; // If the space parameter is a number, make an indent string containing that
116235               // many spaces.
116236
116237               if (typeof space === "number") {
116238                 for (i = 0; i < space; i += 1) {
116239                   indent += " ";
116240                 } // If the space parameter is a string, it will be used as the indent string.
116241
116242               } else if (typeof space === "string") {
116243                 indent = space;
116244               } // If there is a replacer, it must be a function or an array.
116245               // Otherwise, throw an error.
116246
116247
116248               rep = replacer;
116249
116250               if (replacer && typeof replacer !== "function" && (_typeof(replacer) !== "object" || typeof replacer.length !== "number")) {
116251                 throw new Error("JSON.stringify");
116252               } // Make a fake root object containing our value under the key of "".
116253               // Return the result of stringifying the value.
116254
116255
116256               return str("", {
116257                 "": value
116258               });
116259             };
116260           } // If the JSON object does not yet have a parse method, give it one.
116261
116262
116263           if (typeof JSON.parse !== "function") {
116264             JSON.parse = function (text, reviver) {
116265               // The parse method takes a text and an optional reviver function, and returns
116266               // a JavaScript value if the text is a valid JSON text.
116267               var j;
116268
116269               function walk(holder, key) {
116270                 // The walk method is used to recursively walk the resulting structure so
116271                 // that modifications can be made.
116272                 var k;
116273                 var v;
116274                 var value = holder[key];
116275
116276                 if (value && _typeof(value) === "object") {
116277                   for (k in value) {
116278                     if (Object.prototype.hasOwnProperty.call(value, k)) {
116279                       v = walk(value, k);
116280
116281                       if (v !== undefined) {
116282                         value[k] = v;
116283                       } else {
116284                         delete value[k];
116285                       }
116286                     }
116287                   }
116288                 }
116289
116290                 return reviver.call(holder, key, value);
116291               } // Parsing happens in four stages. In the first stage, we replace certain
116292               // Unicode characters with escape sequences. JavaScript handles many characters
116293               // incorrectly, either silently deleting them, or treating them as line endings.
116294
116295
116296               text = String(text);
116297               rx_dangerous.lastIndex = 0;
116298
116299               if (rx_dangerous.test(text)) {
116300                 text = text.replace(rx_dangerous, function (a) {
116301                   return "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
116302                 });
116303               } // In the second stage, we run the text against regular expressions that look
116304               // for non-JSON patterns. We are especially concerned with "()" and "new"
116305               // because they can cause invocation, and "=" because it can cause mutation.
116306               // But just to be safe, we want to reject all unexpected forms.
116307               // We split the second stage into 4 regexp operations in order to work around
116308               // crippling inefficiencies in IE's and Safari's regexp engines. First we
116309               // replace the JSON backslash pairs with "@" (a non-JSON character). Second, we
116310               // replace all simple value tokens with "]" characters. Third, we delete all
116311               // open brackets that follow a colon or comma or that begin the text. Finally,
116312               // we look to see that the remaining characters are only whitespace or "]" or
116313               // "," or ":" or "{" or "}". If that is so, then the text is safe for eval.
116314
116315
116316               if (rx_one.test(text.replace(rx_two, "@").replace(rx_three, "]").replace(rx_four, ""))) {
116317                 // In the third stage we use the eval function to compile the text into a
116318                 // JavaScript structure. The "{" operator is subject to a syntactic ambiguity
116319                 // in JavaScript: it can begin a block or an object literal. We wrap the text
116320                 // in parens to eliminate the ambiguity.
116321                 j = eval("(" + text + ")"); // In the optional fourth stage, we recursively walk the new structure, passing
116322                 // each name/value pair to a reviver function for possible transformation.
116323
116324                 return typeof reviver === "function" ? walk({
116325                   "": j
116326                 }, "") : j;
116327               } // If the text is not JSON parseable, then a SyntaxError is thrown.
116328
116329
116330               throw new SyntaxError("JSON.parse");
116331             };
116332           }
116333         })();
116334
116335         var json2 = json2Plugin;
116336
116337         function json2Plugin() {
116338           return {};
116339         }
116340
116341         var engine = storeEngine;
116342         var storages = all;
116343         var plugins = [json2];
116344         var store_legacy = engine.createStore(storages, plugins);
116345
116346         var immutable = extend;
116347         var hasOwnProperty = Object.prototype.hasOwnProperty;
116348
116349         function extend() {
116350           var target = {};
116351
116352           for (var i = 0; i < arguments.length; i++) {
116353             var source = arguments[i];
116354
116355             for (var key in source) {
116356               if (hasOwnProperty.call(source, key)) {
116357                 target[key] = source[key];
116358               }
116359             }
116360           }
116361
116362           return target;
116363         }
116364
116365         var ohauth = ohauth_1;
116366         var resolveUrl = resolveUrl$1.exports;
116367         var store = store_legacy;
116368         var xtend = immutable; // # osm-auth
116369         //
116370         // This code is only compatible with IE10+ because the [XDomainRequest](http://bit.ly/LfO7xo)
116371         // object, IE<10's idea of [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing),
116372         // does not support custom headers, which this uses everywhere.
116373
116374         var osmAuth = function osmAuth(o) {
116375           var oauth = {}; // authenticated users will also have a request token secret, but it's
116376           // not used in transactions with the server
116377
116378           oauth.authenticated = function () {
116379             return !!(token('oauth_token') && token('oauth_token_secret'));
116380           };
116381
116382           oauth.logout = function () {
116383             token('oauth_token', '');
116384             token('oauth_token_secret', '');
116385             token('oauth_request_token_secret', '');
116386             return oauth;
116387           }; // TODO: detect lack of click event
116388
116389
116390           oauth.authenticate = function (callback) {
116391             if (oauth.authenticated()) return callback();
116392             oauth.logout(); // ## Getting a request token
116393
116394             var params = timenonce(getAuth(o)),
116395                 url = o.url + '/oauth/request_token';
116396             params.oauth_signature = ohauth.signature(o.oauth_secret, '', ohauth.baseString('POST', url, params));
116397
116398             if (!o.singlepage) {
116399               // Create a 600x550 popup window in the center of the screen
116400               var w = 600,
116401                   h = 550,
116402                   settings = [['width', w], ['height', h], ['left', screen.width / 2 - w / 2], ['top', screen.height / 2 - h / 2]].map(function (x) {
116403                 return x.join('=');
116404               }).join(','),
116405                   popup = window.open('about:blank', 'oauth_window', settings);
116406               oauth.popupWindow = popup;
116407
116408               if (!popup) {
116409                 var error = new Error('Popup was blocked');
116410                 error.status = 'popup-blocked';
116411                 throw error;
116412               }
116413             } // Request a request token. When this is complete, the popup
116414             // window is redirected to OSM's authorization page.
116415
116416
116417             ohauth.xhr('POST', url, params, null, {}, reqTokenDone);
116418             o.loading();
116419
116420             function reqTokenDone(err, xhr) {
116421               o.done();
116422               if (err) return callback(err);
116423               var resp = ohauth.stringQs(xhr.response);
116424               token('oauth_request_token_secret', resp.oauth_token_secret);
116425               var authorize_url = o.url + '/oauth/authorize?' + ohauth.qsString({
116426                 oauth_token: resp.oauth_token,
116427                 oauth_callback: resolveUrl(o.landing)
116428               });
116429
116430               if (o.singlepage) {
116431                 location.href = authorize_url;
116432               } else {
116433                 popup.location = authorize_url;
116434               }
116435             } // Called by a function in a landing page, in the popup window. The
116436             // window closes itself.
116437
116438
116439             window.authComplete = function (token) {
116440               var oauth_token = ohauth.stringQs(token.split('?')[1]);
116441               get_access_token(oauth_token.oauth_token);
116442               delete window.authComplete;
116443             }; // ## Getting an request token
116444             //
116445             // At this point we have an `oauth_token`, brought in from a function
116446             // call on a landing page popup.
116447
116448
116449             function get_access_token(oauth_token) {
116450               var url = o.url + '/oauth/access_token',
116451                   params = timenonce(getAuth(o)),
116452                   request_token_secret = token('oauth_request_token_secret');
116453               params.oauth_token = oauth_token;
116454               params.oauth_signature = ohauth.signature(o.oauth_secret, request_token_secret, ohauth.baseString('POST', url, params)); // ## Getting an access token
116455               //
116456               // The final token required for authentication. At this point
116457               // we have a `request token secret`
116458
116459               ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
116460               o.loading();
116461             }
116462
116463             function accessTokenDone(err, xhr) {
116464               o.done();
116465               if (err) return callback(err);
116466               var access_token = ohauth.stringQs(xhr.response);
116467               token('oauth_token', access_token.oauth_token);
116468               token('oauth_token_secret', access_token.oauth_token_secret);
116469               callback(null, oauth);
116470             }
116471           };
116472
116473           oauth.bringPopupWindowToFront = function () {
116474             var brougtPopupToFront = false;
116475
116476             try {
116477               // This may cause a cross-origin error:
116478               // `DOMException: Blocked a frame with origin "..." from accessing a cross-origin frame.`
116479               if (oauth.popupWindow && !oauth.popupWindow.closed) {
116480                 oauth.popupWindow.focus();
116481                 brougtPopupToFront = true;
116482               }
116483             } catch (err) {// Bringing popup window to front failed (probably because of the cross-origin error mentioned above)
116484             }
116485
116486             return brougtPopupToFront;
116487           };
116488
116489           oauth.bootstrapToken = function (oauth_token, callback) {
116490             // ## Getting an request token
116491             // At this point we have an `oauth_token`, brought in from a function
116492             // call on a landing page popup.
116493             function get_access_token(oauth_token) {
116494               var url = o.url + '/oauth/access_token',
116495                   params = timenonce(getAuth(o)),
116496                   request_token_secret = token('oauth_request_token_secret');
116497               params.oauth_token = oauth_token;
116498               params.oauth_signature = ohauth.signature(o.oauth_secret, request_token_secret, ohauth.baseString('POST', url, params)); // ## Getting an access token
116499               // The final token required for authentication. At this point
116500               // we have a `request token secret`
116501
116502               ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
116503               o.loading();
116504             }
116505
116506             function accessTokenDone(err, xhr) {
116507               o.done();
116508               if (err) return callback(err);
116509               var access_token = ohauth.stringQs(xhr.response);
116510               token('oauth_token', access_token.oauth_token);
116511               token('oauth_token_secret', access_token.oauth_token_secret);
116512               callback(null, oauth);
116513             }
116514
116515             get_access_token(oauth_token);
116516           }; // # xhr
116517           //
116518           // A single XMLHttpRequest wrapper that does authenticated calls if the
116519           // user has logged in.
116520
116521
116522           oauth.xhr = function (options, callback) {
116523             if (!oauth.authenticated()) {
116524               if (o.auto) {
116525                 return oauth.authenticate(run);
116526               } else {
116527                 callback('not authenticated', null);
116528                 return;
116529               }
116530             } else {
116531               return run();
116532             }
116533
116534             function run() {
116535               var params = timenonce(getAuth(o)),
116536                   oauth_token_secret = token('oauth_token_secret'),
116537                   url = options.prefix !== false ? o.url + options.path : options.path,
116538                   url_parts = url.replace(/#.*$/, '').split('?', 2),
116539                   base_url = url_parts[0],
116540                   query = url_parts.length === 2 ? url_parts[1] : ''; // https://tools.ietf.org/html/rfc5849#section-3.4.1.3.1
116541
116542               if ((!options.options || !options.options.header || options.options.header['Content-Type'] === 'application/x-www-form-urlencoded') && options.content) {
116543                 params = xtend(params, ohauth.stringQs(options.content));
116544               }
116545
116546               params.oauth_token = token('oauth_token');
116547               params.oauth_signature = ohauth.signature(o.oauth_secret, oauth_token_secret, ohauth.baseString(options.method, base_url, xtend(params, ohauth.stringQs(query))));
116548               return ohauth.xhr(options.method, url, params, options.content, options.options, done);
116549             }
116550
116551             function done(err, xhr) {
116552               if (err) return callback(err);else if (xhr.responseXML) return callback(err, xhr.responseXML);else return callback(err, xhr.response);
116553             }
116554           }; // pre-authorize this object, if we can just get a token and token_secret
116555           // from the start
116556
116557
116558           oauth.preauth = function (c) {
116559             if (!c) return;
116560             if (c.oauth_token) token('oauth_token', c.oauth_token);
116561             if (c.oauth_token_secret) token('oauth_token_secret', c.oauth_token_secret);
116562             return oauth;
116563           };
116564
116565           oauth.options = function (_) {
116566             if (!arguments.length) return o;
116567             o = _;
116568             o.url = o.url || 'https://www.openstreetmap.org';
116569             o.landing = o.landing || 'land.html';
116570             o.singlepage = o.singlepage || false; // Optional loading and loading-done functions for nice UI feedback.
116571             // by default, no-ops
116572
116573             o.loading = o.loading || function () {};
116574
116575             o.done = o.done || function () {};
116576
116577             return oauth.preauth(o);
116578           }; // 'stamp' an authentication object from `getAuth()`
116579           // with a [nonce](http://en.wikipedia.org/wiki/Cryptographic_nonce)
116580           // and timestamp
116581
116582
116583           function timenonce(o) {
116584             o.oauth_timestamp = ohauth.timestamp();
116585             o.oauth_nonce = ohauth.nonce();
116586             return o;
116587           } // get/set tokens. These are prefixed with the base URL so that `osm-auth`
116588           // can be used with multiple APIs and the keys in `localStorage`
116589           // will not clash
116590
116591
116592           var token;
116593
116594           if (store.enabled) {
116595             token = function token(x, y) {
116596               if (arguments.length === 1) return store.get(o.url + x);else if (arguments.length === 2) return store.set(o.url + x, y);
116597             };
116598           } else {
116599             var storage = {};
116600
116601             token = function token(x, y) {
116602               if (arguments.length === 1) return storage[o.url + x];else if (arguments.length === 2) return storage[o.url + x] = y;
116603             };
116604           } // Get an authentication object. If you just add and remove properties
116605           // from a single object, you'll need to use `delete` to make sure that
116606           // it doesn't contain undesired properties for authentication
116607
116608
116609           function getAuth(o) {
116610             return {
116611               oauth_consumer_key: o.oauth_consumer_key,
116612               oauth_signature_method: 'HMAC-SHA1'
116613             };
116614           } // potentially pre-authorize
116615
116616
116617           oauth.options(o);
116618           return oauth;
116619         };
116620
116621         var tiler$2 = utilTiler();
116622         var dispatch$2 = dispatch$8('apiStatusChange', 'authLoading', 'authDone', 'change', 'loading', 'loaded', 'loadedNotes');
116623         var urlroot = 'https://www.openstreetmap.org';
116624         var oauth = osmAuth({
116625           url: urlroot,
116626           oauth_consumer_key: '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT',
116627           oauth_secret: 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL',
116628           loading: authLoading,
116629           done: authDone
116630         }); // hardcode default block of Google Maps
116631
116632         var _imageryBlocklists = [/.*\.google(apis)?\..*\/(vt|kh)[\?\/].*([xyz]=.*){3}.*/];
116633         var _tileCache = {
116634           toLoad: {},
116635           loaded: {},
116636           inflight: {},
116637           seen: {},
116638           rtree: new RBush()
116639         };
116640         var _noteCache = {
116641           toLoad: {},
116642           loaded: {},
116643           inflight: {},
116644           inflightPost: {},
116645           note: {},
116646           closed: {},
116647           rtree: new RBush()
116648         };
116649         var _userCache = {
116650           toLoad: {},
116651           user: {}
116652         };
116653
116654         var _cachedApiStatus;
116655
116656         var _changeset = {};
116657
116658         var _deferred = new Set();
116659
116660         var _connectionID = 1;
116661         var _tileZoom = 16;
116662         var _noteZoom = 12;
116663
116664         var _rateLimitError;
116665
116666         var _userChangesets;
116667
116668         var _userDetails;
116669
116670         var _off; // set a default but also load this from the API status
116671
116672
116673         var _maxWayNodes = 2000;
116674
116675         function authLoading() {
116676           dispatch$2.call('authLoading');
116677         }
116678
116679         function authDone() {
116680           dispatch$2.call('authDone');
116681         }
116682
116683         function abortRequest$2(controllerOrXHR) {
116684           if (controllerOrXHR) {
116685             controllerOrXHR.abort();
116686           }
116687         }
116688
116689         function hasInflightRequests(cache) {
116690           return Object.keys(cache.inflight).length;
116691         }
116692
116693         function abortUnwantedRequests(cache, visibleTiles) {
116694           Object.keys(cache.inflight).forEach(function (k) {
116695             if (cache.toLoad[k]) return;
116696             if (visibleTiles.find(function (tile) {
116697               return k === tile.id;
116698             })) return;
116699             abortRequest$2(cache.inflight[k]);
116700             delete cache.inflight[k];
116701           });
116702         }
116703
116704         function getLoc(attrs) {
116705           var lon = attrs.lon && attrs.lon.value;
116706           var lat = attrs.lat && attrs.lat.value;
116707           return [parseFloat(lon), parseFloat(lat)];
116708         }
116709
116710         function getNodes(obj) {
116711           var elems = obj.getElementsByTagName('nd');
116712           var nodes = new Array(elems.length);
116713
116714           for (var i = 0, l = elems.length; i < l; i++) {
116715             nodes[i] = 'n' + elems[i].attributes.ref.value;
116716           }
116717
116718           return nodes;
116719         }
116720
116721         function getNodesJSON(obj) {
116722           var elems = obj.nodes;
116723           var nodes = new Array(elems.length);
116724
116725           for (var i = 0, l = elems.length; i < l; i++) {
116726             nodes[i] = 'n' + elems[i];
116727           }
116728
116729           return nodes;
116730         }
116731
116732         function getTags(obj) {
116733           var elems = obj.getElementsByTagName('tag');
116734           var tags = {};
116735
116736           for (var i = 0, l = elems.length; i < l; i++) {
116737             var attrs = elems[i].attributes;
116738             tags[attrs.k.value] = attrs.v.value;
116739           }
116740
116741           return tags;
116742         }
116743
116744         function getMembers(obj) {
116745           var elems = obj.getElementsByTagName('member');
116746           var members = new Array(elems.length);
116747
116748           for (var i = 0, l = elems.length; i < l; i++) {
116749             var attrs = elems[i].attributes;
116750             members[i] = {
116751               id: attrs.type.value[0] + attrs.ref.value,
116752               type: attrs.type.value,
116753               role: attrs.role.value
116754             };
116755           }
116756
116757           return members;
116758         }
116759
116760         function getMembersJSON(obj) {
116761           var elems = obj.members;
116762           var members = new Array(elems.length);
116763
116764           for (var i = 0, l = elems.length; i < l; i++) {
116765             var attrs = elems[i];
116766             members[i] = {
116767               id: attrs.type[0] + attrs.ref,
116768               type: attrs.type,
116769               role: attrs.role
116770             };
116771           }
116772
116773           return members;
116774         }
116775
116776         function getVisible(attrs) {
116777           return !attrs.visible || attrs.visible.value !== 'false';
116778         }
116779
116780         function parseComments(comments) {
116781           var parsedComments = []; // for each comment
116782
116783           for (var i = 0; i < comments.length; i++) {
116784             var comment = comments[i];
116785
116786             if (comment.nodeName === 'comment') {
116787               var childNodes = comment.childNodes;
116788               var parsedComment = {};
116789
116790               for (var j = 0; j < childNodes.length; j++) {
116791                 var node = childNodes[j];
116792                 var nodeName = node.nodeName;
116793                 if (nodeName === '#text') continue;
116794                 parsedComment[nodeName] = node.textContent;
116795
116796                 if (nodeName === 'uid') {
116797                   var uid = node.textContent;
116798
116799                   if (uid && !_userCache.user[uid]) {
116800                     _userCache.toLoad[uid] = true;
116801                   }
116802                 }
116803               }
116804
116805               if (parsedComment) {
116806                 parsedComments.push(parsedComment);
116807               }
116808             }
116809           }
116810
116811           return parsedComments;
116812         }
116813
116814         function encodeNoteRtree(note) {
116815           return {
116816             minX: note.loc[0],
116817             minY: note.loc[1],
116818             maxX: note.loc[0],
116819             maxY: note.loc[1],
116820             data: note
116821           };
116822         }
116823
116824         var jsonparsers = {
116825           node: function nodeData(obj, uid) {
116826             return new osmNode({
116827               id: uid,
116828               visible: typeof obj.visible === 'boolean' ? obj.visible : true,
116829               version: obj.version && obj.version.toString(),
116830               changeset: obj.changeset && obj.changeset.toString(),
116831               timestamp: obj.timestamp,
116832               user: obj.user,
116833               uid: obj.uid && obj.uid.toString(),
116834               loc: [parseFloat(obj.lon), parseFloat(obj.lat)],
116835               tags: obj.tags
116836             });
116837           },
116838           way: function wayData(obj, uid) {
116839             return new osmWay({
116840               id: uid,
116841               visible: typeof obj.visible === 'boolean' ? obj.visible : true,
116842               version: obj.version && obj.version.toString(),
116843               changeset: obj.changeset && obj.changeset.toString(),
116844               timestamp: obj.timestamp,
116845               user: obj.user,
116846               uid: obj.uid && obj.uid.toString(),
116847               tags: obj.tags,
116848               nodes: getNodesJSON(obj)
116849             });
116850           },
116851           relation: function relationData(obj, uid) {
116852             return new osmRelation({
116853               id: uid,
116854               visible: typeof obj.visible === 'boolean' ? obj.visible : true,
116855               version: obj.version && obj.version.toString(),
116856               changeset: obj.changeset && obj.changeset.toString(),
116857               timestamp: obj.timestamp,
116858               user: obj.user,
116859               uid: obj.uid && obj.uid.toString(),
116860               tags: obj.tags,
116861               members: getMembersJSON(obj)
116862             });
116863           },
116864           user: function parseUser(obj, uid) {
116865             return {
116866               id: uid,
116867               display_name: obj.display_name,
116868               account_created: obj.account_created,
116869               image_url: obj.img && obj.img.href,
116870               changesets_count: obj.changesets && obj.changesets.count && obj.changesets.count.toString() || '0',
116871               active_blocks: obj.blocks && obj.blocks.received && obj.blocks.received.active && obj.blocks.received.active.toString() || '0'
116872             };
116873           }
116874         };
116875
116876         function parseJSON(payload, callback, options) {
116877           options = Object.assign({
116878             skipSeen: true
116879           }, options);
116880
116881           if (!payload) {
116882             return callback({
116883               message: 'No JSON',
116884               status: -1
116885             });
116886           }
116887
116888           var json = payload;
116889           if (_typeof(json) !== 'object') json = JSON.parse(payload);
116890           if (!json.elements) return callback({
116891             message: 'No JSON',
116892             status: -1
116893           });
116894           var children = json.elements;
116895           var handle = window.requestIdleCallback(function () {
116896             _deferred["delete"](handle);
116897
116898             var results = [];
116899             var result;
116900
116901             for (var i = 0; i < children.length; i++) {
116902               result = parseChild(children[i]);
116903               if (result) results.push(result);
116904             }
116905
116906             callback(null, results);
116907           });
116908
116909           _deferred.add(handle);
116910
116911           function parseChild(child) {
116912             var parser = jsonparsers[child.type];
116913             if (!parser) return null;
116914             var uid;
116915             uid = osmEntity.id.fromOSM(child.type, child.id);
116916
116917             if (options.skipSeen) {
116918               if (_tileCache.seen[uid]) return null; // avoid reparsing a "seen" entity
116919
116920               _tileCache.seen[uid] = true;
116921             }
116922
116923             return parser(child, uid);
116924           }
116925         }
116926
116927         function parseUserJSON(payload, callback, options) {
116928           options = Object.assign({
116929             skipSeen: true
116930           }, options);
116931
116932           if (!payload) {
116933             return callback({
116934               message: 'No JSON',
116935               status: -1
116936             });
116937           }
116938
116939           var json = payload;
116940           if (_typeof(json) !== 'object') json = JSON.parse(payload);
116941           if (!json.users && !json.user) return callback({
116942             message: 'No JSON',
116943             status: -1
116944           });
116945           var objs = json.users || [json];
116946           var handle = window.requestIdleCallback(function () {
116947             _deferred["delete"](handle);
116948
116949             var results = [];
116950             var result;
116951
116952             for (var i = 0; i < objs.length; i++) {
116953               result = parseObj(objs[i]);
116954               if (result) results.push(result);
116955             }
116956
116957             callback(null, results);
116958           });
116959
116960           _deferred.add(handle);
116961
116962           function parseObj(obj) {
116963             var uid = obj.user.id && obj.user.id.toString();
116964
116965             if (options.skipSeen && _userCache.user[uid]) {
116966               delete _userCache.toLoad[uid];
116967               return null;
116968             }
116969
116970             var user = jsonparsers.user(obj.user, uid);
116971             _userCache.user[uid] = user;
116972             delete _userCache.toLoad[uid];
116973             return user;
116974           }
116975         }
116976
116977         var parsers = {
116978           node: function nodeData(obj, uid) {
116979             var attrs = obj.attributes;
116980             return new osmNode({
116981               id: uid,
116982               visible: getVisible(attrs),
116983               version: attrs.version.value,
116984               changeset: attrs.changeset && attrs.changeset.value,
116985               timestamp: attrs.timestamp && attrs.timestamp.value,
116986               user: attrs.user && attrs.user.value,
116987               uid: attrs.uid && attrs.uid.value,
116988               loc: getLoc(attrs),
116989               tags: getTags(obj)
116990             });
116991           },
116992           way: function wayData(obj, uid) {
116993             var attrs = obj.attributes;
116994             return new osmWay({
116995               id: uid,
116996               visible: getVisible(attrs),
116997               version: attrs.version.value,
116998               changeset: attrs.changeset && attrs.changeset.value,
116999               timestamp: attrs.timestamp && attrs.timestamp.value,
117000               user: attrs.user && attrs.user.value,
117001               uid: attrs.uid && attrs.uid.value,
117002               tags: getTags(obj),
117003               nodes: getNodes(obj)
117004             });
117005           },
117006           relation: function relationData(obj, uid) {
117007             var attrs = obj.attributes;
117008             return new osmRelation({
117009               id: uid,
117010               visible: getVisible(attrs),
117011               version: attrs.version.value,
117012               changeset: attrs.changeset && attrs.changeset.value,
117013               timestamp: attrs.timestamp && attrs.timestamp.value,
117014               user: attrs.user && attrs.user.value,
117015               uid: attrs.uid && attrs.uid.value,
117016               tags: getTags(obj),
117017               members: getMembers(obj)
117018             });
117019           },
117020           note: function parseNote(obj, uid) {
117021             var attrs = obj.attributes;
117022             var childNodes = obj.childNodes;
117023             var props = {};
117024             props.id = uid;
117025             props.loc = getLoc(attrs); // if notes are coincident, move them apart slightly
117026
117027             var coincident = false;
117028             var epsilon = 0.00001;
117029
117030             do {
117031               if (coincident) {
117032                 props.loc = geoVecAdd(props.loc, [epsilon, epsilon]);
117033               }
117034
117035               var bbox = geoExtent(props.loc).bbox();
117036               coincident = _noteCache.rtree.search(bbox).length;
117037             } while (coincident); // parse note contents
117038
117039
117040             for (var i = 0; i < childNodes.length; i++) {
117041               var node = childNodes[i];
117042               var nodeName = node.nodeName;
117043               if (nodeName === '#text') continue; // if the element is comments, parse the comments
117044
117045               if (nodeName === 'comments') {
117046                 props[nodeName] = parseComments(node.childNodes);
117047               } else {
117048                 props[nodeName] = node.textContent;
117049               }
117050             }
117051
117052             var note = new osmNote(props);
117053             var item = encodeNoteRtree(note);
117054             _noteCache.note[note.id] = note;
117055
117056             _noteCache.rtree.insert(item);
117057
117058             return note;
117059           },
117060           user: function parseUser(obj, uid) {
117061             var attrs = obj.attributes;
117062             var user = {
117063               id: uid,
117064               display_name: attrs.display_name && attrs.display_name.value,
117065               account_created: attrs.account_created && attrs.account_created.value,
117066               changesets_count: '0',
117067               active_blocks: '0'
117068             };
117069             var img = obj.getElementsByTagName('img');
117070
117071             if (img && img[0] && img[0].getAttribute('href')) {
117072               user.image_url = img[0].getAttribute('href');
117073             }
117074
117075             var changesets = obj.getElementsByTagName('changesets');
117076
117077             if (changesets && changesets[0] && changesets[0].getAttribute('count')) {
117078               user.changesets_count = changesets[0].getAttribute('count');
117079             }
117080
117081             var blocks = obj.getElementsByTagName('blocks');
117082
117083             if (blocks && blocks[0]) {
117084               var received = blocks[0].getElementsByTagName('received');
117085
117086               if (received && received[0] && received[0].getAttribute('active')) {
117087                 user.active_blocks = received[0].getAttribute('active');
117088               }
117089             }
117090
117091             _userCache.user[uid] = user;
117092             delete _userCache.toLoad[uid];
117093             return user;
117094           }
117095         };
117096
117097         function parseXML(xml, callback, options) {
117098           options = Object.assign({
117099             skipSeen: true
117100           }, options);
117101
117102           if (!xml || !xml.childNodes) {
117103             return callback({
117104               message: 'No XML',
117105               status: -1
117106             });
117107           }
117108
117109           var root = xml.childNodes[0];
117110           var children = root.childNodes;
117111           var handle = window.requestIdleCallback(function () {
117112             _deferred["delete"](handle);
117113
117114             var results = [];
117115             var result;
117116
117117             for (var i = 0; i < children.length; i++) {
117118               result = parseChild(children[i]);
117119               if (result) results.push(result);
117120             }
117121
117122             callback(null, results);
117123           });
117124
117125           _deferred.add(handle);
117126
117127           function parseChild(child) {
117128             var parser = parsers[child.nodeName];
117129             if (!parser) return null;
117130             var uid;
117131
117132             if (child.nodeName === 'user') {
117133               uid = child.attributes.id.value;
117134
117135               if (options.skipSeen && _userCache.user[uid]) {
117136                 delete _userCache.toLoad[uid];
117137                 return null;
117138               }
117139             } else if (child.nodeName === 'note') {
117140               uid = child.getElementsByTagName('id')[0].textContent;
117141             } else {
117142               uid = osmEntity.id.fromOSM(child.nodeName, child.attributes.id.value);
117143
117144               if (options.skipSeen) {
117145                 if (_tileCache.seen[uid]) return null; // avoid reparsing a "seen" entity
117146
117147                 _tileCache.seen[uid] = true;
117148               }
117149             }
117150
117151             return parser(child, uid);
117152           }
117153         } // replace or remove note from rtree
117154
117155
117156         function updateRtree(item, replace) {
117157           _noteCache.rtree.remove(item, function isEql(a, b) {
117158             return a.data.id === b.data.id;
117159           });
117160
117161           if (replace) {
117162             _noteCache.rtree.insert(item);
117163           }
117164         }
117165
117166         function wrapcb(thisArg, callback, cid) {
117167           return function (err, result) {
117168             if (err) {
117169               // 400 Bad Request, 401 Unauthorized, 403 Forbidden..
117170               if (err.status === 400 || err.status === 401 || err.status === 403) {
117171                 thisArg.logout();
117172               }
117173
117174               return callback.call(thisArg, err);
117175             } else if (thisArg.getConnectionId() !== cid) {
117176               return callback.call(thisArg, {
117177                 message: 'Connection Switched',
117178                 status: -1
117179               });
117180             } else {
117181               return callback.call(thisArg, err, result);
117182             }
117183           };
117184         }
117185
117186         var serviceOsm = {
117187           init: function init() {
117188             utilRebind(this, dispatch$2, 'on');
117189           },
117190           reset: function reset() {
117191             Array.from(_deferred).forEach(function (handle) {
117192               window.cancelIdleCallback(handle);
117193
117194               _deferred["delete"](handle);
117195             });
117196             _connectionID++;
117197             _userChangesets = undefined;
117198             _userDetails = undefined;
117199             _rateLimitError = undefined;
117200             Object.values(_tileCache.inflight).forEach(abortRequest$2);
117201             Object.values(_noteCache.inflight).forEach(abortRequest$2);
117202             Object.values(_noteCache.inflightPost).forEach(abortRequest$2);
117203             if (_changeset.inflight) abortRequest$2(_changeset.inflight);
117204             _tileCache = {
117205               toLoad: {},
117206               loaded: {},
117207               inflight: {},
117208               seen: {},
117209               rtree: new RBush()
117210             };
117211             _noteCache = {
117212               toLoad: {},
117213               loaded: {},
117214               inflight: {},
117215               inflightPost: {},
117216               note: {},
117217               closed: {},
117218               rtree: new RBush()
117219             };
117220             _userCache = {
117221               toLoad: {},
117222               user: {}
117223             };
117224             _cachedApiStatus = undefined;
117225             _changeset = {};
117226             return this;
117227           },
117228           getConnectionId: function getConnectionId() {
117229             return _connectionID;
117230           },
117231           changesetURL: function changesetURL(changesetID) {
117232             return urlroot + '/changeset/' + changesetID;
117233           },
117234           changesetsURL: function changesetsURL(center, zoom) {
117235             var precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));
117236             return urlroot + '/history#map=' + Math.floor(zoom) + '/' + center[1].toFixed(precision) + '/' + center[0].toFixed(precision);
117237           },
117238           entityURL: function entityURL(entity) {
117239             return urlroot + '/' + entity.type + '/' + entity.osmId();
117240           },
117241           historyURL: function historyURL(entity) {
117242             return urlroot + '/' + entity.type + '/' + entity.osmId() + '/history';
117243           },
117244           userURL: function userURL(username) {
117245             return urlroot + '/user/' + encodeURIComponent(username);
117246           },
117247           noteURL: function noteURL(note) {
117248             return urlroot + '/note/' + note.id;
117249           },
117250           noteReportURL: function noteReportURL(note) {
117251             return urlroot + '/reports/new?reportable_type=Note&reportable_id=' + note.id;
117252           },
117253           // Generic method to load data from the OSM API
117254           // Can handle either auth or unauth calls.
117255           loadFromAPI: function loadFromAPI(path, callback, options) {
117256             options = Object.assign({
117257               skipSeen: true
117258             }, options);
117259             var that = this;
117260             var cid = _connectionID;
117261
117262             function done(err, payload) {
117263               if (that.getConnectionId() !== cid) {
117264                 if (callback) callback({
117265                   message: 'Connection Switched',
117266                   status: -1
117267                 });
117268                 return;
117269               }
117270
117271               var isAuthenticated = that.authenticated(); // 400 Bad Request, 401 Unauthorized, 403 Forbidden
117272               // Logout and retry the request..
117273
117274               if (isAuthenticated && err && err.status && (err.status === 400 || err.status === 401 || err.status === 403)) {
117275                 that.logout();
117276                 that.loadFromAPI(path, callback, options); // else, no retry..
117277               } else {
117278                 // 509 Bandwidth Limit Exceeded, 429 Too Many Requests
117279                 // Set the rateLimitError flag and trigger a warning..
117280                 if (!isAuthenticated && !_rateLimitError && err && err.status && (err.status === 509 || err.status === 429)) {
117281                   _rateLimitError = err;
117282                   dispatch$2.call('change');
117283                   that.reloadApiStatus();
117284                 } else if (err && _cachedApiStatus === 'online' || !err && _cachedApiStatus !== 'online') {
117285                   // If the response's error state doesn't match the status,
117286                   // it's likely we lost or gained the connection so reload the status
117287                   that.reloadApiStatus();
117288                 }
117289
117290                 if (callback) {
117291                   if (err) {
117292                     return callback(err);
117293                   } else {
117294                     if (path.indexOf('.json') !== -1) {
117295                       return parseJSON(payload, callback, options);
117296                     } else {
117297                       return parseXML(payload, callback, options);
117298                     }
117299                   }
117300                 }
117301               }
117302             }
117303
117304             if (this.authenticated()) {
117305               return oauth.xhr({
117306                 method: 'GET',
117307                 path: path
117308               }, done);
117309             } else {
117310               var url = urlroot + path;
117311               var controller = new AbortController();
117312               var fn;
117313
117314               if (path.indexOf('.json') !== -1) {
117315                 fn = d3_json;
117316               } else {
117317                 fn = d3_xml;
117318               }
117319
117320               fn(url, {
117321                 signal: controller.signal
117322               }).then(function (data) {
117323                 done(null, data);
117324               })["catch"](function (err) {
117325                 if (err.name === 'AbortError') return; // d3-fetch includes status in the error message,
117326                 // but we can't access the response itself
117327                 // https://github.com/d3/d3-fetch/issues/27
117328
117329                 var match = err.message.match(/^\d{3}/);
117330
117331                 if (match) {
117332                   done({
117333                     status: +match[0],
117334                     statusText: err.message
117335                   });
117336                 } else {
117337                   done(err.message);
117338                 }
117339               });
117340               return controller;
117341             }
117342           },
117343           // Load a single entity by id (ways and relations use the `/full` call to include
117344           // nodes and members). Parent relations are not included, see `loadEntityRelations`.
117345           // GET /api/0.6/node/#id
117346           // GET /api/0.6/[way|relation]/#id/full
117347           loadEntity: function loadEntity(id, callback) {
117348             var type = osmEntity.id.type(id);
117349             var osmID = osmEntity.id.toOSM(id);
117350             var options = {
117351               skipSeen: false
117352             };
117353             this.loadFromAPI('/api/0.6/' + type + '/' + osmID + (type !== 'node' ? '/full' : '') + '.json', function (err, entities) {
117354               if (callback) callback(err, {
117355                 data: entities
117356               });
117357             }, options);
117358           },
117359           // Load a single entity with a specific version
117360           // GET /api/0.6/[node|way|relation]/#id/#version
117361           loadEntityVersion: function loadEntityVersion(id, version, callback) {
117362             var type = osmEntity.id.type(id);
117363             var osmID = osmEntity.id.toOSM(id);
117364             var options = {
117365               skipSeen: false
117366             };
117367             this.loadFromAPI('/api/0.6/' + type + '/' + osmID + '/' + version + '.json', function (err, entities) {
117368               if (callback) callback(err, {
117369                 data: entities
117370               });
117371             }, options);
117372           },
117373           // Load the relations of a single entity with the given.
117374           // GET /api/0.6/[node|way|relation]/#id/relations
117375           loadEntityRelations: function loadEntityRelations(id, callback) {
117376             var type = osmEntity.id.type(id);
117377             var osmID = osmEntity.id.toOSM(id);
117378             var options = {
117379               skipSeen: false
117380             };
117381             this.loadFromAPI('/api/0.6/' + type + '/' + osmID + '/relations.json', function (err, entities) {
117382               if (callback) callback(err, {
117383                 data: entities
117384               });
117385             }, options);
117386           },
117387           // Load multiple entities in chunks
117388           // (note: callback may be called multiple times)
117389           // Unlike `loadEntity`, child nodes and members are not fetched
117390           // GET /api/0.6/[nodes|ways|relations]?#parameters
117391           loadMultiple: function loadMultiple(ids, callback) {
117392             var that = this;
117393             var groups = utilArrayGroupBy(utilArrayUniq(ids), osmEntity.id.type);
117394             Object.keys(groups).forEach(function (k) {
117395               var type = k + 's'; // nodes, ways, relations
117396
117397               var osmIDs = groups[k].map(function (id) {
117398                 return osmEntity.id.toOSM(id);
117399               });
117400               var options = {
117401                 skipSeen: false
117402               };
117403               utilArrayChunk(osmIDs, 150).forEach(function (arr) {
117404                 that.loadFromAPI('/api/0.6/' + type + '.json?' + type + '=' + arr.join(), function (err, entities) {
117405                   if (callback) callback(err, {
117406                     data: entities
117407                   });
117408                 }, options);
117409               });
117410             });
117411           },
117412           // Create, upload, and close a changeset
117413           // PUT /api/0.6/changeset/create
117414           // POST /api/0.6/changeset/#id/upload
117415           // PUT /api/0.6/changeset/#id/close
117416           putChangeset: function putChangeset(changeset, changes, callback) {
117417             var cid = _connectionID;
117418
117419             if (_changeset.inflight) {
117420               return callback({
117421                 message: 'Changeset already inflight',
117422                 status: -2
117423               }, changeset);
117424             } else if (_changeset.open) {
117425               // reuse existing open changeset..
117426               return createdChangeset.call(this, null, _changeset.open);
117427             } else {
117428               // Open a new changeset..
117429               var options = {
117430                 method: 'PUT',
117431                 path: '/api/0.6/changeset/create',
117432                 options: {
117433                   header: {
117434                     'Content-Type': 'text/xml'
117435                   }
117436                 },
117437                 content: JXON.stringify(changeset.asJXON())
117438               };
117439               _changeset.inflight = oauth.xhr(options, wrapcb(this, createdChangeset, cid));
117440             }
117441
117442             function createdChangeset(err, changesetID) {
117443               _changeset.inflight = null;
117444
117445               if (err) {
117446                 return callback(err, changeset);
117447               }
117448
117449               _changeset.open = changesetID;
117450               changeset = changeset.update({
117451                 id: changesetID
117452               }); // Upload the changeset..
117453
117454               var options = {
117455                 method: 'POST',
117456                 path: '/api/0.6/changeset/' + changesetID + '/upload',
117457                 options: {
117458                   header: {
117459                     'Content-Type': 'text/xml'
117460                   }
117461                 },
117462                 content: JXON.stringify(changeset.osmChangeJXON(changes))
117463               };
117464               _changeset.inflight = oauth.xhr(options, wrapcb(this, uploadedChangeset, cid));
117465             }
117466
117467             function uploadedChangeset(err) {
117468               _changeset.inflight = null;
117469               if (err) return callback(err, changeset); // Upload was successful, safe to call the callback.
117470               // Add delay to allow for postgres replication #1646 #2678
117471
117472               window.setTimeout(function () {
117473                 callback(null, changeset);
117474               }, 2500);
117475               _changeset.open = null; // At this point, we don't really care if the connection was switched..
117476               // Only try to close the changeset if we're still talking to the same server.
117477
117478               if (this.getConnectionId() === cid) {
117479                 // Still attempt to close changeset, but ignore response because #2667
117480                 oauth.xhr({
117481                   method: 'PUT',
117482                   path: '/api/0.6/changeset/' + changeset.id + '/close',
117483                   options: {
117484                     header: {
117485                       'Content-Type': 'text/xml'
117486                     }
117487                   }
117488                 }, function () {
117489                   return true;
117490                 });
117491               }
117492             }
117493           },
117494           // Load multiple users in chunks
117495           // (note: callback may be called multiple times)
117496           // GET /api/0.6/users?users=#id1,#id2,...,#idn
117497           loadUsers: function loadUsers(uids, callback) {
117498             var toLoad = [];
117499             var cached = [];
117500             utilArrayUniq(uids).forEach(function (uid) {
117501               if (_userCache.user[uid]) {
117502                 delete _userCache.toLoad[uid];
117503                 cached.push(_userCache.user[uid]);
117504               } else {
117505                 toLoad.push(uid);
117506               }
117507             });
117508
117509             if (cached.length || !this.authenticated()) {
117510               callback(undefined, cached);
117511               if (!this.authenticated()) return; // require auth
117512             }
117513
117514             utilArrayChunk(toLoad, 150).forEach(function (arr) {
117515               oauth.xhr({
117516                 method: 'GET',
117517                 path: '/api/0.6/users.json?users=' + arr.join()
117518               }, wrapcb(this, done, _connectionID));
117519             }.bind(this));
117520
117521             function done(err, payload) {
117522               if (err) return callback(err);
117523               var options = {
117524                 skipSeen: true
117525               };
117526               return parseUserJSON(payload, function (err, results) {
117527                 if (err) return callback(err);
117528                 return callback(undefined, results);
117529               }, options);
117530             }
117531           },
117532           // Load a given user by id
117533           // GET /api/0.6/user/#id
117534           loadUser: function loadUser(uid, callback) {
117535             if (_userCache.user[uid] || !this.authenticated()) {
117536               // require auth
117537               delete _userCache.toLoad[uid];
117538               return callback(undefined, _userCache.user[uid]);
117539             }
117540
117541             oauth.xhr({
117542               method: 'GET',
117543               path: '/api/0.6/user/' + uid + '.json'
117544             }, wrapcb(this, done, _connectionID));
117545
117546             function done(err, payload) {
117547               if (err) return callback(err);
117548               var options = {
117549                 skipSeen: true
117550               };
117551               return parseUserJSON(payload, function (err, results) {
117552                 if (err) return callback(err);
117553                 return callback(undefined, results[0]);
117554               }, options);
117555             }
117556           },
117557           // Load the details of the logged-in user
117558           // GET /api/0.6/user/details
117559           userDetails: function userDetails(callback) {
117560             if (_userDetails) {
117561               // retrieve cached
117562               return callback(undefined, _userDetails);
117563             }
117564
117565             oauth.xhr({
117566               method: 'GET',
117567               path: '/api/0.6/user/details.json'
117568             }, wrapcb(this, done, _connectionID));
117569
117570             function done(err, payload) {
117571               if (err) return callback(err);
117572               var options = {
117573                 skipSeen: false
117574               };
117575               return parseUserJSON(payload, function (err, results) {
117576                 if (err) return callback(err);
117577                 _userDetails = results[0];
117578                 return callback(undefined, _userDetails);
117579               }, options);
117580             }
117581           },
117582           // Load previous changesets for the logged in user
117583           // GET /api/0.6/changesets?user=#id
117584           userChangesets: function userChangesets(callback) {
117585             if (_userChangesets) {
117586               // retrieve cached
117587               return callback(undefined, _userChangesets);
117588             }
117589
117590             this.userDetails(wrapcb(this, gotDetails, _connectionID));
117591
117592             function gotDetails(err, user) {
117593               if (err) {
117594                 return callback(err);
117595               }
117596
117597               oauth.xhr({
117598                 method: 'GET',
117599                 path: '/api/0.6/changesets?user=' + user.id
117600               }, wrapcb(this, done, _connectionID));
117601             }
117602
117603             function done(err, xml) {
117604               if (err) {
117605                 return callback(err);
117606               }
117607
117608               _userChangesets = Array.prototype.map.call(xml.getElementsByTagName('changeset'), function (changeset) {
117609                 return {
117610                   tags: getTags(changeset)
117611                 };
117612               }).filter(function (changeset) {
117613                 var comment = changeset.tags.comment;
117614                 return comment && comment !== '';
117615               });
117616               return callback(undefined, _userChangesets);
117617             }
117618           },
117619           // Fetch the status of the OSM API
117620           // GET /api/capabilities
117621           status: function status(callback) {
117622             var url = urlroot + '/api/capabilities';
117623             var errback = wrapcb(this, done, _connectionID);
117624             d3_xml(url).then(function (data) {
117625               errback(null, data);
117626             })["catch"](function (err) {
117627               errback(err.message);
117628             });
117629
117630             function done(err, xml) {
117631               if (err) {
117632                 // the status is null if no response could be retrieved
117633                 return callback(err, null);
117634               } // update blocklists
117635
117636
117637               var elements = xml.getElementsByTagName('blacklist');
117638               var regexes = [];
117639
117640               for (var i = 0; i < elements.length; i++) {
117641                 var regexString = elements[i].getAttribute('regex'); // needs unencode?
117642
117643                 if (regexString) {
117644                   try {
117645                     var regex = new RegExp(regexString);
117646                     regexes.push(regex);
117647                   } catch (e) {
117648                     /* noop */
117649                   }
117650                 }
117651               }
117652
117653               if (regexes.length) {
117654                 _imageryBlocklists = regexes;
117655               }
117656
117657               if (_rateLimitError) {
117658                 return callback(_rateLimitError, 'rateLimited');
117659               } else {
117660                 var waynodes = xml.getElementsByTagName('waynodes');
117661                 var maxWayNodes = waynodes.length && parseInt(waynodes[0].getAttribute('maximum'), 10);
117662                 if (maxWayNodes && isFinite(maxWayNodes)) _maxWayNodes = maxWayNodes;
117663                 var apiStatus = xml.getElementsByTagName('status');
117664                 var val = apiStatus[0].getAttribute('api');
117665                 return callback(undefined, val);
117666               }
117667             }
117668           },
117669           // Calls `status` and dispatches an `apiStatusChange` event if the returned
117670           // status differs from the cached status.
117671           reloadApiStatus: function reloadApiStatus() {
117672             // throttle to avoid unnecessary API calls
117673             if (!this.throttledReloadApiStatus) {
117674               var that = this;
117675               this.throttledReloadApiStatus = throttle(function () {
117676                 that.status(function (err, status) {
117677                   if (status !== _cachedApiStatus) {
117678                     _cachedApiStatus = status;
117679                     dispatch$2.call('apiStatusChange', that, err, status);
117680                   }
117681                 });
117682               }, 500);
117683             }
117684
117685             this.throttledReloadApiStatus();
117686           },
117687           // Returns the maximum number of nodes a single way can have
117688           maxWayNodes: function maxWayNodes() {
117689             return _maxWayNodes;
117690           },
117691           // Load data (entities) from the API in tiles
117692           // GET /api/0.6/map?bbox=
117693           loadTiles: function loadTiles(projection, callback) {
117694             if (_off) return; // determine the needed tiles to cover the view
117695
117696             var tiles = tiler$2.zoomExtent([_tileZoom, _tileZoom]).getTiles(projection); // abort inflight requests that are no longer needed
117697
117698             var hadRequests = hasInflightRequests(_tileCache);
117699             abortUnwantedRequests(_tileCache, tiles);
117700
117701             if (hadRequests && !hasInflightRequests(_tileCache)) {
117702               dispatch$2.call('loaded'); // stop the spinner
117703             } // issue new requests..
117704
117705
117706             tiles.forEach(function (tile) {
117707               this.loadTile(tile, callback);
117708             }, this);
117709           },
117710           // Load a single data tile
117711           // GET /api/0.6/map?bbox=
117712           loadTile: function loadTile(tile, callback) {
117713             if (_off) return;
117714             if (_tileCache.loaded[tile.id] || _tileCache.inflight[tile.id]) return;
117715
117716             if (!hasInflightRequests(_tileCache)) {
117717               dispatch$2.call('loading'); // start the spinner
117718             }
117719
117720             var path = '/api/0.6/map.json?bbox=';
117721             var options = {
117722               skipSeen: true
117723             };
117724             _tileCache.inflight[tile.id] = this.loadFromAPI(path + tile.extent.toParam(), tileCallback, options);
117725
117726             function tileCallback(err, parsed) {
117727               delete _tileCache.inflight[tile.id];
117728
117729               if (!err) {
117730                 delete _tileCache.toLoad[tile.id];
117731                 _tileCache.loaded[tile.id] = true;
117732                 var bbox = tile.extent.bbox();
117733                 bbox.id = tile.id;
117734
117735                 _tileCache.rtree.insert(bbox);
117736               }
117737
117738               if (callback) {
117739                 callback(err, Object.assign({
117740                   data: parsed
117741                 }, tile));
117742               }
117743
117744               if (!hasInflightRequests(_tileCache)) {
117745                 dispatch$2.call('loaded'); // stop the spinner
117746               }
117747             }
117748           },
117749           isDataLoaded: function isDataLoaded(loc) {
117750             var bbox = {
117751               minX: loc[0],
117752               minY: loc[1],
117753               maxX: loc[0],
117754               maxY: loc[1]
117755             };
117756             return _tileCache.rtree.collides(bbox);
117757           },
117758           // load the tile that covers the given `loc`
117759           loadTileAtLoc: function loadTileAtLoc(loc, callback) {
117760             // Back off if the toLoad queue is filling up.. re #6417
117761             // (Currently `loadTileAtLoc` requests are considered low priority - used by operations to
117762             // let users safely edit geometries which extend to unloaded tiles.  We can drop some.)
117763             if (Object.keys(_tileCache.toLoad).length > 50) return;
117764             var k = geoZoomToScale(_tileZoom + 1);
117765             var offset = geoRawMercator().scale(k)(loc);
117766             var projection = geoRawMercator().transform({
117767               k: k,
117768               x: -offset[0],
117769               y: -offset[1]
117770             });
117771             var tiles = tiler$2.zoomExtent([_tileZoom, _tileZoom]).getTiles(projection);
117772             tiles.forEach(function (tile) {
117773               if (_tileCache.toLoad[tile.id] || _tileCache.loaded[tile.id] || _tileCache.inflight[tile.id]) return;
117774               _tileCache.toLoad[tile.id] = true;
117775               this.loadTile(tile, callback);
117776             }, this);
117777           },
117778           // Load notes from the API in tiles
117779           // GET /api/0.6/notes?bbox=
117780           loadNotes: function loadNotes(projection, noteOptions) {
117781             noteOptions = Object.assign({
117782               limit: 10000,
117783               closed: 7
117784             }, noteOptions);
117785             if (_off) return;
117786             var that = this;
117787             var path = '/api/0.6/notes?limit=' + noteOptions.limit + '&closed=' + noteOptions.closed + '&bbox=';
117788
117789             var throttleLoadUsers = throttle(function () {
117790               var uids = Object.keys(_userCache.toLoad);
117791               if (!uids.length) return;
117792               that.loadUsers(uids, function () {}); // eagerly load user details
117793             }, 750); // determine the needed tiles to cover the view
117794
117795
117796             var tiles = tiler$2.zoomExtent([_noteZoom, _noteZoom]).getTiles(projection); // abort inflight requests that are no longer needed
117797
117798             abortUnwantedRequests(_noteCache, tiles); // issue new requests..
117799
117800             tiles.forEach(function (tile) {
117801               if (_noteCache.loaded[tile.id] || _noteCache.inflight[tile.id]) return;
117802               var options = {
117803                 skipSeen: false
117804               };
117805               _noteCache.inflight[tile.id] = that.loadFromAPI(path + tile.extent.toParam(), function (err) {
117806                 delete _noteCache.inflight[tile.id];
117807
117808                 if (!err) {
117809                   _noteCache.loaded[tile.id] = true;
117810                 }
117811
117812                 throttleLoadUsers();
117813                 dispatch$2.call('loadedNotes');
117814               }, options);
117815             });
117816           },
117817           // Create a note
117818           // POST /api/0.6/notes?params
117819           postNoteCreate: function postNoteCreate(note, callback) {
117820             if (!this.authenticated()) {
117821               return callback({
117822                 message: 'Not Authenticated',
117823                 status: -3
117824               }, note);
117825             }
117826
117827             if (_noteCache.inflightPost[note.id]) {
117828               return callback({
117829                 message: 'Note update already inflight',
117830                 status: -2
117831               }, note);
117832             }
117833
117834             if (!note.loc[0] || !note.loc[1] || !note.newComment) return; // location & description required
117835
117836             var comment = note.newComment;
117837
117838             if (note.newCategory && note.newCategory !== 'None') {
117839               comment += ' #' + note.newCategory;
117840             }
117841
117842             var path = '/api/0.6/notes?' + utilQsString({
117843               lon: note.loc[0],
117844               lat: note.loc[1],
117845               text: comment
117846             });
117847             _noteCache.inflightPost[note.id] = oauth.xhr({
117848               method: 'POST',
117849               path: path
117850             }, wrapcb(this, done, _connectionID));
117851
117852             function done(err, xml) {
117853               delete _noteCache.inflightPost[note.id];
117854
117855               if (err) {
117856                 return callback(err);
117857               } // we get the updated note back, remove from caches and reparse..
117858
117859
117860               this.removeNote(note);
117861               var options = {
117862                 skipSeen: false
117863               };
117864               return parseXML(xml, function (err, results) {
117865                 if (err) {
117866                   return callback(err);
117867                 } else {
117868                   return callback(undefined, results[0]);
117869                 }
117870               }, options);
117871             }
117872           },
117873           // Update a note
117874           // POST /api/0.6/notes/#id/comment?text=comment
117875           // POST /api/0.6/notes/#id/close?text=comment
117876           // POST /api/0.6/notes/#id/reopen?text=comment
117877           postNoteUpdate: function postNoteUpdate(note, newStatus, callback) {
117878             if (!this.authenticated()) {
117879               return callback({
117880                 message: 'Not Authenticated',
117881                 status: -3
117882               }, note);
117883             }
117884
117885             if (_noteCache.inflightPost[note.id]) {
117886               return callback({
117887                 message: 'Note update already inflight',
117888                 status: -2
117889               }, note);
117890             }
117891
117892             var action;
117893
117894             if (note.status !== 'closed' && newStatus === 'closed') {
117895               action = 'close';
117896             } else if (note.status !== 'open' && newStatus === 'open') {
117897               action = 'reopen';
117898             } else {
117899               action = 'comment';
117900               if (!note.newComment) return; // when commenting, comment required
117901             }
117902
117903             var path = '/api/0.6/notes/' + note.id + '/' + action;
117904
117905             if (note.newComment) {
117906               path += '?' + utilQsString({
117907                 text: note.newComment
117908               });
117909             }
117910
117911             _noteCache.inflightPost[note.id] = oauth.xhr({
117912               method: 'POST',
117913               path: path
117914             }, wrapcb(this, done, _connectionID));
117915
117916             function done(err, xml) {
117917               delete _noteCache.inflightPost[note.id];
117918
117919               if (err) {
117920                 return callback(err);
117921               } // we get the updated note back, remove from caches and reparse..
117922
117923
117924               this.removeNote(note); // update closed note cache - used to populate `closed:note` changeset tag
117925
117926               if (action === 'close') {
117927                 _noteCache.closed[note.id] = true;
117928               } else if (action === 'reopen') {
117929                 delete _noteCache.closed[note.id];
117930               }
117931
117932               var options = {
117933                 skipSeen: false
117934               };
117935               return parseXML(xml, function (err, results) {
117936                 if (err) {
117937                   return callback(err);
117938                 } else {
117939                   return callback(undefined, results[0]);
117940                 }
117941               }, options);
117942             }
117943           },
117944           "switch": function _switch(options) {
117945             urlroot = options.urlroot;
117946             oauth.options(Object.assign({
117947               url: urlroot,
117948               loading: authLoading,
117949               done: authDone
117950             }, options));
117951             this.reset();
117952             this.userChangesets(function () {}); // eagerly load user details/changesets
117953
117954             dispatch$2.call('change');
117955             return this;
117956           },
117957           toggle: function toggle(val) {
117958             _off = !val;
117959             return this;
117960           },
117961           isChangesetInflight: function isChangesetInflight() {
117962             return !!_changeset.inflight;
117963           },
117964           // get/set cached data
117965           // This is used to save/restore the state when entering/exiting the walkthrough
117966           // Also used for testing purposes.
117967           caches: function caches(obj) {
117968             function cloneCache(source) {
117969               var target = {};
117970               Object.keys(source).forEach(function (k) {
117971                 if (k === 'rtree') {
117972                   target.rtree = new RBush().fromJSON(source.rtree.toJSON()); // clone rbush
117973                 } else if (k === 'note') {
117974                   target.note = {};
117975                   Object.keys(source.note).forEach(function (id) {
117976                     target.note[id] = osmNote(source.note[id]); // copy notes
117977                   });
117978                 } else {
117979                   target[k] = JSON.parse(JSON.stringify(source[k])); // clone deep
117980                 }
117981               });
117982               return target;
117983             }
117984
117985             if (!arguments.length) {
117986               return {
117987                 tile: cloneCache(_tileCache),
117988                 note: cloneCache(_noteCache),
117989                 user: cloneCache(_userCache)
117990               };
117991             } // access caches directly for testing (e.g., loading notes rtree)
117992
117993
117994             if (obj === 'get') {
117995               return {
117996                 tile: _tileCache,
117997                 note: _noteCache,
117998                 user: _userCache
117999               };
118000             }
118001
118002             if (obj.tile) {
118003               _tileCache = obj.tile;
118004               _tileCache.inflight = {};
118005             }
118006
118007             if (obj.note) {
118008               _noteCache = obj.note;
118009               _noteCache.inflight = {};
118010               _noteCache.inflightPost = {};
118011             }
118012
118013             if (obj.user) {
118014               _userCache = obj.user;
118015             }
118016
118017             return this;
118018           },
118019           logout: function logout() {
118020             _userChangesets = undefined;
118021             _userDetails = undefined;
118022             oauth.logout();
118023             dispatch$2.call('change');
118024             return this;
118025           },
118026           authenticated: function authenticated() {
118027             return oauth.authenticated();
118028           },
118029           authenticate: function authenticate(callback) {
118030             var that = this;
118031             var cid = _connectionID;
118032             _userChangesets = undefined;
118033             _userDetails = undefined;
118034
118035             function done(err, res) {
118036               if (err) {
118037                 if (callback) callback(err);
118038                 return;
118039               }
118040
118041               if (that.getConnectionId() !== cid) {
118042                 if (callback) callback({
118043                   message: 'Connection Switched',
118044                   status: -1
118045                 });
118046                 return;
118047               }
118048
118049               _rateLimitError = undefined;
118050               dispatch$2.call('change');
118051               if (callback) callback(err, res);
118052               that.userChangesets(function () {}); // eagerly load user details/changesets
118053             }
118054
118055             return oauth.authenticate(done);
118056           },
118057           imageryBlocklists: function imageryBlocklists() {
118058             return _imageryBlocklists;
118059           },
118060           tileZoom: function tileZoom(val) {
118061             if (!arguments.length) return _tileZoom;
118062             _tileZoom = val;
118063             return this;
118064           },
118065           // get all cached notes covering the viewport
118066           notes: function notes(projection) {
118067             var viewport = projection.clipExtent();
118068             var min = [viewport[0][0], viewport[1][1]];
118069             var max = [viewport[1][0], viewport[0][1]];
118070             var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();
118071             return _noteCache.rtree.search(bbox).map(function (d) {
118072               return d.data;
118073             });
118074           },
118075           // get a single note from the cache
118076           getNote: function getNote(id) {
118077             return _noteCache.note[id];
118078           },
118079           // remove a single note from the cache
118080           removeNote: function removeNote(note) {
118081             if (!(note instanceof osmNote) || !note.id) return;
118082             delete _noteCache.note[note.id];
118083             updateRtree(encodeNoteRtree(note), false); // false = remove
118084           },
118085           // replace a single note in the cache
118086           replaceNote: function replaceNote(note) {
118087             if (!(note instanceof osmNote) || !note.id) return;
118088             _noteCache.note[note.id] = note;
118089             updateRtree(encodeNoteRtree(note), true); // true = replace
118090
118091             return note;
118092           },
118093           // Get an array of note IDs closed during this session.
118094           // Used to populate `closed:note` changeset tag
118095           getClosedIDs: function getClosedIDs() {
118096             return Object.keys(_noteCache.closed).sort();
118097           }
118098         };
118099
118100         var _apibase$1 = 'https://wiki.openstreetmap.org/w/api.php';
118101         var _inflight$1 = {};
118102         var _wikibaseCache = {};
118103         var _localeIDs = {
118104           en: false
118105         };
118106
118107         var debouncedRequest$1 = debounce(request$1, 500, {
118108           leading: false
118109         });
118110
118111         function request$1(url, callback) {
118112           if (_inflight$1[url]) return;
118113           var controller = new AbortController();
118114           _inflight$1[url] = controller;
118115           d3_json(url, {
118116             signal: controller.signal
118117           }).then(function (result) {
118118             delete _inflight$1[url];
118119             if (callback) callback(null, result);
118120           })["catch"](function (err) {
118121             delete _inflight$1[url];
118122             if (err.name === 'AbortError') return;
118123             if (callback) callback(err.message);
118124           });
118125         }
118126
118127         var serviceOsmWikibase = {
118128           init: function init() {
118129             _inflight$1 = {};
118130             _wikibaseCache = {};
118131             _localeIDs = {};
118132           },
118133           reset: function reset() {
118134             Object.values(_inflight$1).forEach(function (controller) {
118135               controller.abort();
118136             });
118137             _inflight$1 = {};
118138           },
118139
118140           /**
118141            * Get the best value for the property, or undefined if not found
118142            * @param entity object from wikibase
118143            * @param property string e.g. 'P4' for image
118144            * @param langCode string e.g. 'fr' for French
118145            */
118146           claimToValue: function claimToValue(entity, property, langCode) {
118147             if (!entity.claims[property]) return undefined;
118148             var locale = _localeIDs[langCode];
118149             var preferredPick, localePick;
118150             entity.claims[property].forEach(function (stmt) {
118151               // If exists, use value limited to the needed language (has a qualifier P26 = locale)
118152               // Or if not found, use the first value with the "preferred" rank
118153               if (!preferredPick && stmt.rank === 'preferred') {
118154                 preferredPick = stmt;
118155               }
118156
118157               if (locale && stmt.qualifiers && stmt.qualifiers.P26 && stmt.qualifiers.P26[0].datavalue.value.id === locale) {
118158                 localePick = stmt;
118159               }
118160             });
118161             var result = localePick || preferredPick;
118162
118163             if (result) {
118164               var datavalue = result.mainsnak.datavalue;
118165               return datavalue.type === 'wikibase-entityid' ? datavalue.value.id : datavalue.value;
118166             } else {
118167               return undefined;
118168             }
118169           },
118170
118171           /**
118172            * Convert monolingual property into a key-value object (language -> value)
118173            * @param entity object from wikibase
118174            * @param property string e.g. 'P31' for monolingual wiki page title
118175            */
118176           monolingualClaimToValueObj: function monolingualClaimToValueObj(entity, property) {
118177             if (!entity || !entity.claims[property]) return undefined;
118178             return entity.claims[property].reduce(function (acc, obj) {
118179               var value = obj.mainsnak.datavalue.value;
118180               acc[value.language] = value.text;
118181               return acc;
118182             }, {});
118183           },
118184           toSitelink: function toSitelink(key, value) {
118185             var result = value ? 'Tag:' + key + '=' + value : 'Key:' + key;
118186             return result.replace(/_/g, ' ').trim();
118187           },
118188           //
118189           // Pass params object of the form:
118190           // {
118191           //   key: 'string',
118192           //   value: 'string',
118193           //   langCode: 'string'
118194           // }
118195           //
118196           getEntity: function getEntity(params, callback) {
118197             var doRequest = params.debounce ? debouncedRequest$1 : request$1;
118198             var that = this;
118199             var titles = [];
118200             var result = {};
118201             var rtypeSitelink = params.key === 'type' && params.value ? ('Relation:' + params.value).replace(/_/g, ' ').trim() : false;
118202             var keySitelink = params.key ? this.toSitelink(params.key) : false;
118203             var tagSitelink = params.key && params.value ? this.toSitelink(params.key, params.value) : false;
118204             var localeSitelink;
118205
118206             if (params.langCodes) {
118207               params.langCodes.forEach(function (langCode) {
118208                 if (_localeIDs[langCode] === undefined) {
118209                   // If this is the first time we are asking about this locale,
118210                   // fetch corresponding entity (if it exists), and cache it.
118211                   // If there is no such entry, cache `false` value to avoid re-requesting it.
118212                   localeSitelink = ('Locale:' + langCode).replace(/_/g, ' ').trim();
118213                   titles.push(localeSitelink);
118214                 }
118215               });
118216             }
118217
118218             if (rtypeSitelink) {
118219               if (_wikibaseCache[rtypeSitelink]) {
118220                 result.rtype = _wikibaseCache[rtypeSitelink];
118221               } else {
118222                 titles.push(rtypeSitelink);
118223               }
118224             }
118225
118226             if (keySitelink) {
118227               if (_wikibaseCache[keySitelink]) {
118228                 result.key = _wikibaseCache[keySitelink];
118229               } else {
118230                 titles.push(keySitelink);
118231               }
118232             }
118233
118234             if (tagSitelink) {
118235               if (_wikibaseCache[tagSitelink]) {
118236                 result.tag = _wikibaseCache[tagSitelink];
118237               } else {
118238                 titles.push(tagSitelink);
118239               }
118240             }
118241
118242             if (!titles.length) {
118243               // Nothing to do, we already had everything in the cache
118244               return callback(null, result);
118245             } // Requesting just the user language code
118246             // If backend recognizes the code, it will perform proper fallbacks,
118247             // and the result will contain the requested code. If not, all values are returned:
118248             // {"zh-tw":{"value":"...","language":"zh-tw","source-language":"zh-hant"}
118249             // {"pt-br":{"value":"...","language":"pt","for-language":"pt-br"}}
118250
118251
118252             var obj = {
118253               action: 'wbgetentities',
118254               sites: 'wiki',
118255               titles: titles.join('|'),
118256               languages: params.langCodes.join('|'),
118257               languagefallback: 1,
118258               origin: '*',
118259               format: 'json' // There is an MW Wikibase API bug https://phabricator.wikimedia.org/T212069
118260               // We shouldn't use v1 until it gets fixed, but should switch to it afterwards
118261               // formatversion: 2,
118262
118263             };
118264             var url = _apibase$1 + '?' + utilQsString(obj);
118265             doRequest(url, function (err, d) {
118266               if (err) {
118267                 callback(err);
118268               } else if (!d.success || d.error) {
118269                 callback(d.error.messages.map(function (v) {
118270                   return v.html['*'];
118271                 }).join('<br>'));
118272               } else {
118273                 var localeID = false;
118274                 Object.values(d.entities).forEach(function (res) {
118275                   if (res.missing !== '') {
118276                     var title = res.sitelinks.wiki.title;
118277
118278                     if (title === rtypeSitelink) {
118279                       _wikibaseCache[rtypeSitelink] = res;
118280                       result.rtype = res;
118281                     } else if (title === keySitelink) {
118282                       _wikibaseCache[keySitelink] = res;
118283                       result.key = res;
118284                     } else if (title === tagSitelink) {
118285                       _wikibaseCache[tagSitelink] = res;
118286                       result.tag = res;
118287                     } else if (title === localeSitelink) {
118288                       localeID = res.id;
118289                     } else {
118290                       console.log('Unexpected title ' + title); // eslint-disable-line no-console
118291                     }
118292                   }
118293                 });
118294
118295                 if (localeSitelink) {
118296                   // If locale ID is not found, store false to prevent repeated queries
118297                   that.addLocale(params.langCodes[0], localeID);
118298                 }
118299
118300                 callback(null, result);
118301               }
118302             });
118303           },
118304           //
118305           // Pass params object of the form:
118306           // {
118307           //   key: 'string',     // required
118308           //   value: 'string'    // optional
118309           // }
118310           //
118311           // Get an result object used to display tag documentation
118312           // {
118313           //   title:        'string',
118314           //   description:  'string',
118315           //   editURL:      'string',
118316           //   imageURL:     'string',
118317           //   wiki:         { title: 'string', text: 'string', url: 'string' }
118318           // }
118319           //
118320           getDocs: function getDocs(params, callback) {
118321             var that = this;
118322             var langCodes = _mainLocalizer.localeCodes().map(function (code) {
118323               return code.toLowerCase();
118324             });
118325             params.langCodes = langCodes;
118326             this.getEntity(params, function (err, data) {
118327               if (err) {
118328                 callback(err);
118329                 return;
118330               }
118331
118332               var entity = data.rtype || data.tag || data.key;
118333
118334               if (!entity) {
118335                 callback('No entity');
118336                 return;
118337               }
118338
118339               var i;
118340               var description;
118341
118342               for (i in langCodes) {
118343                 var _code = langCodes[i];
118344
118345                 if (entity.descriptions[_code] && entity.descriptions[_code].language === _code) {
118346                   description = entity.descriptions[_code];
118347                   break;
118348                 }
118349               }
118350
118351               if (!description && Object.values(entity.descriptions).length) description = Object.values(entity.descriptions)[0]; // prepare result
118352
118353               var result = {
118354                 title: entity.title,
118355                 description: description ? description.value : '',
118356                 descriptionLocaleCode: description ? description.language : '',
118357                 editURL: 'https://wiki.openstreetmap.org/wiki/' + entity.title
118358               }; // add image
118359
118360               if (entity.claims) {
118361                 var imageroot;
118362                 var image = that.claimToValue(entity, 'P4', langCodes[0]);
118363
118364                 if (image) {
118365                   imageroot = 'https://commons.wikimedia.org/w/index.php';
118366                 } else {
118367                   image = that.claimToValue(entity, 'P28', langCodes[0]);
118368
118369                   if (image) {
118370                     imageroot = 'https://wiki.openstreetmap.org/w/index.php';
118371                   }
118372                 }
118373
118374                 if (imageroot && image) {
118375                   result.imageURL = imageroot + '?' + utilQsString({
118376                     title: 'Special:Redirect/file/' + image,
118377                     width: 400
118378                   });
118379                 }
118380               } // Try to get a wiki page from tag data item first, followed by the corresponding key data item.
118381               // If neither tag nor key data item contain a wiki page in the needed language nor English,
118382               // get the first found wiki page from either the tag or the key item.
118383
118384
118385               var rtypeWiki = that.monolingualClaimToValueObj(data.rtype, 'P31');
118386               var tagWiki = that.monolingualClaimToValueObj(data.tag, 'P31');
118387               var keyWiki = that.monolingualClaimToValueObj(data.key, 'P31');
118388               var wikis = [rtypeWiki, tagWiki, keyWiki];
118389
118390               for (i in wikis) {
118391                 var wiki = wikis[i];
118392
118393                 for (var j in langCodes) {
118394                   var code = langCodes[j];
118395                   var referenceId = langCodes[0].split('-')[0] !== 'en' && code.split('-')[0] === 'en' ? 'inspector.wiki_en_reference' : 'inspector.wiki_reference';
118396                   var info = getWikiInfo(wiki, code, referenceId);
118397
118398                   if (info) {
118399                     result.wiki = info;
118400                     break;
118401                   }
118402                 }
118403
118404                 if (result.wiki) break;
118405               }
118406
118407               callback(null, result); // Helper method to get wiki info if a given language exists
118408
118409               function getWikiInfo(wiki, langCode, tKey) {
118410                 if (wiki && wiki[langCode]) {
118411                   return {
118412                     title: wiki[langCode],
118413                     text: tKey,
118414                     url: 'https://wiki.openstreetmap.org/wiki/' + wiki[langCode]
118415                   };
118416                 }
118417               }
118418             });
118419           },
118420           addLocale: function addLocale(langCode, qid) {
118421             // Makes it easier to unit test
118422             _localeIDs[langCode] = qid;
118423           },
118424           apibase: function apibase(val) {
118425             if (!arguments.length) return _apibase$1;
118426             _apibase$1 = val;
118427             return this;
118428           }
118429         };
118430
118431         var jsonpCache = {};
118432         window.jsonpCache = jsonpCache;
118433         function jsonpRequest(url, callback) {
118434           var request = {
118435             abort: function abort() {}
118436           };
118437
118438           if (window.JSONP_FIX) {
118439             if (window.JSONP_DELAY === 0) {
118440               callback(window.JSONP_FIX);
118441             } else {
118442               var t = window.setTimeout(function () {
118443                 callback(window.JSONP_FIX);
118444               }, window.JSONP_DELAY || 0);
118445
118446               request.abort = function () {
118447                 window.clearTimeout(t);
118448               };
118449             }
118450
118451             return request;
118452           }
118453
118454           function rand() {
118455             var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
118456             var c = '';
118457             var i = -1;
118458
118459             while (++i < 15) {
118460               c += chars.charAt(Math.floor(Math.random() * 52));
118461             }
118462
118463             return c;
118464           }
118465
118466           function create(url) {
118467             var e = url.match(/callback=(\w+)/);
118468             var c = e ? e[1] : rand();
118469
118470             jsonpCache[c] = function (data) {
118471               if (jsonpCache[c]) {
118472                 callback(data);
118473               }
118474
118475               finalize();
118476             };
118477
118478             function finalize() {
118479               delete jsonpCache[c];
118480               script.remove();
118481             }
118482
118483             request.abort = finalize;
118484             return 'jsonpCache.' + c;
118485           }
118486
118487           var cb = create(url);
118488           var script = select('head').append('script').attr('type', 'text/javascript').attr('src', url.replace(/(\{|%7B)callback(\}|%7D)/, cb));
118489           return request;
118490         }
118491
118492         var bubbleApi = 'https://dev.virtualearth.net/mapcontrol/HumanScaleServices/GetBubbles.ashx?';
118493         var streetsideImagesApi = 'https://t.ssl.ak.tiles.virtualearth.net/tiles/';
118494         var bubbleAppKey = 'AuftgJsO0Xs8Ts4M1xZUQJQXJNsvmh3IV8DkNieCiy3tCwCUMq76-WpkrBtNAuEm';
118495         var pannellumViewerCSS = 'pannellum-streetside/pannellum.css';
118496         var pannellumViewerJS = 'pannellum-streetside/pannellum.js';
118497         var maxResults = 2000;
118498         var tileZoom = 16.5;
118499         var tiler$1 = utilTiler().zoomExtent([tileZoom, tileZoom]).skipNullIsland(true);
118500         var dispatch$1 = dispatch$8('loadedImages', 'viewerChanged');
118501         var minHfov = 10; // zoom in degrees:  20, 10, 5
118502
118503         var maxHfov = 90; // zoom out degrees
118504
118505         var defaultHfov = 45;
118506         var _hires = false;
118507         var _resolution = 512; // higher numbers are slower - 512, 1024, 2048, 4096
118508
118509         var _currScene = 0;
118510
118511         var _ssCache;
118512
118513         var _pannellumViewer;
118514
118515         var _sceneOptions = {
118516           showFullscreenCtrl: false,
118517           autoLoad: true,
118518           compass: true,
118519           yaw: 0,
118520           minHfov: minHfov,
118521           maxHfov: maxHfov,
118522           hfov: defaultHfov,
118523           type: 'cubemap',
118524           cubeMap: []
118525         };
118526
118527         var _loadViewerPromise;
118528         /**
118529          * abortRequest().
118530          */
118531
118532
118533         function abortRequest$1(i) {
118534           i.abort();
118535         }
118536         /**
118537          * localeTimeStamp().
118538          */
118539
118540
118541         function localeTimestamp(s) {
118542           if (!s) return null;
118543           var options = {
118544             day: 'numeric',
118545             month: 'short',
118546             year: 'numeric'
118547           };
118548           var d = new Date(s);
118549           if (isNaN(d.getTime())) return null;
118550           return d.toLocaleString(_mainLocalizer.localeCode(), options);
118551         }
118552         /**
118553          * loadTiles() wraps the process of generating tiles and then fetching image points for each tile.
118554          */
118555
118556
118557         function loadTiles(which, url, projection, margin) {
118558           var tiles = tiler$1.margin(margin).getTiles(projection); // abort inflight requests that are no longer needed
118559
118560           var cache = _ssCache[which];
118561           Object.keys(cache.inflight).forEach(function (k) {
118562             var wanted = tiles.find(function (tile) {
118563               return k.indexOf(tile.id + ',') === 0;
118564             });
118565
118566             if (!wanted) {
118567               abortRequest$1(cache.inflight[k]);
118568               delete cache.inflight[k];
118569             }
118570           });
118571           tiles.forEach(function (tile) {
118572             return loadNextTilePage(which, url, tile);
118573           });
118574         }
118575         /**
118576          * loadNextTilePage() load data for the next tile page in line.
118577          */
118578
118579
118580         function loadNextTilePage(which, url, tile) {
118581           var cache = _ssCache[which];
118582           var nextPage = cache.nextPage[tile.id] || 0;
118583           var id = tile.id + ',' + String(nextPage);
118584           if (cache.loaded[id] || cache.inflight[id]) return;
118585           cache.inflight[id] = getBubbles(url, tile, function (bubbles) {
118586             cache.loaded[id] = true;
118587             delete cache.inflight[id];
118588             if (!bubbles) return; // [].shift() removes the first element, some statistics info, not a bubble point
118589
118590             bubbles.shift();
118591             var features = bubbles.map(function (bubble) {
118592               if (cache.points[bubble.id]) return null; // skip duplicates
118593
118594               var loc = [bubble.lo, bubble.la];
118595               var d = {
118596                 loc: loc,
118597                 key: bubble.id,
118598                 ca: bubble.he,
118599                 captured_at: bubble.cd,
118600                 captured_by: 'microsoft',
118601                 // nbn: bubble.nbn,
118602                 // pbn: bubble.pbn,
118603                 // ad: bubble.ad,
118604                 // rn: bubble.rn,
118605                 pr: bubble.pr,
118606                 // previous
118607                 ne: bubble.ne,
118608                 // next
118609                 pano: true,
118610                 sequenceKey: null
118611               };
118612               cache.points[bubble.id] = d; // a sequence starts here
118613
118614               if (bubble.pr === undefined) {
118615                 cache.leaders.push(bubble.id);
118616               }
118617
118618               return {
118619                 minX: loc[0],
118620                 minY: loc[1],
118621                 maxX: loc[0],
118622                 maxY: loc[1],
118623                 data: d
118624               };
118625             }).filter(Boolean);
118626             cache.rtree.load(features);
118627             connectSequences();
118628
118629             if (which === 'bubbles') {
118630               dispatch$1.call('loadedImages');
118631             }
118632           });
118633         } // call this sometimes to connect the bubbles into sequences
118634
118635
118636         function connectSequences() {
118637           var cache = _ssCache.bubbles;
118638           var keepLeaders = [];
118639
118640           for (var i = 0; i < cache.leaders.length; i++) {
118641             var bubble = cache.points[cache.leaders[i]];
118642             var seen = {}; // try to make a sequence.. use the key of the leader bubble.
118643
118644             var sequence = {
118645               key: bubble.key,
118646               bubbles: []
118647             };
118648             var complete = false;
118649
118650             do {
118651               sequence.bubbles.push(bubble);
118652               seen[bubble.key] = true;
118653
118654               if (bubble.ne === undefined) {
118655                 complete = true;
118656               } else {
118657                 bubble = cache.points[bubble.ne]; // advance to next
118658               }
118659             } while (bubble && !seen[bubble.key] && !complete);
118660
118661             if (complete) {
118662               _ssCache.sequences[sequence.key] = sequence; // assign bubbles to the sequence
118663
118664               for (var j = 0; j < sequence.bubbles.length; j++) {
118665                 sequence.bubbles[j].sequenceKey = sequence.key;
118666               } // create a GeoJSON LineString
118667
118668
118669               sequence.geojson = {
118670                 type: 'LineString',
118671                 properties: {
118672                   captured_at: sequence.bubbles[0] ? sequence.bubbles[0].captured_at : null,
118673                   captured_by: sequence.bubbles[0] ? sequence.bubbles[0].captured_by : null,
118674                   key: sequence.key
118675                 },
118676                 coordinates: sequence.bubbles.map(function (d) {
118677                   return d.loc;
118678                 })
118679               };
118680             } else {
118681               keepLeaders.push(cache.leaders[i]);
118682             }
118683           } // couldn't complete these, save for later
118684
118685
118686           cache.leaders = keepLeaders;
118687         }
118688         /**
118689          * getBubbles() handles the request to the server for a tile extent of 'bubbles' (streetside image locations).
118690          */
118691
118692
118693         function getBubbles(url, tile, callback) {
118694           var rect = tile.extent.rectangle();
118695           var urlForRequest = url + utilQsString({
118696             n: rect[3],
118697             s: rect[1],
118698             e: rect[2],
118699             w: rect[0],
118700             c: maxResults,
118701             appkey: bubbleAppKey,
118702             jsCallback: '{callback}'
118703           });
118704           return jsonpRequest(urlForRequest, function (data) {
118705             if (!data || data.error) {
118706               callback(null);
118707             } else {
118708               callback(data);
118709             }
118710           });
118711         } // partition viewport into higher zoom tiles
118712
118713
118714         function partitionViewport(projection) {
118715           var z = geoScaleToZoom(projection.scale());
118716           var z2 = Math.ceil(z * 2) / 2 + 2.5; // round to next 0.5 and add 2.5
118717
118718           var tiler = utilTiler().zoomExtent([z2, z2]);
118719           return tiler.getTiles(projection).map(function (tile) {
118720             return tile.extent;
118721           });
118722         } // no more than `limit` results per partition.
118723
118724
118725         function searchLimited(limit, projection, rtree) {
118726           limit = limit || 5;
118727           return partitionViewport(projection).reduce(function (result, extent) {
118728             var found = rtree.search(extent.bbox()).slice(0, limit).map(function (d) {
118729               return d.data;
118730             });
118731             return found.length ? result.concat(found) : result;
118732           }, []);
118733         }
118734         /**
118735          * loadImage()
118736          */
118737
118738
118739         function loadImage(imgInfo) {
118740           return new Promise(function (resolve) {
118741             var img = new Image();
118742
118743             img.onload = function () {
118744               var canvas = document.getElementById('ideditor-canvas' + imgInfo.face);
118745               var ctx = canvas.getContext('2d');
118746               ctx.drawImage(img, imgInfo.x, imgInfo.y);
118747               resolve({
118748                 imgInfo: imgInfo,
118749                 status: 'ok'
118750               });
118751             };
118752
118753             img.onerror = function () {
118754               resolve({
118755                 data: imgInfo,
118756                 status: 'error'
118757               });
118758             };
118759
118760             img.setAttribute('crossorigin', '');
118761             img.src = imgInfo.url;
118762           });
118763         }
118764         /**
118765          * loadCanvas()
118766          */
118767
118768
118769         function loadCanvas(imageGroup) {
118770           return Promise.all(imageGroup.map(loadImage)).then(function (data) {
118771             var canvas = document.getElementById('ideditor-canvas' + data[0].imgInfo.face);
118772             var which = {
118773               '01': 0,
118774               '02': 1,
118775               '03': 2,
118776               '10': 3,
118777               '11': 4,
118778               '12': 5
118779             };
118780             var face = data[0].imgInfo.face;
118781             _sceneOptions.cubeMap[which[face]] = canvas.toDataURL('image/jpeg', 1.0);
118782             return {
118783               status: 'loadCanvas for face ' + data[0].imgInfo.face + 'ok'
118784             };
118785           });
118786         }
118787         /**
118788          * loadFaces()
118789          */
118790
118791
118792         function loadFaces(faceGroup) {
118793           return Promise.all(faceGroup.map(loadCanvas)).then(function () {
118794             return {
118795               status: 'loadFaces done'
118796             };
118797           });
118798         }
118799
118800         function setupCanvas(selection, reset) {
118801           if (reset) {
118802             selection.selectAll('#ideditor-stitcher-canvases').remove();
118803           } // Add the Streetside working canvases. These are used for 'stitching', or combining,
118804           // multiple images for each of the six faces, before passing to the Pannellum control as DataUrls
118805
118806
118807           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) {
118808             return 'ideditor-' + d;
118809           }).attr('width', _resolution).attr('height', _resolution);
118810         }
118811
118812         function qkToXY(qk) {
118813           var x = 0;
118814           var y = 0;
118815           var scale = 256;
118816
118817           for (var i = qk.length; i > 0; i--) {
118818             var key = qk[i - 1];
118819             x += +(key === '1' || key === '3') * scale;
118820             y += +(key === '2' || key === '3') * scale;
118821             scale *= 2;
118822           }
118823
118824           return [x, y];
118825         }
118826
118827         function getQuadKeys() {
118828           var dim = _resolution / 256;
118829           var quadKeys;
118830
118831           if (dim === 16) {
118832             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'];
118833           } else if (dim === 8) {
118834             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'];
118835           } else if (dim === 4) {
118836             quadKeys = ['00', '01', '10', '11', '02', '03', '12', '13', '20', '21', '30', '31', '22', '23', '32', '33'];
118837           } else {
118838             // dim === 2
118839             quadKeys = ['0', '1', '2', '3'];
118840           }
118841
118842           return quadKeys;
118843         }
118844
118845         var serviceStreetside = {
118846           /**
118847            * init() initialize streetside.
118848            */
118849           init: function init() {
118850             if (!_ssCache) {
118851               this.reset();
118852             }
118853
118854             this.event = utilRebind(this, dispatch$1, 'on');
118855           },
118856
118857           /**
118858            * reset() reset the cache.
118859            */
118860           reset: function reset() {
118861             if (_ssCache) {
118862               Object.values(_ssCache.bubbles.inflight).forEach(abortRequest$1);
118863             }
118864
118865             _ssCache = {
118866               bubbles: {
118867                 inflight: {},
118868                 loaded: {},
118869                 nextPage: {},
118870                 rtree: new RBush(),
118871                 points: {},
118872                 leaders: []
118873               },
118874               sequences: {}
118875             };
118876           },
118877
118878           /**
118879            * bubbles()
118880            */
118881           bubbles: function bubbles(projection) {
118882             var limit = 5;
118883             return searchLimited(limit, projection, _ssCache.bubbles.rtree);
118884           },
118885           cachedImage: function cachedImage(imageKey) {
118886             return _ssCache.bubbles.points[imageKey];
118887           },
118888           sequences: function sequences(projection) {
118889             var viewport = projection.clipExtent();
118890             var min = [viewport[0][0], viewport[1][1]];
118891             var max = [viewport[1][0], viewport[0][1]];
118892             var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();
118893             var seen = {};
118894             var results = []; // all sequences for bubbles in viewport
118895
118896             _ssCache.bubbles.rtree.search(bbox).forEach(function (d) {
118897               var key = d.data.sequenceKey;
118898
118899               if (key && !seen[key]) {
118900                 seen[key] = true;
118901                 results.push(_ssCache.sequences[key].geojson);
118902               }
118903             });
118904
118905             return results;
118906           },
118907
118908           /**
118909            * loadBubbles()
118910            */
118911           loadBubbles: function loadBubbles(projection, margin) {
118912             // by default: request 2 nearby tiles so we can connect sequences.
118913             if (margin === undefined) margin = 2;
118914             loadTiles('bubbles', bubbleApi, projection, margin);
118915           },
118916           viewer: function viewer() {
118917             return _pannellumViewer;
118918           },
118919           initViewer: function initViewer() {
118920             if (!window.pannellum) return;
118921             if (_pannellumViewer) return;
118922             _currScene += 1;
118923
118924             var sceneID = _currScene.toString();
118925
118926             var options = {
118927               'default': {
118928                 firstScene: sceneID
118929               },
118930               scenes: {}
118931             };
118932             options.scenes[sceneID] = _sceneOptions;
118933             _pannellumViewer = window.pannellum.viewer('ideditor-viewer-streetside', options);
118934           },
118935           ensureViewerLoaded: function ensureViewerLoaded(context) {
118936             if (_loadViewerPromise) return _loadViewerPromise; // create ms-wrapper, a photo wrapper class
118937
118938             var wrap = context.container().select('.photoviewer').selectAll('.ms-wrapper').data([0]); // inject ms-wrapper into the photoviewer div
118939             // (used by all to house each custom photo viewer)
118940
118941             var wrapEnter = wrap.enter().append('div').attr('class', 'photo-wrapper ms-wrapper').classed('hide', true);
118942             var that = this;
118943             var pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse'; // inject div to support streetside viewer (pannellum) and attribution line
118944
118945             wrapEnter.append('div').attr('id', 'ideditor-viewer-streetside').on(pointerPrefix + 'down.streetside', function () {
118946               select(window).on(pointerPrefix + 'move.streetside', function () {
118947                 dispatch$1.call('viewerChanged');
118948               }, true);
118949             }).on(pointerPrefix + 'up.streetside pointercancel.streetside', function () {
118950               select(window).on(pointerPrefix + 'move.streetside', null); // continue dispatching events for a few seconds, in case viewer has inertia.
118951
118952               var t = timer(function (elapsed) {
118953                 dispatch$1.call('viewerChanged');
118954
118955                 if (elapsed > 2000) {
118956                   t.stop();
118957                 }
118958               });
118959             }).append('div').attr('class', 'photo-attribution fillD');
118960             var controlsEnter = wrapEnter.append('div').attr('class', 'photo-controls-wrap').append('div').attr('class', 'photo-controls');
118961             controlsEnter.append('button').on('click.back', step(-1)).text('◄');
118962             controlsEnter.append('button').on('click.forward', step(1)).text('►'); // create working canvas for stitching together images
118963
118964             wrap = wrap.merge(wrapEnter).call(setupCanvas, true); // Register viewer resize handler
118965
118966             context.ui().photoviewer.on('resize.streetside', function () {
118967               if (_pannellumViewer) {
118968                 _pannellumViewer.resize();
118969               }
118970             });
118971             _loadViewerPromise = new Promise(function (resolve, reject) {
118972               var loadedCount = 0;
118973
118974               function loaded() {
118975                 loadedCount += 1; // wait until both files are loaded
118976
118977                 if (loadedCount === 2) resolve();
118978               }
118979
118980               var head = select('head'); // load streetside pannellum viewer css
118981
118982               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 () {
118983                 reject();
118984               }); // load streetside pannellum viewer js
118985
118986               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 () {
118987                 reject();
118988               });
118989             })["catch"](function () {
118990               _loadViewerPromise = null;
118991             });
118992             return _loadViewerPromise;
118993
118994             function step(stepBy) {
118995               return function () {
118996                 var viewer = context.container().select('.photoviewer');
118997                 var selected = viewer.empty() ? undefined : viewer.datum();
118998                 if (!selected) return;
118999                 var nextID = stepBy === 1 ? selected.ne : selected.pr;
119000
119001                 var yaw = _pannellumViewer.getYaw();
119002
119003                 var ca = selected.ca + yaw;
119004                 var origin = selected.loc; // construct a search trapezoid pointing out from current bubble
119005
119006                 var meters = 35;
119007                 var p1 = [origin[0] + geoMetersToLon(meters / 5, origin[1]), origin[1]];
119008                 var p2 = [origin[0] + geoMetersToLon(meters / 2, origin[1]), origin[1] + geoMetersToLat(meters)];
119009                 var p3 = [origin[0] - geoMetersToLon(meters / 2, origin[1]), origin[1] + geoMetersToLat(meters)];
119010                 var p4 = [origin[0] - geoMetersToLon(meters / 5, origin[1]), origin[1]];
119011                 var poly = [p1, p2, p3, p4, p1]; // rotate it to face forward/backward
119012
119013                 var angle = (stepBy === 1 ? ca : ca + 180) * (Math.PI / 180);
119014                 poly = geoRotate(poly, -angle, origin);
119015                 var extent = poly.reduce(function (extent, point) {
119016                   return extent.extend(geoExtent(point));
119017                 }, geoExtent()); // find nearest other bubble in the search polygon
119018
119019                 var minDist = Infinity;
119020
119021                 _ssCache.bubbles.rtree.search(extent.bbox()).forEach(function (d) {
119022                   if (d.data.key === selected.key) return;
119023                   if (!geoPointInPolygon(d.data.loc, poly)) return;
119024                   var dist = geoVecLength(d.data.loc, selected.loc);
119025                   var theta = selected.ca - d.data.ca;
119026                   var minTheta = Math.min(Math.abs(theta), 360 - Math.abs(theta));
119027
119028                   if (minTheta > 20) {
119029                     dist += 5; // penalize distance if camera angles don't match
119030                   }
119031
119032                   if (dist < minDist) {
119033                     nextID = d.data.key;
119034                     minDist = dist;
119035                   }
119036                 });
119037
119038                 var nextBubble = nextID && that.cachedImage(nextID);
119039                 if (!nextBubble) return;
119040                 context.map().centerEase(nextBubble.loc);
119041                 that.selectImage(context, nextBubble.key).yaw(yaw).showViewer(context);
119042               };
119043             }
119044           },
119045           yaw: function yaw(_yaw) {
119046             if (typeof _yaw !== 'number') return _yaw;
119047             _sceneOptions.yaw = _yaw;
119048             return this;
119049           },
119050
119051           /**
119052            * showViewer()
119053            */
119054           showViewer: function showViewer(context) {
119055             var wrap = context.container().select('.photoviewer').classed('hide', false);
119056             var isHidden = wrap.selectAll('.photo-wrapper.ms-wrapper.hide').size();
119057
119058             if (isHidden) {
119059               wrap.selectAll('.photo-wrapper:not(.ms-wrapper)').classed('hide', true);
119060               wrap.selectAll('.photo-wrapper.ms-wrapper').classed('hide', false);
119061             }
119062
119063             return this;
119064           },
119065
119066           /**
119067            * hideViewer()
119068            */
119069           hideViewer: function hideViewer(context) {
119070             var viewer = context.container().select('.photoviewer');
119071             if (!viewer.empty()) viewer.datum(null);
119072             viewer.classed('hide', true).selectAll('.photo-wrapper').classed('hide', true);
119073             context.container().selectAll('.viewfield-group, .sequence, .icon-sign').classed('currentView', false);
119074             this.updateUrlImage(null);
119075             return this.setStyles(context, null, true);
119076           },
119077
119078           /**
119079            * selectImage().
119080            */
119081           selectImage: function selectImage(context, key) {
119082             var that = this;
119083             var d = this.cachedImage(key);
119084             var viewer = context.container().select('.photoviewer');
119085             if (!viewer.empty()) viewer.datum(d);
119086             this.setStyles(context, null, true);
119087             var wrap = context.container().select('.photoviewer .ms-wrapper');
119088             var attribution = wrap.selectAll('.photo-attribution').html('');
119089             wrap.selectAll('.pnlm-load-box') // display "loading.."
119090             .style('display', 'block');
119091             if (!d) return this;
119092             this.updateUrlImage(key);
119093             _sceneOptions.northOffset = d.ca;
119094             var line1 = attribution.append('div').attr('class', 'attribution-row');
119095             var hiresDomId = utilUniqueDomId('streetside-hires'); // Add hires checkbox
119096
119097             var label = line1.append('label').attr('for', hiresDomId).attr('class', 'streetside-hires');
119098             label.append('input').attr('type', 'checkbox').attr('id', hiresDomId).property('checked', _hires).on('click', function (d3_event) {
119099               d3_event.stopPropagation();
119100               _hires = !_hires;
119101               _resolution = _hires ? 1024 : 512;
119102               wrap.call(setupCanvas, true);
119103               var viewstate = {
119104                 yaw: _pannellumViewer.getYaw(),
119105                 pitch: _pannellumViewer.getPitch(),
119106                 hfov: _pannellumViewer.getHfov()
119107               };
119108               _sceneOptions = Object.assign(_sceneOptions, viewstate);
119109               that.selectImage(context, d.key).showViewer(context);
119110             });
119111             label.append('span').call(_t.append('streetside.hires'));
119112             var captureInfo = line1.append('div').attr('class', 'attribution-capture-info'); // Add capture date
119113
119114             if (d.captured_by) {
119115               var yyyy = new Date().getFullYear();
119116               captureInfo.append('a').attr('class', 'captured_by').attr('target', '_blank').attr('href', 'https://www.microsoft.com/en-us/maps/streetside').text('©' + yyyy + ' Microsoft');
119117               captureInfo.append('span').text('|');
119118             }
119119
119120             if (d.captured_at) {
119121               captureInfo.append('span').attr('class', 'captured_at').text(localeTimestamp(d.captured_at));
119122             } // Add image links
119123
119124
119125             var line2 = attribution.append('div').attr('class', 'attribution-row');
119126             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'));
119127             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'));
119128             var bubbleIdQuadKey = d.key.toString(4);
119129             var paddingNeeded = 16 - bubbleIdQuadKey.length;
119130
119131             for (var i = 0; i < paddingNeeded; i++) {
119132               bubbleIdQuadKey = '0' + bubbleIdQuadKey;
119133             }
119134
119135             var imgUrlPrefix = streetsideImagesApi + 'hs' + bubbleIdQuadKey;
119136             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
119137
119138             var faceKeys = ['01', '02', '03', '10', '11', '12']; // Map images to cube faces
119139
119140             var quadKeys = getQuadKeys();
119141             var faces = faceKeys.map(function (faceKey) {
119142               return quadKeys.map(function (quadKey) {
119143                 var xy = qkToXY(quadKey);
119144                 return {
119145                   face: faceKey,
119146                   url: imgUrlPrefix + faceKey + quadKey + imgUrlSuffix,
119147                   x: xy[0],
119148                   y: xy[1]
119149                 };
119150               });
119151             });
119152             loadFaces(faces).then(function () {
119153               if (!_pannellumViewer) {
119154                 that.initViewer();
119155               } else {
119156                 // make a new scene
119157                 _currScene += 1;
119158
119159                 var sceneID = _currScene.toString();
119160
119161                 _pannellumViewer.addScene(sceneID, _sceneOptions).loadScene(sceneID); // remove previous scene
119162
119163
119164                 if (_currScene > 2) {
119165                   sceneID = (_currScene - 1).toString();
119166
119167                   _pannellumViewer.removeScene(sceneID);
119168                 }
119169               }
119170             });
119171             return this;
119172           },
119173           getSequenceKeyForBubble: function getSequenceKeyForBubble(d) {
119174             return d && d.sequenceKey;
119175           },
119176           // Updates the currently highlighted sequence and selected bubble.
119177           // Reset is only necessary when interacting with the viewport because
119178           // this implicitly changes the currently selected bubble/sequence
119179           setStyles: function setStyles(context, hovered, reset) {
119180             if (reset) {
119181               // reset all layers
119182               context.container().selectAll('.viewfield-group').classed('highlighted', false).classed('hovered', false).classed('currentView', false);
119183               context.container().selectAll('.sequence').classed('highlighted', false).classed('currentView', false);
119184             }
119185
119186             var hoveredBubbleKey = hovered && hovered.key;
119187             var hoveredSequenceKey = this.getSequenceKeyForBubble(hovered);
119188             var hoveredSequence = hoveredSequenceKey && _ssCache.sequences[hoveredSequenceKey];
119189             var hoveredBubbleKeys = hoveredSequence && hoveredSequence.bubbles.map(function (d) {
119190               return d.key;
119191             }) || [];
119192             var viewer = context.container().select('.photoviewer');
119193             var selected = viewer.empty() ? undefined : viewer.datum();
119194             var selectedBubbleKey = selected && selected.key;
119195             var selectedSequenceKey = this.getSequenceKeyForBubble(selected);
119196             var selectedSequence = selectedSequenceKey && _ssCache.sequences[selectedSequenceKey];
119197             var selectedBubbleKeys = selectedSequence && selectedSequence.bubbles.map(function (d) {
119198               return d.key;
119199             }) || []; // highlight sibling viewfields on either the selected or the hovered sequences
119200
119201             var highlightedBubbleKeys = utilArrayUnion(hoveredBubbleKeys, selectedBubbleKeys);
119202             context.container().selectAll('.layer-streetside-images .viewfield-group').classed('highlighted', function (d) {
119203               return highlightedBubbleKeys.indexOf(d.key) !== -1;
119204             }).classed('hovered', function (d) {
119205               return d.key === hoveredBubbleKey;
119206             }).classed('currentView', function (d) {
119207               return d.key === selectedBubbleKey;
119208             });
119209             context.container().selectAll('.layer-streetside-images .sequence').classed('highlighted', function (d) {
119210               return d.properties.key === hoveredSequenceKey;
119211             }).classed('currentView', function (d) {
119212               return d.properties.key === selectedSequenceKey;
119213             }); // update viewfields if needed
119214
119215             context.container().selectAll('.layer-streetside-images .viewfield-group .viewfield').attr('d', viewfieldPath);
119216
119217             function viewfieldPath() {
119218               var d = this.parentNode.__data__;
119219
119220               if (d.pano && d.key !== selectedBubbleKey) {
119221                 return 'M 8,13 m -10,0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0';
119222               } else {
119223                 return 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z';
119224               }
119225             }
119226
119227             return this;
119228           },
119229           updateUrlImage: function updateUrlImage(imageKey) {
119230             if (!window.mocha) {
119231               var hash = utilStringQs(window.location.hash);
119232
119233               if (imageKey) {
119234                 hash.photo = 'streetside/' + imageKey;
119235               } else {
119236                 delete hash.photo;
119237               }
119238
119239               window.location.replace('#' + utilQsString(hash, true));
119240             }
119241           },
119242
119243           /**
119244            * cache().
119245            */
119246           cache: function cache() {
119247             return _ssCache;
119248           }
119249         };
119250
119251         var _apibase = 'https://taginfo.openstreetmap.org/api/4/';
119252         var _inflight = {};
119253         var _popularKeys = {};
119254         var _taginfoCache = {};
119255         var tag_sorts = {
119256           point: 'count_nodes',
119257           vertex: 'count_nodes',
119258           area: 'count_ways',
119259           line: 'count_ways'
119260         };
119261         var tag_sort_members = {
119262           point: 'count_node_members',
119263           vertex: 'count_node_members',
119264           area: 'count_way_members',
119265           line: 'count_way_members',
119266           relation: 'count_relation_members'
119267         };
119268         var tag_filters = {
119269           point: 'nodes',
119270           vertex: 'nodes',
119271           area: 'ways',
119272           line: 'ways'
119273         };
119274         var tag_members_fractions = {
119275           point: 'count_node_members_fraction',
119276           vertex: 'count_node_members_fraction',
119277           area: 'count_way_members_fraction',
119278           line: 'count_way_members_fraction',
119279           relation: 'count_relation_members_fraction'
119280         };
119281
119282         function sets(params, n, o) {
119283           if (params.geometry && o[params.geometry]) {
119284             params[n] = o[params.geometry];
119285           }
119286
119287           return params;
119288         }
119289
119290         function setFilter(params) {
119291           return sets(params, 'filter', tag_filters);
119292         }
119293
119294         function setSort(params) {
119295           return sets(params, 'sortname', tag_sorts);
119296         }
119297
119298         function setSortMembers(params) {
119299           return sets(params, 'sortname', tag_sort_members);
119300         }
119301
119302         function clean(params) {
119303           return utilObjectOmit(params, ['geometry', 'debounce']);
119304         }
119305
119306         function filterKeys(type) {
119307           var count_type = type ? 'count_' + type : 'count_all';
119308           return function (d) {
119309             return parseFloat(d[count_type]) > 2500 || d.in_wiki;
119310           };
119311         }
119312
119313         function filterMultikeys(prefix) {
119314           return function (d) {
119315             // d.key begins with prefix, and d.key contains no additional ':'s
119316             var re = new RegExp('^' + prefix + '(.*)$');
119317             var matches = d.key.match(re) || [];
119318             return matches.length === 2 && matches[1].indexOf(':') === -1;
119319           };
119320         }
119321
119322         function filterValues(allowUpperCase) {
119323           return function (d) {
119324             if (d.value.match(/[;,]/) !== null) return false; // exclude some punctuation
119325
119326             if (!allowUpperCase && d.value.match(/[A-Z*]/) !== null) return false; // exclude uppercase letters
119327
119328             return parseFloat(d.fraction) > 0.0;
119329           };
119330         }
119331
119332         function filterRoles(geometry) {
119333           return function (d) {
119334             if (d.role === '') return false; // exclude empty role
119335
119336             if (d.role.match(/[A-Z*;,]/) !== null) return false; // exclude uppercase letters and some punctuation
119337
119338             return parseFloat(d[tag_members_fractions[geometry]]) > 0.0;
119339           };
119340         }
119341
119342         function valKey(d) {
119343           return {
119344             value: d.key,
119345             title: d.key
119346           };
119347         }
119348
119349         function valKeyDescription(d) {
119350           var obj = {
119351             value: d.value,
119352             title: d.description || d.value
119353           };
119354
119355           if (d.count) {
119356             obj.count = d.count;
119357           }
119358
119359           return obj;
119360         }
119361
119362         function roleKey(d) {
119363           return {
119364             value: d.role,
119365             title: d.role
119366           };
119367         } // sort keys with ':' lower than keys without ':'
119368
119369
119370         function sortKeys(a, b) {
119371           return a.key.indexOf(':') === -1 && b.key.indexOf(':') !== -1 ? -1 : a.key.indexOf(':') !== -1 && b.key.indexOf(':') === -1 ? 1 : 0;
119372         }
119373
119374         var debouncedRequest = debounce(request, 300, {
119375           leading: false
119376         });
119377
119378         function request(url, params, exactMatch, callback, loaded) {
119379           if (_inflight[url]) return;
119380           if (checkCache(url, params, exactMatch, callback)) return;
119381           var controller = new AbortController();
119382           _inflight[url] = controller;
119383           d3_json(url, {
119384             signal: controller.signal
119385           }).then(function (result) {
119386             delete _inflight[url];
119387             if (loaded) loaded(null, result);
119388           })["catch"](function (err) {
119389             delete _inflight[url];
119390             if (err.name === 'AbortError') return;
119391             if (loaded) loaded(err.message);
119392           });
119393         }
119394
119395         function checkCache(url, params, exactMatch, callback) {
119396           var rp = params.rp || 25;
119397           var testQuery = params.query || '';
119398           var testUrl = url;
119399
119400           do {
119401             var hit = _taginfoCache[testUrl]; // exact match, or shorter match yielding fewer than max results (rp)
119402
119403             if (hit && (url === testUrl || hit.length < rp)) {
119404               callback(null, hit);
119405               return true;
119406             } // don't try to shorten the query
119407
119408
119409             if (exactMatch || !testQuery.length) return false; // do shorten the query to see if we already have a cached result
119410             // that has returned fewer than max results (rp)
119411
119412             testQuery = testQuery.slice(0, -1);
119413             testUrl = url.replace(/&query=(.*?)&/, '&query=' + testQuery + '&');
119414           } while (testQuery.length >= 0);
119415
119416           return false;
119417         }
119418
119419         var serviceTaginfo = {
119420           init: function init() {
119421             _inflight = {};
119422             _taginfoCache = {};
119423             _popularKeys = {
119424               // manually exclude some keys – #5377, #7485
119425               postal_code: true,
119426               full_name: true,
119427               loc_name: true,
119428               reg_name: true,
119429               short_name: true,
119430               sorting_name: true,
119431               artist_name: true,
119432               nat_name: true,
119433               long_name: true,
119434               'bridge:name': true
119435             }; // Fetch popular keys.  We'll exclude these from `values`
119436             // lookups because they stress taginfo, and they aren't likely
119437             // to yield meaningful autocomplete results.. see #3955
119438
119439             var params = {
119440               rp: 100,
119441               sortname: 'values_all',
119442               sortorder: 'desc',
119443               page: 1,
119444               debounce: false,
119445               lang: _mainLocalizer.languageCode()
119446             };
119447             this.keys(params, function (err, data) {
119448               if (err) return;
119449               data.forEach(function (d) {
119450                 if (d.value === 'opening_hours') return; // exception
119451
119452                 _popularKeys[d.value] = true;
119453               });
119454             });
119455           },
119456           reset: function reset() {
119457             Object.values(_inflight).forEach(function (controller) {
119458               controller.abort();
119459             });
119460             _inflight = {};
119461           },
119462           keys: function keys(params, callback) {
119463             var doRequest = params.debounce ? debouncedRequest : request;
119464             params = clean(setSort(params));
119465             params = Object.assign({
119466               rp: 10,
119467               sortname: 'count_all',
119468               sortorder: 'desc',
119469               page: 1,
119470               lang: _mainLocalizer.languageCode()
119471             }, params);
119472             var url = _apibase + 'keys/all?' + utilQsString(params);
119473             doRequest(url, params, false, callback, function (err, d) {
119474               if (err) {
119475                 callback(err);
119476               } else {
119477                 var f = filterKeys(params.filter);
119478                 var result = d.data.filter(f).sort(sortKeys).map(valKey);
119479                 _taginfoCache[url] = result;
119480                 callback(null, result);
119481               }
119482             });
119483           },
119484           multikeys: function multikeys(params, callback) {
119485             var doRequest = params.debounce ? debouncedRequest : request;
119486             params = clean(setSort(params));
119487             params = Object.assign({
119488               rp: 25,
119489               sortname: 'count_all',
119490               sortorder: 'desc',
119491               page: 1,
119492               lang: _mainLocalizer.languageCode()
119493             }, params);
119494             var prefix = params.query;
119495             var url = _apibase + 'keys/all?' + utilQsString(params);
119496             doRequest(url, params, true, callback, function (err, d) {
119497               if (err) {
119498                 callback(err);
119499               } else {
119500                 var f = filterMultikeys(prefix);
119501                 var result = d.data.filter(f).map(valKey);
119502                 _taginfoCache[url] = result;
119503                 callback(null, result);
119504               }
119505             });
119506           },
119507           values: function values(params, callback) {
119508             // Exclude popular keys from values lookups.. see #3955
119509             var key = params.key;
119510
119511             if (key && _popularKeys[key]) {
119512               callback(null, []);
119513               return;
119514             }
119515
119516             var doRequest = params.debounce ? debouncedRequest : request;
119517             params = clean(setSort(setFilter(params)));
119518             params = Object.assign({
119519               rp: 25,
119520               sortname: 'count_all',
119521               sortorder: 'desc',
119522               page: 1,
119523               lang: _mainLocalizer.languageCode()
119524             }, params);
119525             var url = _apibase + 'key/values?' + utilQsString(params);
119526             doRequest(url, params, false, callback, function (err, d) {
119527               if (err) {
119528                 callback(err);
119529               } else {
119530                 // In most cases we prefer taginfo value results with lowercase letters.
119531                 // A few OSM keys expect values to contain uppercase values (see #3377).
119532                 // This is not an exhaustive list (e.g. `name` also has uppercase values)
119533                 // but these are the fields where taginfo value lookup is most useful.
119534                 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/;
119535                 var allowUpperCase = re.test(params.key);
119536                 var f = filterValues(allowUpperCase);
119537                 var result = d.data.filter(f).map(valKeyDescription);
119538                 _taginfoCache[url] = result;
119539                 callback(null, result);
119540               }
119541             });
119542           },
119543           roles: function roles(params, callback) {
119544             var doRequest = params.debounce ? debouncedRequest : request;
119545             var geometry = params.geometry;
119546             params = clean(setSortMembers(params));
119547             params = Object.assign({
119548               rp: 25,
119549               sortname: 'count_all_members',
119550               sortorder: 'desc',
119551               page: 1,
119552               lang: _mainLocalizer.languageCode()
119553             }, params);
119554             var url = _apibase + 'relation/roles?' + utilQsString(params);
119555             doRequest(url, params, true, callback, function (err, d) {
119556               if (err) {
119557                 callback(err);
119558               } else {
119559                 var f = filterRoles(geometry);
119560                 var result = d.data.filter(f).map(roleKey);
119561                 _taginfoCache[url] = result;
119562                 callback(null, result);
119563               }
119564             });
119565           },
119566           docs: function docs(params, callback) {
119567             var doRequest = params.debounce ? debouncedRequest : request;
119568             params = clean(setSort(params));
119569             var path = 'key/wiki_pages?';
119570
119571             if (params.value) {
119572               path = 'tag/wiki_pages?';
119573             } else if (params.rtype) {
119574               path = 'relation/wiki_pages?';
119575             }
119576
119577             var url = _apibase + path + utilQsString(params);
119578             doRequest(url, params, true, callback, function (err, d) {
119579               if (err) {
119580                 callback(err);
119581               } else {
119582                 _taginfoCache[url] = d.data;
119583                 callback(null, d.data);
119584               }
119585             });
119586           },
119587           apibase: function apibase(_) {
119588             if (!arguments.length) return _apibase;
119589             _apibase = _;
119590             return this;
119591           }
119592         };
119593
119594         /**
119595          * Wraps a GeoJSON {@link Geometry} in a GeoJSON {@link Feature}.
119596          *
119597          * @name feature
119598          * @param {Geometry} geometry input geometry
119599          * @param {Object} [properties={}] an Object of key-value pairs to add as properties
119600          * @param {Object} [options={}] Optional Parameters
119601          * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
119602          * @param {string|number} [options.id] Identifier associated with the Feature
119603          * @returns {Feature} a GeoJSON Feature
119604          * @example
119605          * var geometry = {
119606          *   "type": "Point",
119607          *   "coordinates": [110, 50]
119608          * };
119609          *
119610          * var feature = turf.feature(geometry);
119611          *
119612          * //=feature
119613          */
119614
119615         function feature(geom, properties, options) {
119616           if (options === void 0) {
119617             options = {};
119618           }
119619
119620           var feat = {
119621             type: "Feature"
119622           };
119623
119624           if (options.id === 0 || options.id) {
119625             feat.id = options.id;
119626           }
119627
119628           if (options.bbox) {
119629             feat.bbox = options.bbox;
119630           }
119631
119632           feat.properties = properties || {};
119633           feat.geometry = geom;
119634           return feat;
119635         }
119636         /**
119637          * Creates a {@link Polygon} {@link Feature} from an Array of LinearRings.
119638          *
119639          * @name polygon
119640          * @param {Array<Array<Array<number>>>} coordinates an array of LinearRings
119641          * @param {Object} [properties={}] an Object of key-value pairs to add as properties
119642          * @param {Object} [options={}] Optional Parameters
119643          * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
119644          * @param {string|number} [options.id] Identifier associated with the Feature
119645          * @returns {Feature<Polygon>} Polygon Feature
119646          * @example
119647          * var polygon = turf.polygon([[[-5, 52], [-4, 56], [-2, 51], [-7, 54], [-5, 52]]], { name: 'poly1' });
119648          *
119649          * //=polygon
119650          */
119651
119652         function polygon(coordinates, properties, options) {
119653           if (options === void 0) {
119654             options = {};
119655           }
119656
119657           for (var _i = 0, coordinates_1 = coordinates; _i < coordinates_1.length; _i++) {
119658             var ring = coordinates_1[_i];
119659
119660             if (ring.length < 4) {
119661               throw new Error("Each LinearRing of a Polygon must have 4 or more Positions.");
119662             }
119663
119664             for (var j = 0; j < ring[ring.length - 1].length; j++) {
119665               // Check if first point of Polygon contains two numbers
119666               if (ring[ring.length - 1][j] !== ring[0][j]) {
119667                 throw new Error("First and last Position are not equivalent.");
119668               }
119669             }
119670           }
119671
119672           var geom = {
119673             type: "Polygon",
119674             coordinates: coordinates
119675           };
119676           return feature(geom, properties, options);
119677         }
119678         /**
119679          * Creates a {@link LineString} {@link Feature} from an Array of Positions.
119680          *
119681          * @name lineString
119682          * @param {Array<Array<number>>} coordinates an array of Positions
119683          * @param {Object} [properties={}] an Object of key-value pairs to add as properties
119684          * @param {Object} [options={}] Optional Parameters
119685          * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
119686          * @param {string|number} [options.id] Identifier associated with the Feature
119687          * @returns {Feature<LineString>} LineString Feature
119688          * @example
119689          * var linestring1 = turf.lineString([[-24, 63], [-23, 60], [-25, 65], [-20, 69]], {name: 'line 1'});
119690          * var linestring2 = turf.lineString([[-14, 43], [-13, 40], [-15, 45], [-10, 49]], {name: 'line 2'});
119691          *
119692          * //=linestring1
119693          * //=linestring2
119694          */
119695
119696         function lineString(coordinates, properties, options) {
119697           if (options === void 0) {
119698             options = {};
119699           }
119700
119701           if (coordinates.length < 2) {
119702             throw new Error("coordinates must be an array of two or more positions");
119703           }
119704
119705           var geom = {
119706             type: "LineString",
119707             coordinates: coordinates
119708           };
119709           return feature(geom, properties, options);
119710         }
119711         /**
119712          * Creates a {@link Feature<MultiLineString>} based on a
119713          * coordinate array. Properties can be added optionally.
119714          *
119715          * @name multiLineString
119716          * @param {Array<Array<Array<number>>>} coordinates an array of LineStrings
119717          * @param {Object} [properties={}] an Object of key-value pairs to add as properties
119718          * @param {Object} [options={}] Optional Parameters
119719          * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
119720          * @param {string|number} [options.id] Identifier associated with the Feature
119721          * @returns {Feature<MultiLineString>} a MultiLineString feature
119722          * @throws {Error} if no coordinates are passed
119723          * @example
119724          * var multiLine = turf.multiLineString([[[0,0],[10,10]]]);
119725          *
119726          * //=multiLine
119727          */
119728
119729         function multiLineString(coordinates, properties, options) {
119730           if (options === void 0) {
119731             options = {};
119732           }
119733
119734           var geom = {
119735             type: "MultiLineString",
119736             coordinates: coordinates
119737           };
119738           return feature(geom, properties, options);
119739         }
119740         /**
119741          * Creates a {@link Feature<MultiPolygon>} based on a
119742          * coordinate array. Properties can be added optionally.
119743          *
119744          * @name multiPolygon
119745          * @param {Array<Array<Array<Array<number>>>>} coordinates an array of Polygons
119746          * @param {Object} [properties={}] an Object of key-value pairs to add as properties
119747          * @param {Object} [options={}] Optional Parameters
119748          * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
119749          * @param {string|number} [options.id] Identifier associated with the Feature
119750          * @returns {Feature<MultiPolygon>} a multipolygon feature
119751          * @throws {Error} if no coordinates are passed
119752          * @example
119753          * var multiPoly = turf.multiPolygon([[[[0,0],[0,10],[10,10],[10,0],[0,0]]]]);
119754          *
119755          * //=multiPoly
119756          *
119757          */
119758
119759         function multiPolygon(coordinates, properties, options) {
119760           if (options === void 0) {
119761             options = {};
119762           }
119763
119764           var geom = {
119765             type: "MultiPolygon",
119766             coordinates: coordinates
119767           };
119768           return feature(geom, properties, options);
119769         }
119770
119771         /**
119772          * Get Geometry from Feature or Geometry Object
119773          *
119774          * @param {Feature|Geometry} geojson GeoJSON Feature or Geometry Object
119775          * @returns {Geometry|null} GeoJSON Geometry Object
119776          * @throws {Error} if geojson is not a Feature or Geometry Object
119777          * @example
119778          * var point = {
119779          *   "type": "Feature",
119780          *   "properties": {},
119781          *   "geometry": {
119782          *     "type": "Point",
119783          *     "coordinates": [110, 40]
119784          *   }
119785          * }
119786          * var geom = turf.getGeom(point)
119787          * //={"type": "Point", "coordinates": [110, 40]}
119788          */
119789
119790         function getGeom(geojson) {
119791           if (geojson.type === "Feature") {
119792             return geojson.geometry;
119793           }
119794
119795           return geojson;
119796         }
119797
119798         // Cohen-Sutherland line clipping algorithm, adapted to efficiently
119799         // handle polylines rather than just segments
119800         function lineclip(points, bbox, result) {
119801           var len = points.length,
119802               codeA = bitCode(points[0], bbox),
119803               part = [],
119804               i,
119805               codeB,
119806               lastCode;
119807           var a;
119808           var b;
119809           if (!result) result = [];
119810
119811           for (i = 1; i < len; i++) {
119812             a = points[i - 1];
119813             b = points[i];
119814             codeB = lastCode = bitCode(b, bbox);
119815
119816             while (true) {
119817               if (!(codeA | codeB)) {
119818                 // accept
119819                 part.push(a);
119820
119821                 if (codeB !== lastCode) {
119822                   // segment went outside
119823                   part.push(b);
119824
119825                   if (i < len - 1) {
119826                     // start a new line
119827                     result.push(part);
119828                     part = [];
119829                   }
119830                 } else if (i === len - 1) {
119831                   part.push(b);
119832                 }
119833
119834                 break;
119835               } else if (codeA & codeB) {
119836                 // trivial reject
119837                 break;
119838               } else if (codeA) {
119839                 // a outside, intersect with clip edge
119840                 a = intersect(a, b, codeA, bbox);
119841                 codeA = bitCode(a, bbox);
119842               } else {
119843                 // b outside
119844                 b = intersect(a, b, codeB, bbox);
119845                 codeB = bitCode(b, bbox);
119846               }
119847             }
119848
119849             codeA = lastCode;
119850           }
119851
119852           if (part.length) result.push(part);
119853           return result;
119854         } // Sutherland-Hodgeman polygon clipping algorithm
119855
119856         function polygonclip(points, bbox) {
119857           var result, edge, prev, prevInside, i, p, inside; // clip against each side of the clip rectangle
119858
119859           for (edge = 1; edge <= 8; edge *= 2) {
119860             result = [];
119861             prev = points[points.length - 1];
119862             prevInside = !(bitCode(prev, bbox) & edge);
119863
119864             for (i = 0; i < points.length; i++) {
119865               p = points[i];
119866               inside = !(bitCode(p, bbox) & edge); // if segment goes through the clip window, add an intersection
119867
119868               if (inside !== prevInside) result.push(intersect(prev, p, edge, bbox));
119869               if (inside) result.push(p); // add a point if it's inside
119870
119871               prev = p;
119872               prevInside = inside;
119873             }
119874
119875             points = result;
119876             if (!points.length) break;
119877           }
119878
119879           return result;
119880         } // intersect a segment against one of the 4 lines that make up the bbox
119881
119882         function intersect(a, b, edge, bbox) {
119883           return edge & 8 ? [a[0] + (b[0] - a[0]) * (bbox[3] - a[1]) / (b[1] - a[1]), bbox[3]] // top
119884           : edge & 4 ? [a[0] + (b[0] - a[0]) * (bbox[1] - a[1]) / (b[1] - a[1]), bbox[1]] // bottom
119885           : edge & 2 ? [bbox[2], a[1] + (b[1] - a[1]) * (bbox[2] - a[0]) / (b[0] - a[0])] // right
119886           : edge & 1 ? [bbox[0], a[1] + (b[1] - a[1]) * (bbox[0] - a[0]) / (b[0] - a[0])] // left
119887           : null;
119888         } // bit code reflects the point position relative to the bbox:
119889         //         left  mid  right
119890         //    top  1001  1000  1010
119891         //    mid  0001  0000  0010
119892         // bottom  0101  0100  0110
119893
119894
119895         function bitCode(p, bbox) {
119896           var code = 0;
119897           if (p[0] < bbox[0]) code |= 1; // left
119898           else if (p[0] > bbox[2]) code |= 2; // right
119899
119900           if (p[1] < bbox[1]) code |= 4; // bottom
119901           else if (p[1] > bbox[3]) code |= 8; // top
119902
119903           return code;
119904         }
119905
119906         /**
119907          * Takes a {@link Feature} and a bbox and clips the feature to the bbox using
119908          * [lineclip](https://github.com/mapbox/lineclip).
119909          * May result in degenerate edges when clipping Polygons.
119910          *
119911          * @name bboxClip
119912          * @param {Feature<LineString|MultiLineString|Polygon|MultiPolygon>} feature feature to clip to the bbox
119913          * @param {BBox} bbox extent in [minX, minY, maxX, maxY] order
119914          * @returns {Feature<LineString|MultiLineString|Polygon|MultiPolygon>} clipped Feature
119915          * @example
119916          * var bbox = [0, 0, 10, 10];
119917          * var poly = turf.polygon([[[2, 2], [8, 4], [12, 8], [3, 7], [2, 2]]]);
119918          *
119919          * var clipped = turf.bboxClip(poly, bbox);
119920          *
119921          * //addToMap
119922          * var addToMap = [bbox, poly, clipped]
119923          */
119924
119925         function bboxClip(feature, bbox) {
119926           var geom = getGeom(feature);
119927           var type = geom.type;
119928           var properties = feature.type === "Feature" ? feature.properties : {};
119929           var coords = geom.coordinates;
119930
119931           switch (type) {
119932             case "LineString":
119933             case "MultiLineString":
119934               {
119935                 var lines_1 = [];
119936
119937                 if (type === "LineString") {
119938                   coords = [coords];
119939                 }
119940
119941                 coords.forEach(function (line) {
119942                   lineclip(line, bbox, lines_1);
119943                 });
119944
119945                 if (lines_1.length === 1) {
119946                   return lineString(lines_1[0], properties);
119947                 }
119948
119949                 return multiLineString(lines_1, properties);
119950               }
119951
119952             case "Polygon":
119953               return polygon(clipPolygon(coords, bbox), properties);
119954
119955             case "MultiPolygon":
119956               return multiPolygon(coords.map(function (poly) {
119957                 return clipPolygon(poly, bbox);
119958               }), properties);
119959
119960             default:
119961               throw new Error("geometry " + type + " not supported");
119962           }
119963         }
119964
119965         function clipPolygon(rings, bbox) {
119966           var outRings = [];
119967
119968           for (var _i = 0, rings_1 = rings; _i < rings_1.length; _i++) {
119969             var ring = rings_1[_i];
119970             var clipped = polygonclip(ring, bbox);
119971
119972             if (clipped.length > 0) {
119973               if (clipped[0][0] !== clipped[clipped.length - 1][0] || clipped[0][1] !== clipped[clipped.length - 1][1]) {
119974                 clipped.push(clipped[0]);
119975               }
119976
119977               if (clipped.length >= 4) {
119978                 outRings.push(clipped);
119979               }
119980             }
119981           }
119982
119983           return outRings;
119984         }
119985
119986         var tiler = utilTiler().tileSize(512).margin(1);
119987         var dispatch = dispatch$8('loadedData');
119988
119989         var _vtCache;
119990
119991         function abortRequest(controller) {
119992           controller.abort();
119993         }
119994
119995         function vtToGeoJSON(data, tile, mergeCache) {
119996           var vectorTile$1 = new vectorTile.VectorTile(new pbf(data));
119997           var layers = Object.keys(vectorTile$1.layers);
119998
119999           if (!Array.isArray(layers)) {
120000             layers = [layers];
120001           }
120002
120003           var features = [];
120004           layers.forEach(function (layerID) {
120005             var layer = vectorTile$1.layers[layerID];
120006
120007             if (layer) {
120008               for (var i = 0; i < layer.length; i++) {
120009                 var feature = layer.feature(i).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
120010                 var geometry = feature.geometry; // Treat all Polygons as MultiPolygons
120011
120012                 if (geometry.type === 'Polygon') {
120013                   geometry.type = 'MultiPolygon';
120014                   geometry.coordinates = [geometry.coordinates];
120015                 }
120016
120017                 var isClipped = false; // Clip to tile bounds
120018
120019                 if (geometry.type === 'MultiPolygon') {
120020                   var featureClip = bboxClip(feature, tile.extent.rectangle());
120021
120022                   if (!fastDeepEqual(feature.geometry, featureClip.geometry)) {
120023                     // feature = featureClip;
120024                     isClipped = true;
120025                   }
120026
120027                   if (!feature.geometry.coordinates.length) continue; // not actually on this tile
120028
120029                   if (!feature.geometry.coordinates[0].length) continue; // not actually on this tile
120030                 } // Generate some unique IDs and add some metadata
120031
120032
120033                 var featurehash = utilHashcode(fastJsonStableStringify(feature));
120034                 var propertyhash = utilHashcode(fastJsonStableStringify(feature.properties || {}));
120035                 feature.__layerID__ = layerID.replace(/[^_a-zA-Z0-9\-]/g, '_');
120036                 feature.__featurehash__ = featurehash;
120037                 feature.__propertyhash__ = propertyhash;
120038                 features.push(feature); // Clipped Polygons at same zoom with identical properties can get merged
120039
120040                 if (isClipped && geometry.type === 'MultiPolygon') {
120041                   var merged = mergeCache[propertyhash];
120042
120043                   if (merged && merged.length) {
120044                     var other = merged[0];
120045                     var coords = index.union(feature.geometry.coordinates, other.geometry.coordinates);
120046
120047                     if (!coords || !coords.length) {
120048                       continue; // something failed in polygon union
120049                     }
120050
120051                     merged.push(feature);
120052
120053                     for (var j = 0; j < merged.length; j++) {
120054                       // all these features get...
120055                       merged[j].geometry.coordinates = coords; // same coords
120056
120057                       merged[j].__featurehash__ = featurehash; // same hash, so deduplication works
120058                     }
120059                   } else {
120060                     mergeCache[propertyhash] = [feature];
120061                   }
120062                 }
120063               }
120064             }
120065           });
120066           return features;
120067         }
120068
120069         function loadTile(source, tile) {
120070           if (source.loaded[tile.id] || source.inflight[tile.id]) return;
120071           var url = source.template.replace('{x}', tile.xyz[0]).replace('{y}', tile.xyz[1]) // TMS-flipped y coordinate
120072           .replace(/\{[t-]y\}/, Math.pow(2, tile.xyz[2]) - tile.xyz[1] - 1).replace(/\{z(oom)?\}/, tile.xyz[2]).replace(/\{switch:([^}]+)\}/, function (s, r) {
120073             var subdomains = r.split(',');
120074             return subdomains[(tile.xyz[0] + tile.xyz[1]) % subdomains.length];
120075           });
120076           var controller = new AbortController();
120077           source.inflight[tile.id] = controller;
120078           fetch(url, {
120079             signal: controller.signal
120080           }).then(function (response) {
120081             if (!response.ok) {
120082               throw new Error(response.status + ' ' + response.statusText);
120083             }
120084
120085             source.loaded[tile.id] = [];
120086             delete source.inflight[tile.id];
120087             return response.arrayBuffer();
120088           }).then(function (data) {
120089             if (!data) {
120090               throw new Error('No Data');
120091             }
120092
120093             var z = tile.xyz[2];
120094
120095             if (!source.canMerge[z]) {
120096               source.canMerge[z] = {}; // initialize mergeCache
120097             }
120098
120099             source.loaded[tile.id] = vtToGeoJSON(data, tile, source.canMerge[z]);
120100             dispatch.call('loadedData');
120101           })["catch"](function () {
120102             source.loaded[tile.id] = [];
120103             delete source.inflight[tile.id];
120104           });
120105         }
120106
120107         var serviceVectorTile = {
120108           init: function init() {
120109             if (!_vtCache) {
120110               this.reset();
120111             }
120112
120113             this.event = utilRebind(this, dispatch, 'on');
120114           },
120115           reset: function reset() {
120116             for (var sourceID in _vtCache) {
120117               var source = _vtCache[sourceID];
120118
120119               if (source && source.inflight) {
120120                 Object.values(source.inflight).forEach(abortRequest);
120121               }
120122             }
120123
120124             _vtCache = {};
120125           },
120126           addSource: function addSource(sourceID, template) {
120127             _vtCache[sourceID] = {
120128               template: template,
120129               inflight: {},
120130               loaded: {},
120131               canMerge: {}
120132             };
120133             return _vtCache[sourceID];
120134           },
120135           data: function data(sourceID, projection) {
120136             var source = _vtCache[sourceID];
120137             if (!source) return [];
120138             var tiles = tiler.getTiles(projection);
120139             var seen = {};
120140             var results = [];
120141
120142             for (var i = 0; i < tiles.length; i++) {
120143               var features = source.loaded[tiles[i].id];
120144               if (!features || !features.length) continue;
120145
120146               for (var j = 0; j < features.length; j++) {
120147                 var feature = features[j];
120148                 var hash = feature.__featurehash__;
120149                 if (seen[hash]) continue;
120150                 seen[hash] = true; // return a shallow copy, because the hash may change
120151                 // later if this feature gets merged with another
120152
120153                 results.push(Object.assign({}, feature)); // shallow copy
120154               }
120155             }
120156
120157             return results;
120158           },
120159           loadTiles: function loadTiles(sourceID, template, projection) {
120160             var source = _vtCache[sourceID];
120161
120162             if (!source) {
120163               source = this.addSource(sourceID, template);
120164             }
120165
120166             var tiles = tiler.getTiles(projection); // abort inflight requests that are no longer needed
120167
120168             Object.keys(source.inflight).forEach(function (k) {
120169               var wanted = tiles.find(function (tile) {
120170                 return k === tile.id;
120171               });
120172
120173               if (!wanted) {
120174                 abortRequest(source.inflight[k]);
120175                 delete source.inflight[k];
120176               }
120177             });
120178             tiles.forEach(function (tile) {
120179               loadTile(source, tile);
120180             });
120181           },
120182           cache: function cache() {
120183             return _vtCache;
120184           }
120185         };
120186
120187         var apibase = 'https://www.wikidata.org/w/api.php?';
120188         var _wikidataCache = {};
120189         var serviceWikidata = {
120190           init: function init() {},
120191           reset: function reset() {
120192             _wikidataCache = {};
120193           },
120194           // Search for Wikidata items matching the query
120195           itemsForSearchQuery: function itemsForSearchQuery(query, callback) {
120196             if (!query) {
120197               if (callback) callback('No query', {});
120198               return;
120199             }
120200
120201             var lang = this.languagesToQuery()[0];
120202             var url = apibase + utilQsString({
120203               action: 'wbsearchentities',
120204               format: 'json',
120205               formatversion: 2,
120206               search: query,
120207               type: 'item',
120208               // the language to search
120209               language: lang,
120210               // the language for the label and description in the result
120211               uselang: lang,
120212               limit: 10,
120213               origin: '*'
120214             });
120215             d3_json(url).then(function (result) {
120216               if (result && result.error) {
120217                 throw new Error(result.error);
120218               }
120219
120220               if (callback) callback(null, result.search || {});
120221             })["catch"](function (err) {
120222               if (callback) callback(err.message, {});
120223             });
120224           },
120225           // Given a Wikipedia language and article title,
120226           // return an array of corresponding Wikidata entities.
120227           itemsByTitle: function itemsByTitle(lang, title, callback) {
120228             if (!title) {
120229               if (callback) callback('No title', {});
120230               return;
120231             }
120232
120233             lang = lang || 'en';
120234             var url = apibase + utilQsString({
120235               action: 'wbgetentities',
120236               format: 'json',
120237               formatversion: 2,
120238               sites: lang.replace(/-/g, '_') + 'wiki',
120239               titles: title,
120240               languages: 'en',
120241               // shrink response by filtering to one language
120242               origin: '*'
120243             });
120244             d3_json(url).then(function (result) {
120245               if (result && result.error) {
120246                 throw new Error(result.error);
120247               }
120248
120249               if (callback) callback(null, result.entities || {});
120250             })["catch"](function (err) {
120251               if (callback) callback(err.message, {});
120252             });
120253           },
120254           languagesToQuery: function languagesToQuery() {
120255             return _mainLocalizer.localeCodes().map(function (code) {
120256               return code.toLowerCase();
120257             }).filter(function (code) {
120258               // HACK: en-us isn't a wikidata language. We should really be filtering by
120259               // the languages known to be supported by wikidata.
120260               return code !== 'en-us';
120261             });
120262           },
120263           entityByQID: function entityByQID(qid, callback) {
120264             if (!qid) {
120265               callback('No qid', {});
120266               return;
120267             }
120268
120269             if (_wikidataCache[qid]) {
120270               if (callback) callback(null, _wikidataCache[qid]);
120271               return;
120272             }
120273
120274             var langs = this.languagesToQuery();
120275             var url = apibase + utilQsString({
120276               action: 'wbgetentities',
120277               format: 'json',
120278               formatversion: 2,
120279               ids: qid,
120280               props: 'labels|descriptions|claims|sitelinks',
120281               sitefilter: langs.map(function (d) {
120282                 return d + 'wiki';
120283               }).join('|'),
120284               languages: langs.join('|'),
120285               languagefallback: 1,
120286               origin: '*'
120287             });
120288             d3_json(url).then(function (result) {
120289               if (result && result.error) {
120290                 throw new Error(result.error);
120291               }
120292
120293               if (callback) callback(null, result.entities[qid] || {});
120294             })["catch"](function (err) {
120295               if (callback) callback(err.message, {});
120296             });
120297           },
120298           // Pass `params` object of the form:
120299           // {
120300           //   qid: 'string'      // brand wikidata  (e.g. 'Q37158')
120301           // }
120302           //
120303           // Get an result object used to display tag documentation
120304           // {
120305           //   title:        'string',
120306           //   description:  'string',
120307           //   editURL:      'string',
120308           //   imageURL:     'string',
120309           //   wiki:         { title: 'string', text: 'string', url: 'string' }
120310           // }
120311           //
120312           getDocs: function getDocs(params, callback) {
120313             var langs = this.languagesToQuery();
120314             this.entityByQID(params.qid, function (err, entity) {
120315               if (err || !entity) {
120316                 callback(err || 'No entity');
120317                 return;
120318               }
120319
120320               var i;
120321               var description;
120322
120323               for (i in langs) {
120324                 var code = langs[i];
120325
120326                 if (entity.descriptions[code] && entity.descriptions[code].language === code) {
120327                   description = entity.descriptions[code];
120328                   break;
120329                 }
120330               }
120331
120332               if (!description && Object.values(entity.descriptions).length) description = Object.values(entity.descriptions)[0]; // prepare result
120333
120334               var result = {
120335                 title: entity.id,
120336                 description: description ? description.value : '',
120337                 descriptionLocaleCode: description ? description.language : '',
120338                 editURL: 'https://www.wikidata.org/wiki/' + entity.id
120339               }; // add image
120340
120341               if (entity.claims) {
120342                 var imageroot = 'https://commons.wikimedia.org/w/index.php';
120343                 var props = ['P154', 'P18']; // logo image, image
120344
120345                 var prop, image;
120346
120347                 for (i = 0; i < props.length; i++) {
120348                   prop = entity.claims[props[i]];
120349
120350                   if (prop && Object.keys(prop).length > 0) {
120351                     image = prop[Object.keys(prop)[0]].mainsnak.datavalue.value;
120352
120353                     if (image) {
120354                       result.imageURL = imageroot + '?' + utilQsString({
120355                         title: 'Special:Redirect/file/' + image,
120356                         width: 400
120357                       });
120358                       break;
120359                     }
120360                   }
120361                 }
120362               }
120363
120364               if (entity.sitelinks) {
120365                 var englishLocale = _mainLocalizer.languageCode().toLowerCase() === 'en'; // must be one of these that we requested..
120366
120367                 for (i = 0; i < langs.length; i++) {
120368                   // check each, in order of preference
120369                   var w = langs[i] + 'wiki';
120370
120371                   if (entity.sitelinks[w]) {
120372                     var title = entity.sitelinks[w].title;
120373                     var tKey = 'inspector.wiki_reference';
120374
120375                     if (!englishLocale && langs[i] === 'en') {
120376                       // user's locale isn't English but
120377                       tKey = 'inspector.wiki_en_reference'; // we are sending them to enwiki anyway..
120378                     }
120379
120380                     result.wiki = {
120381                       title: title,
120382                       text: tKey,
120383                       url: 'https://' + langs[i] + '.wikipedia.org/wiki/' + title.replace(/ /g, '_')
120384                     };
120385                     break;
120386                   }
120387                 }
120388               }
120389
120390               callback(null, result);
120391             });
120392           }
120393         };
120394
120395         var endpoint = 'https://en.wikipedia.org/w/api.php?';
120396         var serviceWikipedia = {
120397           init: function init() {},
120398           reset: function reset() {},
120399           search: function search(lang, query, callback) {
120400             if (!query) {
120401               if (callback) callback('No Query', []);
120402               return;
120403             }
120404
120405             lang = lang || 'en';
120406             var url = endpoint.replace('en', lang) + utilQsString({
120407               action: 'query',
120408               list: 'search',
120409               srlimit: '10',
120410               srinfo: 'suggestion',
120411               format: 'json',
120412               origin: '*',
120413               srsearch: query
120414             });
120415             d3_json(url).then(function (result) {
120416               if (result && result.error) {
120417                 throw new Error(result.error);
120418               } else if (!result || !result.query || !result.query.search) {
120419                 throw new Error('No Results');
120420               }
120421
120422               if (callback) {
120423                 var titles = result.query.search.map(function (d) {
120424                   return d.title;
120425                 });
120426                 callback(null, titles);
120427               }
120428             })["catch"](function (err) {
120429               if (callback) callback(err, []);
120430             });
120431           },
120432           suggestions: function suggestions(lang, query, callback) {
120433             if (!query) {
120434               if (callback) callback('', []);
120435               return;
120436             }
120437
120438             lang = lang || 'en';
120439             var url = endpoint.replace('en', lang) + utilQsString({
120440               action: 'opensearch',
120441               namespace: 0,
120442               suggest: '',
120443               format: 'json',
120444               origin: '*',
120445               search: query
120446             });
120447             d3_json(url).then(function (result) {
120448               if (result && result.error) {
120449                 throw new Error(result.error);
120450               } else if (!result || result.length < 2) {
120451                 throw new Error('No Results');
120452               }
120453
120454               if (callback) callback(null, result[1] || []);
120455             })["catch"](function (err) {
120456               if (callback) callback(err.message, []);
120457             });
120458           },
120459           translations: function translations(lang, title, callback) {
120460             if (!title) {
120461               if (callback) callback('No Title');
120462               return;
120463             }
120464
120465             var url = endpoint.replace('en', lang) + utilQsString({
120466               action: 'query',
120467               prop: 'langlinks',
120468               format: 'json',
120469               origin: '*',
120470               lllimit: 500,
120471               titles: title
120472             });
120473             d3_json(url).then(function (result) {
120474               if (result && result.error) {
120475                 throw new Error(result.error);
120476               } else if (!result || !result.query || !result.query.pages) {
120477                 throw new Error('No Results');
120478               }
120479
120480               if (callback) {
120481                 var list = result.query.pages[Object.keys(result.query.pages)[0]];
120482                 var translations = {};
120483
120484                 if (list && list.langlinks) {
120485                   list.langlinks.forEach(function (d) {
120486                     translations[d.lang] = d['*'];
120487                   });
120488                 }
120489
120490                 callback(null, translations);
120491               }
120492             })["catch"](function (err) {
120493               if (callback) callback(err.message);
120494             });
120495           }
120496         };
120497
120498         var services = {
120499           geocoder: serviceNominatim,
120500           keepRight: serviceKeepRight,
120501           improveOSM: serviceImproveOSM,
120502           osmose: serviceOsmose,
120503           mapillary: serviceMapillary,
120504           nsi: serviceNsi,
120505           kartaview: serviceKartaview,
120506           osm: serviceOsm,
120507           osmWikibase: serviceOsmWikibase,
120508           maprules: serviceMapRules,
120509           streetside: serviceStreetside,
120510           taginfo: serviceTaginfo,
120511           vectorTile: serviceVectorTile,
120512           wikidata: serviceWikidata,
120513           wikipedia: serviceWikipedia
120514         };
120515
120516         function modeDragNote(context) {
120517           var mode = {
120518             id: 'drag-note',
120519             button: 'browse'
120520           };
120521           var edit = behaviorEdit(context);
120522
120523           var _nudgeInterval;
120524
120525           var _lastLoc;
120526
120527           var _note; // most current note.. dragged note may have stale datum.
120528
120529
120530           function startNudge(d3_event, nudge) {
120531             if (_nudgeInterval) window.clearInterval(_nudgeInterval);
120532             _nudgeInterval = window.setInterval(function () {
120533               context.map().pan(nudge);
120534               doMove(d3_event, nudge);
120535             }, 50);
120536           }
120537
120538           function stopNudge() {
120539             if (_nudgeInterval) {
120540               window.clearInterval(_nudgeInterval);
120541               _nudgeInterval = null;
120542             }
120543           }
120544
120545           function origin(note) {
120546             return context.projection(note.loc);
120547           }
120548
120549           function start(d3_event, note) {
120550             _note = note;
120551             var osm = services.osm;
120552
120553             if (osm) {
120554               // Get latest note from cache.. The marker may have a stale datum bound to it
120555               // and dragging it around can sometimes delete the users note comment.
120556               _note = osm.getNote(_note.id);
120557             }
120558
120559             context.surface().selectAll('.note-' + _note.id).classed('active', true);
120560             context.perform(actionNoop());
120561             context.enter(mode);
120562             context.selectedNoteID(_note.id);
120563           }
120564
120565           function move(d3_event, entity, point) {
120566             d3_event.stopPropagation();
120567             _lastLoc = context.projection.invert(point);
120568             doMove(d3_event);
120569             var nudge = geoViewportEdge(point, context.map().dimensions());
120570
120571             if (nudge) {
120572               startNudge(d3_event, nudge);
120573             } else {
120574               stopNudge();
120575             }
120576           }
120577
120578           function doMove(d3_event, nudge) {
120579             nudge = nudge || [0, 0];
120580             var currPoint = d3_event && d3_event.point || context.projection(_lastLoc);
120581             var currMouse = geoVecSubtract(currPoint, nudge);
120582             var loc = context.projection.invert(currMouse);
120583             _note = _note.move(loc);
120584             var osm = services.osm;
120585
120586             if (osm) {
120587               osm.replaceNote(_note); // update note cache
120588             }
120589
120590             context.replace(actionNoop()); // trigger redraw
120591           }
120592
120593           function end() {
120594             context.replace(actionNoop()); // trigger redraw
120595
120596             context.selectedNoteID(_note.id).enter(modeSelectNote(context, _note.id));
120597           }
120598
120599           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);
120600
120601           mode.enter = function () {
120602             context.install(edit);
120603           };
120604
120605           mode.exit = function () {
120606             context.ui().sidebar.hover.cancel();
120607             context.uninstall(edit);
120608             context.surface().selectAll('.active').classed('active', false);
120609             stopNudge();
120610           };
120611
120612           mode.behavior = drag;
120613           return mode;
120614         }
120615
120616         function modeSelectData(context, selectedDatum) {
120617           var mode = {
120618             id: 'select-data',
120619             button: 'browse'
120620           };
120621           var keybinding = utilKeybinding('select-data');
120622           var dataEditor = uiDataEditor(context);
120623           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
120624
120625           function selectData(d3_event, drawn) {
120626             var selection = context.surface().selectAll('.layer-mapdata .data' + selectedDatum.__featurehash__);
120627
120628             if (selection.empty()) {
120629               // Return to browse mode if selected DOM elements have
120630               // disappeared because the user moved them out of view..
120631               var source = d3_event && d3_event.type === 'zoom' && d3_event.sourceEvent;
120632
120633               if (drawn && source && (source.type === 'pointermove' || source.type === 'mousemove' || source.type === 'touchmove')) {
120634                 context.enter(modeBrowse(context));
120635               }
120636             } else {
120637               selection.classed('selected', true);
120638             }
120639           }
120640
120641           function esc() {
120642             if (context.container().select('.combobox').size()) return;
120643             context.enter(modeBrowse(context));
120644           }
120645
120646           mode.zoomToSelected = function () {
120647             var extent = geoExtent(d3_geoBounds(selectedDatum));
120648             context.map().centerZoomEase(extent.center(), context.map().trimmedExtentZoom(extent));
120649           };
120650
120651           mode.enter = function () {
120652             behaviors.forEach(context.install);
120653             keybinding.on(_t('inspector.zoom_to.key'), mode.zoomToSelected).on('⎋', esc, true);
120654             select(document).call(keybinding);
120655             selectData();
120656             var sidebar = context.ui().sidebar;
120657             sidebar.show(dataEditor.datum(selectedDatum)); // expand the sidebar, avoid obscuring the data if needed
120658
120659             var extent = geoExtent(d3_geoBounds(selectedDatum));
120660             sidebar.expand(sidebar.intersects(extent));
120661             context.map().on('drawn.select-data', selectData);
120662           };
120663
120664           mode.exit = function () {
120665             behaviors.forEach(context.uninstall);
120666             select(document).call(keybinding.unbind);
120667             context.surface().selectAll('.layer-mapdata .selected').classed('selected hover', false);
120668             context.map().on('drawn.select-data', null);
120669             context.ui().sidebar.hide();
120670           };
120671
120672           return mode;
120673         }
120674
120675         function behaviorSelect(context) {
120676           var _tolerancePx = 4; // see also behaviorDrag
120677
120678           var _lastMouseEvent = null;
120679           var _showMenu = false;
120680           var _downPointers = {};
120681           var _longPressTimeout = null;
120682           var _lastInteractionType = null; // the id of the down pointer that's enabling multiselection while down
120683
120684           var _multiselectionPointerId = null; // use pointer events on supported platforms; fallback to mouse events
120685
120686           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
120687
120688           function keydown(d3_event) {
120689             if (d3_event.keyCode === 32) {
120690               // don't react to spacebar events during text input
120691               var activeNode = document.activeElement;
120692               if (activeNode && new Set(['INPUT', 'TEXTAREA']).has(activeNode.nodeName)) return;
120693             }
120694
120695             if (d3_event.keyCode === 93 || // context menu key
120696             d3_event.keyCode === 32) {
120697               // spacebar
120698               d3_event.preventDefault();
120699             }
120700
120701             if (d3_event.repeat) return; // ignore repeated events for held keys
120702             // if any key is pressed the user is probably doing something other than long-pressing
120703
120704             cancelLongPress();
120705
120706             if (d3_event.shiftKey) {
120707               context.surface().classed('behavior-multiselect', true);
120708             }
120709
120710             if (d3_event.keyCode === 32) {
120711               // spacebar
120712               if (!_downPointers.spacebar && _lastMouseEvent) {
120713                 cancelLongPress();
120714                 _longPressTimeout = window.setTimeout(didLongPress, 500, 'spacebar', 'spacebar');
120715                 _downPointers.spacebar = {
120716                   firstEvent: _lastMouseEvent,
120717                   lastEvent: _lastMouseEvent
120718                 };
120719               }
120720             }
120721           }
120722
120723           function keyup(d3_event) {
120724             cancelLongPress();
120725
120726             if (!d3_event.shiftKey) {
120727               context.surface().classed('behavior-multiselect', false);
120728             }
120729
120730             if (d3_event.keyCode === 93) {
120731               // context menu key
120732               d3_event.preventDefault();
120733               _lastInteractionType = 'menukey';
120734               contextmenu(d3_event);
120735             } else if (d3_event.keyCode === 32) {
120736               // spacebar
120737               var pointer = _downPointers.spacebar;
120738
120739               if (pointer) {
120740                 delete _downPointers.spacebar;
120741                 if (pointer.done) return;
120742                 d3_event.preventDefault();
120743                 _lastInteractionType = 'spacebar';
120744                 click(pointer.firstEvent, pointer.lastEvent, 'spacebar');
120745               }
120746             }
120747           }
120748
120749           function pointerdown(d3_event) {
120750             var id = (d3_event.pointerId || 'mouse').toString();
120751             cancelLongPress();
120752             if (d3_event.buttons && d3_event.buttons !== 1) return;
120753             context.ui().closeEditMenu();
120754             _longPressTimeout = window.setTimeout(didLongPress, 500, id, 'longdown-' + (d3_event.pointerType || 'mouse'));
120755             _downPointers[id] = {
120756               firstEvent: d3_event,
120757               lastEvent: d3_event
120758             };
120759           }
120760
120761           function didLongPress(id, interactionType) {
120762             var pointer = _downPointers[id];
120763             if (!pointer) return;
120764
120765             for (var i in _downPointers) {
120766               // don't allow this or any currently down pointer to trigger another click
120767               _downPointers[i].done = true;
120768             } // treat long presses like right-clicks
120769
120770
120771             _longPressTimeout = null;
120772             _lastInteractionType = interactionType;
120773             _showMenu = true;
120774             click(pointer.firstEvent, pointer.lastEvent, id);
120775           }
120776
120777           function pointermove(d3_event) {
120778             var id = (d3_event.pointerId || 'mouse').toString();
120779
120780             if (_downPointers[id]) {
120781               _downPointers[id].lastEvent = d3_event;
120782             }
120783
120784             if (!d3_event.pointerType || d3_event.pointerType === 'mouse') {
120785               _lastMouseEvent = d3_event;
120786
120787               if (_downPointers.spacebar) {
120788                 _downPointers.spacebar.lastEvent = d3_event;
120789               }
120790             }
120791           }
120792
120793           function pointerup(d3_event) {
120794             var id = (d3_event.pointerId || 'mouse').toString();
120795             var pointer = _downPointers[id];
120796             if (!pointer) return;
120797             delete _downPointers[id];
120798
120799             if (_multiselectionPointerId === id) {
120800               _multiselectionPointerId = null;
120801             }
120802
120803             if (pointer.done) return;
120804             click(pointer.firstEvent, d3_event, id);
120805           }
120806
120807           function pointercancel(d3_event) {
120808             var id = (d3_event.pointerId || 'mouse').toString();
120809             if (!_downPointers[id]) return;
120810             delete _downPointers[id];
120811
120812             if (_multiselectionPointerId === id) {
120813               _multiselectionPointerId = null;
120814             }
120815           }
120816
120817           function contextmenu(d3_event) {
120818             d3_event.preventDefault();
120819
120820             if (!+d3_event.clientX && !+d3_event.clientY) {
120821               if (_lastMouseEvent) {
120822                 d3_event.sourceEvent = _lastMouseEvent;
120823               } else {
120824                 return;
120825               }
120826             } else {
120827               _lastMouseEvent = d3_event;
120828               _lastInteractionType = 'rightclick';
120829             }
120830
120831             _showMenu = true;
120832             click(d3_event, d3_event);
120833           }
120834
120835           function click(firstEvent, lastEvent, pointerId) {
120836             cancelLongPress();
120837             var mapNode = context.container().select('.main-map').node(); // Use the `main-map` coordinate system since the surface and supersurface
120838             // are transformed when drag-panning.
120839
120840             var pointGetter = utilFastMouse(mapNode);
120841             var p1 = pointGetter(firstEvent);
120842             var p2 = pointGetter(lastEvent);
120843             var dist = geoVecLength(p1, p2);
120844
120845             if (dist > _tolerancePx || !mapContains(lastEvent)) {
120846               resetProperties();
120847               return;
120848             }
120849
120850             var targetDatum = lastEvent.target.__data__;
120851             var multiselectEntityId;
120852
120853             if (!_multiselectionPointerId) {
120854               // If a different pointer than the one triggering this click is down on a
120855               // feature, treat this and all future clicks as multiselection until that
120856               // pointer is raised.
120857               var selectPointerInfo = pointerDownOnSelection(pointerId);
120858
120859               if (selectPointerInfo) {
120860                 _multiselectionPointerId = selectPointerInfo.pointerId; // if the other feature isn't selected yet, make sure we select it
120861
120862                 multiselectEntityId = !selectPointerInfo.selected && selectPointerInfo.entityId;
120863                 _downPointers[selectPointerInfo.pointerId].done = true;
120864               }
120865             } // support multiselect if data is already selected
120866
120867
120868             var isMultiselect = context.mode().id === 'select' && ( // and shift key is down
120869             lastEvent && lastEvent.shiftKey || // or we're lasso-selecting
120870             context.surface().select('.lasso').node() || // or a pointer is down over a selected feature
120871             _multiselectionPointerId && !multiselectEntityId);
120872
120873             processClick(targetDatum, isMultiselect, p2, multiselectEntityId);
120874
120875             function mapContains(event) {
120876               var rect = mapNode.getBoundingClientRect();
120877               return event.clientX >= rect.left && event.clientX <= rect.right && event.clientY >= rect.top && event.clientY <= rect.bottom;
120878             }
120879
120880             function pointerDownOnSelection(skipPointerId) {
120881               var mode = context.mode();
120882               var selectedIDs = mode.id === 'select' ? mode.selectedIDs() : [];
120883
120884               for (var pointerId in _downPointers) {
120885                 if (pointerId === 'spacebar' || pointerId === skipPointerId) continue;
120886                 var pointerInfo = _downPointers[pointerId];
120887                 var p1 = pointGetter(pointerInfo.firstEvent);
120888                 var p2 = pointGetter(pointerInfo.lastEvent);
120889                 if (geoVecLength(p1, p2) > _tolerancePx) continue;
120890                 var datum = pointerInfo.firstEvent.target.__data__;
120891                 var entity = datum && datum.properties && datum.properties.entity || datum;
120892
120893                 if (context.graph().hasEntity(entity.id)) {
120894                   return {
120895                     pointerId: pointerId,
120896                     entityId: entity.id,
120897                     selected: selectedIDs.indexOf(entity.id) !== -1
120898                   };
120899                 }
120900               }
120901
120902               return null;
120903             }
120904           }
120905
120906           function processClick(datum, isMultiselect, point, alsoSelectId) {
120907             var mode = context.mode();
120908             var showMenu = _showMenu;
120909             var interactionType = _lastInteractionType;
120910             var entity = datum && datum.properties && datum.properties.entity;
120911             if (entity) datum = entity;
120912
120913             if (datum && datum.type === 'midpoint') {
120914               // treat targeting midpoints as if targeting the parent way
120915               datum = datum.parents[0];
120916             }
120917
120918             var newMode;
120919
120920             if (datum instanceof osmEntity) {
120921               // targeting an entity
120922               var selectedIDs = context.selectedIDs();
120923               context.selectedNoteID(null);
120924               context.selectedErrorID(null);
120925
120926               if (!isMultiselect) {
120927                 // don't change the selection if we're toggling the menu atop a multiselection
120928                 if (!showMenu || selectedIDs.length <= 1 || selectedIDs.indexOf(datum.id) === -1) {
120929                   if (alsoSelectId === datum.id) alsoSelectId = null;
120930                   selectedIDs = (alsoSelectId ? [alsoSelectId] : []).concat([datum.id]); // always enter modeSelect even if the entity is already
120931                   // selected since listeners may expect `context.enter` events,
120932                   // e.g. in the walkthrough
120933
120934                   newMode = mode.id === 'select' ? mode.selectedIDs(selectedIDs) : modeSelect(context, selectedIDs).selectBehavior(behavior);
120935                   context.enter(newMode);
120936                 }
120937               } else {
120938                 if (selectedIDs.indexOf(datum.id) !== -1) {
120939                   // clicked entity is already in the selectedIDs list..
120940                   if (!showMenu) {
120941                     // deselect clicked entity, then reenter select mode or return to browse mode..
120942                     selectedIDs = selectedIDs.filter(function (id) {
120943                       return id !== datum.id;
120944                     });
120945                     newMode = selectedIDs.length ? mode.selectedIDs(selectedIDs) : modeBrowse(context).selectBehavior(behavior);
120946                     context.enter(newMode);
120947                   }
120948                 } else {
120949                   // clicked entity is not in the selected list, add it..
120950                   selectedIDs = selectedIDs.concat([datum.id]);
120951                   newMode = mode.selectedIDs(selectedIDs);
120952                   context.enter(newMode);
120953                 }
120954               }
120955             } else if (datum && datum.__featurehash__ && !isMultiselect) {
120956               // targeting custom data
120957               context.selectedNoteID(null).enter(modeSelectData(context, datum));
120958             } else if (datum instanceof osmNote && !isMultiselect) {
120959               // targeting a note
120960               context.selectedNoteID(datum.id).enter(modeSelectNote(context, datum.id));
120961             } else if (datum instanceof QAItem & !isMultiselect) {
120962               // targeting an external QA issue
120963               context.selectedErrorID(datum.id).enter(modeSelectError(context, datum.id, datum.service));
120964             } else {
120965               // targeting nothing
120966               context.selectedNoteID(null);
120967               context.selectedErrorID(null);
120968
120969               if (!isMultiselect && mode.id !== 'browse') {
120970                 context.enter(modeBrowse(context));
120971               }
120972             }
120973
120974             context.ui().closeEditMenu(); // always request to show the edit menu in case the mode needs it
120975
120976             if (showMenu) context.ui().showEditMenu(point, interactionType);
120977             resetProperties();
120978           }
120979
120980           function cancelLongPress() {
120981             if (_longPressTimeout) window.clearTimeout(_longPressTimeout);
120982             _longPressTimeout = null;
120983           }
120984
120985           function resetProperties() {
120986             cancelLongPress();
120987             _showMenu = false;
120988             _lastInteractionType = null; // don't reset _lastMouseEvent since it might still be useful
120989           }
120990
120991           function behavior(selection) {
120992             resetProperties();
120993             _lastMouseEvent = context.map().lastPointerEvent();
120994             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) {
120995               // Edge and IE really like to show the contextmenu on the
120996               // menubar when user presses a keyboard menu button
120997               // even after we've already preventdefaulted the key event.
120998               var e = d3_event;
120999
121000               if (+e.clientX === 0 && +e.clientY === 0) {
121001                 d3_event.preventDefault();
121002               }
121003             });
121004             selection.on(_pointerPrefix + 'down.select', pointerdown).on('contextmenu.select', contextmenu);
121005             /*if (d3_event && d3_event.shiftKey) {
121006                 context.surface()
121007                     .classed('behavior-multiselect', true);
121008             }*/
121009           }
121010
121011           behavior.off = function (selection) {
121012             cancelLongPress();
121013             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);
121014             selection.on(_pointerPrefix + 'down.select', null).on('contextmenu.select', null);
121015             context.surface().classed('behavior-multiselect', false);
121016           };
121017
121018           return behavior;
121019         }
121020
121021         function operationContinue(context, selectedIDs) {
121022           var _entities = selectedIDs.map(function (id) {
121023             return context.graph().entity(id);
121024           });
121025
121026           var _geometries = Object.assign({
121027             line: [],
121028             vertex: []
121029           }, utilArrayGroupBy(_entities, function (entity) {
121030             return entity.geometry(context.graph());
121031           }));
121032
121033           var _vertex = _geometries.vertex.length && _geometries.vertex[0];
121034
121035           function candidateWays() {
121036             return _vertex ? context.graph().parentWays(_vertex).filter(function (parent) {
121037               return parent.geometry(context.graph()) === 'line' && !parent.isClosed() && parent.affix(_vertex.id) && (_geometries.line.length === 0 || _geometries.line[0] === parent);
121038             }) : [];
121039           }
121040
121041           var _candidates = candidateWays();
121042
121043           var operation = function operation() {
121044             var candidate = _candidates[0];
121045             context.enter(modeDrawLine(context, candidate.id, context.graph(), 'line', candidate.affix(_vertex.id), true));
121046           };
121047
121048           operation.relatedEntityIds = function () {
121049             return _candidates.length ? [_candidates[0].id] : [];
121050           };
121051
121052           operation.available = function () {
121053             return _geometries.vertex.length === 1 && _geometries.line.length <= 1 && !context.features().hasHiddenConnections(_vertex, context.graph());
121054           };
121055
121056           operation.disabled = function () {
121057             if (_candidates.length === 0) {
121058               return 'not_eligible';
121059             } else if (_candidates.length > 1) {
121060               return 'multiple';
121061             }
121062
121063             return false;
121064           };
121065
121066           operation.tooltip = function () {
121067             var disable = operation.disabled();
121068             return disable ? _t('operations.continue.' + disable) : _t('operations.continue.description');
121069           };
121070
121071           operation.annotation = function () {
121072             return _t('operations.continue.annotation.line');
121073           };
121074
121075           operation.id = 'continue';
121076           operation.keys = [_t('operations.continue.key')];
121077           operation.title = _t('operations.continue.title');
121078           operation.behavior = behaviorOperation(context).which(operation);
121079           return operation;
121080         }
121081
121082         function operationCopy(context, selectedIDs) {
121083           function getFilteredIdsToCopy() {
121084             return selectedIDs.filter(function (selectedID) {
121085               var entity = context.graph().hasEntity(selectedID); // don't copy untagged vertices separately from ways
121086
121087               return entity.hasInterestingTags() || entity.geometry(context.graph()) !== 'vertex';
121088             });
121089           }
121090
121091           var operation = function operation() {
121092             var graph = context.graph();
121093             var selected = groupEntities(getFilteredIdsToCopy(), graph);
121094             var canCopy = [];
121095             var skip = {};
121096             var entity;
121097             var i;
121098
121099             for (i = 0; i < selected.relation.length; i++) {
121100               entity = selected.relation[i];
121101
121102               if (!skip[entity.id] && entity.isComplete(graph)) {
121103                 canCopy.push(entity.id);
121104                 skip = getDescendants(entity.id, graph, skip);
121105               }
121106             }
121107
121108             for (i = 0; i < selected.way.length; i++) {
121109               entity = selected.way[i];
121110
121111               if (!skip[entity.id]) {
121112                 canCopy.push(entity.id);
121113                 skip = getDescendants(entity.id, graph, skip);
121114               }
121115             }
121116
121117             for (i = 0; i < selected.node.length; i++) {
121118               entity = selected.node[i];
121119
121120               if (!skip[entity.id]) {
121121                 canCopy.push(entity.id);
121122               }
121123             }
121124
121125             context.copyIDs(canCopy);
121126
121127             if (_point && (canCopy.length !== 1 || graph.entity(canCopy[0]).type !== 'node')) {
121128               // store the anchor coordinates if copying more than a single node
121129               context.copyLonLat(context.projection.invert(_point));
121130             } else {
121131               context.copyLonLat(null);
121132             }
121133           };
121134
121135           function groupEntities(ids, graph) {
121136             var entities = ids.map(function (id) {
121137               return graph.entity(id);
121138             });
121139             return Object.assign({
121140               relation: [],
121141               way: [],
121142               node: []
121143             }, utilArrayGroupBy(entities, 'type'));
121144           }
121145
121146           function getDescendants(id, graph, descendants) {
121147             var entity = graph.entity(id);
121148             var children;
121149             descendants = descendants || {};
121150
121151             if (entity.type === 'relation') {
121152               children = entity.members.map(function (m) {
121153                 return m.id;
121154               });
121155             } else if (entity.type === 'way') {
121156               children = entity.nodes;
121157             } else {
121158               children = [];
121159             }
121160
121161             for (var i = 0; i < children.length; i++) {
121162               if (!descendants[children[i]]) {
121163                 descendants[children[i]] = true;
121164                 descendants = getDescendants(children[i], graph, descendants);
121165               }
121166             }
121167
121168             return descendants;
121169           }
121170
121171           operation.available = function () {
121172             return getFilteredIdsToCopy().length > 0;
121173           };
121174
121175           operation.disabled = function () {
121176             var extent = utilTotalExtent(getFilteredIdsToCopy(), context.graph());
121177
121178             if (extent.percentContainedIn(context.map().extent()) < 0.8) {
121179               return 'too_large';
121180             }
121181
121182             return false;
121183           };
121184
121185           operation.availableForKeypress = function () {
121186             var selection = window.getSelection && window.getSelection(); // if the user has text selected then let them copy that, not the selected feature
121187
121188             return !selection || !selection.toString();
121189           };
121190
121191           operation.tooltip = function () {
121192             var disable = operation.disabled();
121193             return disable ? _t('operations.copy.' + disable, {
121194               n: selectedIDs.length
121195             }) : _t('operations.copy.description', {
121196               n: selectedIDs.length
121197             });
121198           };
121199
121200           operation.annotation = function () {
121201             return _t('operations.copy.annotation', {
121202               n: selectedIDs.length
121203             });
121204           };
121205
121206           var _point;
121207
121208           operation.point = function (val) {
121209             _point = val;
121210             return operation;
121211           };
121212
121213           operation.id = 'copy';
121214           operation.keys = [uiCmd('⌘C')];
121215           operation.title = _t('operations.copy.title');
121216           operation.behavior = behaviorOperation(context).which(operation);
121217           return operation;
121218         }
121219
121220         function operationDisconnect(context, selectedIDs) {
121221           var _vertexIDs = [];
121222           var _wayIDs = [];
121223           var _otherIDs = [];
121224           var _actions = [];
121225           selectedIDs.forEach(function (id) {
121226             var entity = context.entity(id);
121227
121228             if (entity.type === 'way') {
121229               _wayIDs.push(id);
121230             } else if (entity.geometry(context.graph()) === 'vertex') {
121231               _vertexIDs.push(id);
121232             } else {
121233               _otherIDs.push(id);
121234             }
121235           });
121236
121237           var _coords,
121238               _descriptionID = '',
121239               _annotationID = 'features';
121240
121241           var _disconnectingVertexIds = [];
121242           var _disconnectingWayIds = [];
121243
121244           if (_vertexIDs.length > 0) {
121245             // At the selected vertices, disconnect the selected ways, if any, else
121246             // disconnect all connected ways
121247             _disconnectingVertexIds = _vertexIDs;
121248
121249             _vertexIDs.forEach(function (vertexID) {
121250               var action = actionDisconnect(vertexID);
121251
121252               if (_wayIDs.length > 0) {
121253                 var waysIDsForVertex = _wayIDs.filter(function (wayID) {
121254                   var way = context.entity(wayID);
121255                   return way.nodes.indexOf(vertexID) !== -1;
121256                 });
121257
121258                 action.limitWays(waysIDsForVertex);
121259               }
121260
121261               _actions.push(action);
121262
121263               _disconnectingWayIds = _disconnectingWayIds.concat(context.graph().parentWays(context.graph().entity(vertexID)).map(function (d) {
121264                 return d.id;
121265               }));
121266             });
121267
121268             _disconnectingWayIds = utilArrayUniq(_disconnectingWayIds).filter(function (id) {
121269               return _wayIDs.indexOf(id) === -1;
121270             });
121271             _descriptionID += _actions.length === 1 ? 'single_point.' : 'multiple_points.';
121272
121273             if (_wayIDs.length === 1) {
121274               _descriptionID += 'single_way.' + context.graph().geometry(_wayIDs[0]);
121275             } else {
121276               _descriptionID += _wayIDs.length === 0 ? 'no_ways' : 'multiple_ways';
121277             }
121278           } else if (_wayIDs.length > 0) {
121279             // Disconnect the selected ways from each other, if they're connected,
121280             // else disconnect them from all connected ways
121281             var ways = _wayIDs.map(function (id) {
121282               return context.entity(id);
121283             });
121284
121285             var nodes = utilGetAllNodes(_wayIDs, context.graph());
121286             _coords = nodes.map(function (n) {
121287               return n.loc;
121288             }); // actions for connected nodes shared by at least two selected ways
121289
121290             var sharedActions = [];
121291             var sharedNodes = []; // actions for connected nodes
121292
121293             var unsharedActions = [];
121294             var unsharedNodes = [];
121295             nodes.forEach(function (node) {
121296               var action = actionDisconnect(node.id).limitWays(_wayIDs);
121297
121298               if (action.disabled(context.graph()) !== 'not_connected') {
121299                 var count = 0;
121300
121301                 for (var i in ways) {
121302                   var way = ways[i];
121303
121304                   if (way.nodes.indexOf(node.id) !== -1) {
121305                     count += 1;
121306                   }
121307
121308                   if (count > 1) break;
121309                 }
121310
121311                 if (count > 1) {
121312                   sharedActions.push(action);
121313                   sharedNodes.push(node);
121314                 } else {
121315                   unsharedActions.push(action);
121316                   unsharedNodes.push(node);
121317                 }
121318               }
121319             });
121320             _descriptionID += 'no_points.';
121321             _descriptionID += _wayIDs.length === 1 ? 'single_way.' : 'multiple_ways.';
121322
121323             if (sharedActions.length) {
121324               // if any nodes are shared, only disconnect the selected ways from each other
121325               _actions = sharedActions;
121326               _disconnectingVertexIds = sharedNodes.map(function (node) {
121327                 return node.id;
121328               });
121329               _descriptionID += 'conjoined';
121330               _annotationID = 'from_each_other';
121331             } else {
121332               // if no nodes are shared, disconnect the selected ways from all connected ways
121333               _actions = unsharedActions;
121334               _disconnectingVertexIds = unsharedNodes.map(function (node) {
121335                 return node.id;
121336               });
121337
121338               if (_wayIDs.length === 1) {
121339                 _descriptionID += context.graph().geometry(_wayIDs[0]);
121340               } else {
121341                 _descriptionID += 'separate';
121342               }
121343             }
121344           }
121345
121346           var _extent = utilTotalExtent(_disconnectingVertexIds, context.graph());
121347
121348           var operation = function operation() {
121349             context.perform(function (graph) {
121350               return _actions.reduce(function (graph, action) {
121351                 return action(graph);
121352               }, graph);
121353             }, operation.annotation());
121354             context.validator().validate();
121355           };
121356
121357           operation.relatedEntityIds = function () {
121358             if (_vertexIDs.length) {
121359               return _disconnectingWayIds;
121360             }
121361
121362             return _disconnectingVertexIds;
121363           };
121364
121365           operation.available = function () {
121366             if (_actions.length === 0) return false;
121367             if (_otherIDs.length !== 0) return false;
121368             if (_vertexIDs.length !== 0 && _wayIDs.length !== 0 && !_wayIDs.every(function (wayID) {
121369               return _vertexIDs.some(function (vertexID) {
121370                 var way = context.entity(wayID);
121371                 return way.nodes.indexOf(vertexID) !== -1;
121372               });
121373             })) return false;
121374             return true;
121375           };
121376
121377           operation.disabled = function () {
121378             var reason;
121379
121380             for (var actionIndex in _actions) {
121381               reason = _actions[actionIndex].disabled(context.graph());
121382               if (reason) return reason;
121383             }
121384
121385             if (_extent && _extent.percentContainedIn(context.map().extent()) < 0.8) {
121386               return 'too_large.' + ((_vertexIDs.length ? _vertexIDs : _wayIDs).length === 1 ? 'single' : 'multiple');
121387             } else if (_coords && someMissing()) {
121388               return 'not_downloaded';
121389             } else if (selectedIDs.some(context.hasHiddenConnections)) {
121390               return 'connected_to_hidden';
121391             }
121392
121393             return false;
121394
121395             function someMissing() {
121396               if (context.inIntro()) return false;
121397               var osm = context.connection();
121398
121399               if (osm) {
121400                 var missing = _coords.filter(function (loc) {
121401                   return !osm.isDataLoaded(loc);
121402                 });
121403
121404                 if (missing.length) {
121405                   missing.forEach(function (loc) {
121406                     context.loadTileAtLoc(loc);
121407                   });
121408                   return true;
121409                 }
121410               }
121411
121412               return false;
121413             }
121414           };
121415
121416           operation.tooltip = function () {
121417             var disable = operation.disabled();
121418
121419             if (disable) {
121420               return _t('operations.disconnect.' + disable);
121421             }
121422
121423             return _t('operations.disconnect.description.' + _descriptionID);
121424           };
121425
121426           operation.annotation = function () {
121427             return _t('operations.disconnect.annotation.' + _annotationID);
121428           };
121429
121430           operation.id = 'disconnect';
121431           operation.keys = [_t('operations.disconnect.key')];
121432           operation.title = _t('operations.disconnect.title');
121433           operation.behavior = behaviorOperation(context).which(operation);
121434           return operation;
121435         }
121436
121437         function operationDowngrade(context, selectedIDs) {
121438           var _affectedFeatureCount = 0;
121439
121440           var _downgradeType = downgradeTypeForEntityIDs(selectedIDs);
121441
121442           var _multi = _affectedFeatureCount === 1 ? 'single' : 'multiple';
121443
121444           function downgradeTypeForEntityIDs(entityIds) {
121445             var downgradeType;
121446             _affectedFeatureCount = 0;
121447
121448             for (var i in entityIds) {
121449               var entityID = entityIds[i];
121450               var type = downgradeTypeForEntityID(entityID);
121451
121452               if (type) {
121453                 _affectedFeatureCount += 1;
121454
121455                 if (downgradeType && type !== downgradeType) {
121456                   if (downgradeType !== 'generic' && type !== 'generic') {
121457                     downgradeType = 'building_address';
121458                   } else {
121459                     downgradeType = 'generic';
121460                   }
121461                 } else {
121462                   downgradeType = type;
121463                 }
121464               }
121465             }
121466
121467             return downgradeType;
121468           }
121469
121470           function downgradeTypeForEntityID(entityID) {
121471             var graph = context.graph();
121472             var entity = graph.entity(entityID);
121473             var preset = _mainPresetIndex.match(entity, graph);
121474             if (!preset || preset.isFallback()) return null;
121475
121476             if (entity.type === 'node' && preset.id !== 'address' && Object.keys(entity.tags).some(function (key) {
121477               return key.match(/^addr:.{1,}/);
121478             })) {
121479               return 'address';
121480             }
121481
121482             var geometry = entity.geometry(graph);
121483
121484             if (geometry === 'area' && entity.tags.building && !preset.tags.building) {
121485               return 'building';
121486             }
121487
121488             if (geometry === 'vertex' && Object.keys(entity.tags).length) {
121489               return 'generic';
121490             }
121491
121492             return null;
121493           }
121494
121495           var buildingKeysToKeep = ['architect', 'building', 'height', 'layer', 'source', 'type', 'wheelchair'];
121496           var addressKeysToKeep = ['source'];
121497
121498           var operation = function operation() {
121499             context.perform(function (graph) {
121500               for (var i in selectedIDs) {
121501                 var entityID = selectedIDs[i];
121502                 var type = downgradeTypeForEntityID(entityID);
121503                 if (!type) continue;
121504                 var tags = Object.assign({}, graph.entity(entityID).tags); // shallow copy
121505
121506                 for (var key in tags) {
121507                   if (type === 'address' && addressKeysToKeep.indexOf(key) !== -1) continue;
121508
121509                   if (type === 'building') {
121510                     if (buildingKeysToKeep.indexOf(key) !== -1 || key.match(/^building:.{1,}/) || key.match(/^roof:.{1,}/)) continue;
121511                   }
121512
121513                   if (type !== 'generic') {
121514                     if (key.match(/^addr:.{1,}/) || key.match(/^source:.{1,}/)) continue;
121515                   }
121516
121517                   delete tags[key];
121518                 }
121519
121520                 graph = actionChangeTags(entityID, tags)(graph);
121521               }
121522
121523               return graph;
121524             }, operation.annotation());
121525             context.validator().validate(); // refresh the select mode to enable the delete operation
121526
121527             context.enter(modeSelect(context, selectedIDs));
121528           };
121529
121530           operation.available = function () {
121531             return _downgradeType;
121532           };
121533
121534           operation.disabled = function () {
121535             if (selectedIDs.some(hasWikidataTag)) {
121536               return 'has_wikidata_tag';
121537             }
121538
121539             return false;
121540
121541             function hasWikidataTag(id) {
121542               var entity = context.entity(id);
121543               return entity.tags.wikidata && entity.tags.wikidata.trim().length > 0;
121544             }
121545           };
121546
121547           operation.tooltip = function () {
121548             var disable = operation.disabled();
121549             return disable ? _t('operations.downgrade.' + disable + '.' + _multi) : _t('operations.downgrade.description.' + _downgradeType);
121550           };
121551
121552           operation.annotation = function () {
121553             var suffix;
121554
121555             if (_downgradeType === 'building_address') {
121556               suffix = 'generic';
121557             } else {
121558               suffix = _downgradeType;
121559             }
121560
121561             return _t('operations.downgrade.annotation.' + suffix, {
121562               n: _affectedFeatureCount
121563             });
121564           };
121565
121566           operation.id = 'downgrade';
121567           operation.keys = [uiCmd('⌫')];
121568           operation.title = _t('operations.downgrade.title');
121569           operation.behavior = behaviorOperation(context).which(operation);
121570           return operation;
121571         }
121572
121573         function operationExtract(context, selectedIDs) {
121574           var _amount = selectedIDs.length === 1 ? 'single' : 'multiple';
121575
121576           var _geometries = utilArrayUniq(selectedIDs.map(function (entityID) {
121577             return context.graph().hasEntity(entityID) && context.graph().geometry(entityID);
121578           }).filter(Boolean));
121579
121580           var _geometryID = _geometries.length === 1 ? _geometries[0] : 'feature';
121581
121582           var _extent;
121583
121584           var _actions = selectedIDs.map(function (entityID) {
121585             var graph = context.graph();
121586             var entity = graph.hasEntity(entityID);
121587             if (!entity || !entity.hasInterestingTags()) return null;
121588             if (entity.type === 'node' && graph.parentWays(entity).length === 0) return null;
121589
121590             if (entity.type !== 'node') {
121591               var preset = _mainPresetIndex.match(entity, graph); // only allow extraction from ways/relations if the preset supports points
121592
121593               if (preset.geometry.indexOf('point') === -1) return null;
121594             }
121595
121596             _extent = _extent ? _extent.extend(entity.extent(graph)) : entity.extent(graph);
121597             return actionExtract(entityID, context.projection);
121598           }).filter(Boolean);
121599
121600           var operation = function operation() {
121601             var combinedAction = function combinedAction(graph) {
121602               _actions.forEach(function (action) {
121603                 graph = action(graph);
121604               });
121605
121606               return graph;
121607             };
121608
121609             context.perform(combinedAction, operation.annotation()); // do the extract
121610
121611             var extractedNodeIDs = _actions.map(function (action) {
121612               return action.getExtractedNodeID();
121613             });
121614
121615             context.enter(modeSelect(context, extractedNodeIDs));
121616           };
121617
121618           operation.available = function () {
121619             return _actions.length && selectedIDs.length === _actions.length;
121620           };
121621
121622           operation.disabled = function () {
121623             if (_extent && _extent.percentContainedIn(context.map().extent()) < 0.8) {
121624               return 'too_large';
121625             } else if (selectedIDs.some(function (entityID) {
121626               return context.graph().geometry(entityID) === 'vertex' && context.hasHiddenConnections(entityID);
121627             })) {
121628               return 'connected_to_hidden';
121629             }
121630
121631             return false;
121632           };
121633
121634           operation.tooltip = function () {
121635             var disableReason = operation.disabled();
121636
121637             if (disableReason) {
121638               return _t('operations.extract.' + disableReason + '.' + _amount);
121639             } else {
121640               return _t('operations.extract.description.' + _geometryID + '.' + _amount);
121641             }
121642           };
121643
121644           operation.annotation = function () {
121645             return _t('operations.extract.annotation', {
121646               n: selectedIDs.length
121647             });
121648           };
121649
121650           operation.id = 'extract';
121651           operation.keys = [_t('operations.extract.key')];
121652           operation.title = _t('operations.extract.title');
121653           operation.behavior = behaviorOperation(context).which(operation);
121654           return operation;
121655         }
121656
121657         function operationMerge(context, selectedIDs) {
121658           var _action = getAction();
121659
121660           function getAction() {
121661             // prefer a non-disabled action first
121662             var join = actionJoin(selectedIDs);
121663             if (!join.disabled(context.graph())) return join;
121664             var merge = actionMerge(selectedIDs);
121665             if (!merge.disabled(context.graph())) return merge;
121666             var mergePolygon = actionMergePolygon(selectedIDs);
121667             if (!mergePolygon.disabled(context.graph())) return mergePolygon;
121668             var mergeNodes = actionMergeNodes(selectedIDs);
121669             if (!mergeNodes.disabled(context.graph())) return mergeNodes; // otherwise prefer an action with an interesting disabled reason
121670
121671             if (join.disabled(context.graph()) !== 'not_eligible') return join;
121672             if (merge.disabled(context.graph()) !== 'not_eligible') return merge;
121673             if (mergePolygon.disabled(context.graph()) !== 'not_eligible') return mergePolygon;
121674             return mergeNodes;
121675           }
121676
121677           var operation = function operation() {
121678             if (operation.disabled()) return;
121679             context.perform(_action, operation.annotation());
121680             context.validator().validate();
121681             var resultIDs = selectedIDs.filter(context.hasEntity);
121682
121683             if (resultIDs.length > 1) {
121684               var interestingIDs = resultIDs.filter(function (id) {
121685                 return context.entity(id).hasInterestingTags();
121686               });
121687               if (interestingIDs.length) resultIDs = interestingIDs;
121688             }
121689
121690             context.enter(modeSelect(context, resultIDs));
121691           };
121692
121693           operation.available = function () {
121694             return selectedIDs.length >= 2;
121695           };
121696
121697           operation.disabled = function () {
121698             var actionDisabled = _action.disabled(context.graph());
121699
121700             if (actionDisabled) return actionDisabled;
121701             var osm = context.connection();
121702
121703             if (osm && _action.resultingWayNodesLength && _action.resultingWayNodesLength(context.graph()) > osm.maxWayNodes()) {
121704               return 'too_many_vertices';
121705             }
121706
121707             return false;
121708           };
121709
121710           operation.tooltip = function () {
121711             var disabled = operation.disabled();
121712
121713             if (disabled) {
121714               if (disabled === 'conflicting_relations') {
121715                 return _t('operations.merge.conflicting_relations');
121716               }
121717
121718               if (disabled === 'restriction' || disabled === 'connectivity') {
121719                 return _t('operations.merge.damage_relation', {
121720                   relation: _mainPresetIndex.item('type/' + disabled).name()
121721                 });
121722               }
121723
121724               return _t('operations.merge.' + disabled);
121725             }
121726
121727             return _t('operations.merge.description');
121728           };
121729
121730           operation.annotation = function () {
121731             return _t('operations.merge.annotation', {
121732               n: selectedIDs.length
121733             });
121734           };
121735
121736           operation.id = 'merge';
121737           operation.keys = [_t('operations.merge.key')];
121738           operation.title = _t('operations.merge.title');
121739           operation.behavior = behaviorOperation(context).which(operation);
121740           return operation;
121741         }
121742
121743         function operationPaste(context) {
121744           var _pastePoint;
121745
121746           var operation = function operation() {
121747             if (!_pastePoint) return;
121748             var oldIDs = context.copyIDs();
121749             if (!oldIDs.length) return;
121750             var projection = context.projection;
121751             var extent = geoExtent();
121752             var oldGraph = context.copyGraph();
121753             var newIDs = [];
121754             var action = actionCopyEntities(oldIDs, oldGraph);
121755             context.perform(action);
121756             var copies = action.copies();
121757             var originals = new Set();
121758             Object.values(copies).forEach(function (entity) {
121759               originals.add(entity.id);
121760             });
121761
121762             for (var id in copies) {
121763               var oldEntity = oldGraph.entity(id);
121764               var newEntity = copies[id];
121765
121766               extent._extend(oldEntity.extent(oldGraph)); // Exclude child nodes from newIDs if their parent way was also copied.
121767
121768
121769               var parents = context.graph().parentWays(newEntity);
121770               var parentCopied = parents.some(function (parent) {
121771                 return originals.has(parent.id);
121772               });
121773
121774               if (!parentCopied) {
121775                 newIDs.push(newEntity.id);
121776               }
121777             } // Use the location of the copy operation to offset the paste location,
121778             // or else use the center of the pasted extent
121779
121780
121781             var copyPoint = context.copyLonLat() && projection(context.copyLonLat()) || projection(extent.center());
121782             var delta = geoVecSubtract(_pastePoint, copyPoint); // Move the pasted objects to be anchored at the paste location
121783
121784             context.replace(actionMove(newIDs, delta, projection), operation.annotation());
121785             context.enter(modeSelect(context, newIDs));
121786           };
121787
121788           operation.point = function (val) {
121789             _pastePoint = val;
121790             return operation;
121791           };
121792
121793           operation.available = function () {
121794             return context.mode().id === 'browse';
121795           };
121796
121797           operation.disabled = function () {
121798             return !context.copyIDs().length;
121799           };
121800
121801           operation.tooltip = function () {
121802             var oldGraph = context.copyGraph();
121803             var ids = context.copyIDs();
121804
121805             if (!ids.length) {
121806               return _t('operations.paste.nothing_copied');
121807             }
121808
121809             return _t('operations.paste.description', {
121810               feature: utilDisplayLabel(oldGraph.entity(ids[0]), oldGraph),
121811               n: ids.length
121812             });
121813           };
121814
121815           operation.annotation = function () {
121816             var ids = context.copyIDs();
121817             return _t('operations.paste.annotation', {
121818               n: ids.length
121819             });
121820           };
121821
121822           operation.id = 'paste';
121823           operation.keys = [uiCmd('⌘V')];
121824           operation.title = _t('operations.paste.title');
121825           return operation;
121826         }
121827
121828         function operationReverse(context, selectedIDs) {
121829           var operation = function operation() {
121830             context.perform(function combinedReverseAction(graph) {
121831               actions().forEach(function (action) {
121832                 graph = action(graph);
121833               });
121834               return graph;
121835             }, operation.annotation());
121836             context.validator().validate();
121837           };
121838
121839           function actions(situation) {
121840             return selectedIDs.map(function (entityID) {
121841               var entity = context.hasEntity(entityID);
121842               if (!entity) return null;
121843
121844               if (situation === 'toolbar') {
121845                 if (entity.type === 'way' && !entity.isOneWay() && !entity.isSided()) return null;
121846               }
121847
121848               var geometry = entity.geometry(context.graph());
121849               if (entity.type !== 'node' && geometry !== 'line') return null;
121850               var action = actionReverse(entityID);
121851               if (action.disabled(context.graph())) return null;
121852               return action;
121853             }).filter(Boolean);
121854           }
121855
121856           function reverseTypeID() {
121857             var acts = actions();
121858             var nodeActionCount = acts.filter(function (act) {
121859               var entity = context.hasEntity(act.entityID());
121860               return entity && entity.type === 'node';
121861             }).length;
121862             if (nodeActionCount === 0) return 'line';
121863             if (nodeActionCount === acts.length) return 'point';
121864             return 'feature';
121865           }
121866
121867           operation.available = function (situation) {
121868             return actions(situation).length > 0;
121869           };
121870
121871           operation.disabled = function () {
121872             return false;
121873           };
121874
121875           operation.tooltip = function () {
121876             return _t('operations.reverse.description.' + reverseTypeID());
121877           };
121878
121879           operation.annotation = function () {
121880             var acts = actions();
121881             return _t('operations.reverse.annotation.' + reverseTypeID(), {
121882               n: acts.length
121883             });
121884           };
121885
121886           operation.id = 'reverse';
121887           operation.keys = [_t('operations.reverse.key')];
121888           operation.title = _t('operations.reverse.title');
121889           operation.behavior = behaviorOperation(context).which(operation);
121890           return operation;
121891         }
121892
121893         function operationSplit(context, selectedIDs) {
121894           var _vertexIds = selectedIDs.filter(function (id) {
121895             return context.graph().geometry(id) === 'vertex';
121896           });
121897
121898           var _selectedWayIds = selectedIDs.filter(function (id) {
121899             var entity = context.graph().hasEntity(id);
121900             return entity && entity.type === 'way';
121901           });
121902
121903           var _isAvailable = _vertexIds.length > 0 && _vertexIds.length + _selectedWayIds.length === selectedIDs.length;
121904
121905           var _action = actionSplit(_vertexIds);
121906
121907           var _ways = [];
121908           var _geometry = 'feature';
121909           var _waysAmount = 'single';
121910
121911           var _nodesAmount = _vertexIds.length === 1 ? 'single' : 'multiple';
121912
121913           if (_isAvailable) {
121914             if (_selectedWayIds.length) _action.limitWays(_selectedWayIds);
121915             _ways = _action.ways(context.graph());
121916             var geometries = {};
121917
121918             _ways.forEach(function (way) {
121919               geometries[way.geometry(context.graph())] = true;
121920             });
121921
121922             if (Object.keys(geometries).length === 1) {
121923               _geometry = Object.keys(geometries)[0];
121924             }
121925
121926             _waysAmount = _ways.length === 1 ? 'single' : 'multiple';
121927           }
121928
121929           var operation = function operation() {
121930             var difference = context.perform(_action, operation.annotation()); // select both the nodes and the ways so the mapper can immediately disconnect them if desired
121931
121932             var idsToSelect = _vertexIds.concat(difference.extantIDs().filter(function (id) {
121933               // filter out relations that may have had member additions
121934               return context.entity(id).type === 'way';
121935             }));
121936
121937             context.enter(modeSelect(context, idsToSelect));
121938           };
121939
121940           operation.relatedEntityIds = function () {
121941             return _selectedWayIds.length ? [] : _ways.map(function (way) {
121942               return way.id;
121943             });
121944           };
121945
121946           operation.available = function () {
121947             return _isAvailable;
121948           };
121949
121950           operation.disabled = function () {
121951             var reason = _action.disabled(context.graph());
121952
121953             if (reason) {
121954               return reason;
121955             } else if (selectedIDs.some(context.hasHiddenConnections)) {
121956               return 'connected_to_hidden';
121957             }
121958
121959             return false;
121960           };
121961
121962           operation.tooltip = function () {
121963             var disable = operation.disabled();
121964             if (disable) return _t('operations.split.' + disable);
121965             return _t('operations.split.description.' + _geometry + '.' + _waysAmount + '.' + _nodesAmount + '_node');
121966           };
121967
121968           operation.annotation = function () {
121969             return _t('operations.split.annotation.' + _geometry, {
121970               n: _ways.length
121971             });
121972           };
121973
121974           operation.icon = function () {
121975             if (_waysAmount === 'multiple') {
121976               return '#iD-operation-split-multiple';
121977             } else {
121978               return '#iD-operation-split';
121979             }
121980           };
121981
121982           operation.id = 'split';
121983           operation.keys = [_t('operations.split.key')];
121984           operation.title = _t('operations.split.title');
121985           operation.behavior = behaviorOperation(context).which(operation);
121986           return operation;
121987         }
121988
121989         function operationStraighten(context, selectedIDs) {
121990           var _wayIDs = selectedIDs.filter(function (id) {
121991             return id.charAt(0) === 'w';
121992           });
121993
121994           var _nodeIDs = selectedIDs.filter(function (id) {
121995             return id.charAt(0) === 'n';
121996           });
121997
121998           var _amount = (_wayIDs.length ? _wayIDs : _nodeIDs).length === 1 ? 'single' : 'multiple';
121999
122000           var _nodes = utilGetAllNodes(selectedIDs, context.graph());
122001
122002           var _coords = _nodes.map(function (n) {
122003             return n.loc;
122004           });
122005
122006           var _extent = utilTotalExtent(selectedIDs, context.graph());
122007
122008           var _action = chooseAction();
122009
122010           var _geometry;
122011
122012           function chooseAction() {
122013             // straighten selected nodes
122014             if (_wayIDs.length === 0 && _nodeIDs.length > 2) {
122015               _geometry = 'point';
122016               return actionStraightenNodes(_nodeIDs, context.projection); // straighten selected ways (possibly between range of 2 selected nodes)
122017             } else if (_wayIDs.length > 0 && (_nodeIDs.length === 0 || _nodeIDs.length === 2)) {
122018               var startNodeIDs = [];
122019               var endNodeIDs = [];
122020
122021               for (var i = 0; i < selectedIDs.length; i++) {
122022                 var entity = context.entity(selectedIDs[i]);
122023
122024                 if (entity.type === 'node') {
122025                   continue;
122026                 } else if (entity.type !== 'way' || entity.isClosed()) {
122027                   return null; // exit early, can't straighten these
122028                 }
122029
122030                 startNodeIDs.push(entity.first());
122031                 endNodeIDs.push(entity.last());
122032               } // Remove duplicate end/startNodeIDs (duplicate nodes cannot be at the line end)
122033
122034
122035               startNodeIDs = startNodeIDs.filter(function (n) {
122036                 return startNodeIDs.indexOf(n) === startNodeIDs.lastIndexOf(n);
122037               });
122038               endNodeIDs = endNodeIDs.filter(function (n) {
122039                 return endNodeIDs.indexOf(n) === endNodeIDs.lastIndexOf(n);
122040               }); // Ensure all ways are connected (i.e. only 2 unique endpoints/startpoints)
122041
122042               if (utilArrayDifference(startNodeIDs, endNodeIDs).length + utilArrayDifference(endNodeIDs, startNodeIDs).length !== 2) return null; // Ensure path contains at least 3 unique nodes
122043
122044               var wayNodeIDs = utilGetAllNodes(_wayIDs, context.graph()).map(function (node) {
122045                 return node.id;
122046               });
122047               if (wayNodeIDs.length <= 2) return null; // If range of 2 selected nodes is supplied, ensure nodes lie on the selected path
122048
122049               if (_nodeIDs.length === 2 && (wayNodeIDs.indexOf(_nodeIDs[0]) === -1 || wayNodeIDs.indexOf(_nodeIDs[1]) === -1)) return null;
122050
122051               if (_nodeIDs.length) {
122052                 // If we're only straightenting between two points, we only need that extent visible
122053                 _extent = utilTotalExtent(_nodeIDs, context.graph());
122054               }
122055
122056               _geometry = 'line';
122057               return actionStraightenWay(selectedIDs, context.projection);
122058             }
122059
122060             return null;
122061           }
122062
122063           function operation() {
122064             if (!_action) return;
122065             context.perform(_action, operation.annotation());
122066             window.setTimeout(function () {
122067               context.validator().validate();
122068             }, 300); // after any transition
122069           }
122070
122071           operation.available = function () {
122072             return Boolean(_action);
122073           };
122074
122075           operation.disabled = function () {
122076             var reason = _action.disabled(context.graph());
122077
122078             if (reason) {
122079               return reason;
122080             } else if (_extent.percentContainedIn(context.map().extent()) < 0.8) {
122081               return 'too_large';
122082             } else if (someMissing()) {
122083               return 'not_downloaded';
122084             } else if (selectedIDs.some(context.hasHiddenConnections)) {
122085               return 'connected_to_hidden';
122086             }
122087
122088             return false;
122089
122090             function someMissing() {
122091               if (context.inIntro()) return false;
122092               var osm = context.connection();
122093
122094               if (osm) {
122095                 var missing = _coords.filter(function (loc) {
122096                   return !osm.isDataLoaded(loc);
122097                 });
122098
122099                 if (missing.length) {
122100                   missing.forEach(function (loc) {
122101                     context.loadTileAtLoc(loc);
122102                   });
122103                   return true;
122104                 }
122105               }
122106
122107               return false;
122108             }
122109           };
122110
122111           operation.tooltip = function () {
122112             var disable = operation.disabled();
122113             return disable ? _t('operations.straighten.' + disable + '.' + _amount) : _t('operations.straighten.description.' + _geometry + (_wayIDs.length === 1 ? '' : 's'));
122114           };
122115
122116           operation.annotation = function () {
122117             return _t('operations.straighten.annotation.' + _geometry, {
122118               n: _wayIDs.length ? _wayIDs.length : _nodeIDs.length
122119             });
122120           };
122121
122122           operation.id = 'straighten';
122123           operation.keys = [_t('operations.straighten.key')];
122124           operation.title = _t('operations.straighten.title');
122125           operation.behavior = behaviorOperation(context).which(operation);
122126           return operation;
122127         }
122128
122129         var Operations = /*#__PURE__*/Object.freeze({
122130                 __proto__: null,
122131                 operationCircularize: operationCircularize,
122132                 operationContinue: operationContinue,
122133                 operationCopy: operationCopy,
122134                 operationDelete: operationDelete,
122135                 operationDisconnect: operationDisconnect,
122136                 operationDowngrade: operationDowngrade,
122137                 operationExtract: operationExtract,
122138                 operationMerge: operationMerge,
122139                 operationMove: operationMove,
122140                 operationOrthogonalize: operationOrthogonalize,
122141                 operationPaste: operationPaste,
122142                 operationReflectShort: operationReflectShort,
122143                 operationReflectLong: operationReflectLong,
122144                 operationReverse: operationReverse,
122145                 operationRotate: operationRotate,
122146                 operationSplit: operationSplit,
122147                 operationStraighten: operationStraighten
122148         });
122149
122150         function modeSelect(context, selectedIDs) {
122151           var mode = {
122152             id: 'select',
122153             button: 'browse'
122154           };
122155           var keybinding = utilKeybinding('select');
122156
122157           var _breatheBehavior = behaviorBreathe();
122158
122159           var _modeDragNode = modeDragNode(context);
122160
122161           var _selectBehavior;
122162
122163           var _behaviors = [];
122164           var _operations = [];
122165           var _newFeature = false;
122166           var _follow = false; // `_focusedParentWayId` is used when we visit a vertex with multiple
122167           // parents, and we want to remember which parent line we started on.
122168
122169           var _focusedParentWayId;
122170
122171           var _focusedVertexIds;
122172
122173           function singular() {
122174             if (selectedIDs && selectedIDs.length === 1) {
122175               return context.hasEntity(selectedIDs[0]);
122176             }
122177           }
122178
122179           function selectedEntities() {
122180             return selectedIDs.map(function (id) {
122181               return context.hasEntity(id);
122182             }).filter(Boolean);
122183           }
122184
122185           function checkSelectedIDs() {
122186             var ids = [];
122187
122188             if (Array.isArray(selectedIDs)) {
122189               ids = selectedIDs.filter(function (id) {
122190                 return context.hasEntity(id);
122191               });
122192             }
122193
122194             if (!ids.length) {
122195               context.enter(modeBrowse(context));
122196               return false;
122197             } else if (selectedIDs.length > 1 && ids.length === 1 || selectedIDs.length === 1 && ids.length > 1) {
122198               // switch between single- and multi-select UI
122199               context.enter(modeSelect(context, ids));
122200               return false;
122201             }
122202
122203             selectedIDs = ids;
122204             return true;
122205           } // find the parent ways for nextVertex, previousVertex, and selectParent
122206
122207
122208           function parentWaysIdsOfSelection(onlyCommonParents) {
122209             var graph = context.graph();
122210             var parents = [];
122211
122212             for (var i = 0; i < selectedIDs.length; i++) {
122213               var entity = context.hasEntity(selectedIDs[i]);
122214
122215               if (!entity || entity.geometry(graph) !== 'vertex') {
122216                 return []; // selection includes some non-vertices
122217               }
122218
122219               var currParents = graph.parentWays(entity).map(function (w) {
122220                 return w.id;
122221               });
122222
122223               if (!parents.length) {
122224                 parents = currParents;
122225                 continue;
122226               }
122227
122228               parents = (onlyCommonParents ? utilArrayIntersection : utilArrayUnion)(parents, currParents);
122229
122230               if (!parents.length) {
122231                 return [];
122232               }
122233             }
122234
122235             return parents;
122236           } // find the child nodes for selected ways
122237
122238
122239           function childNodeIdsOfSelection(onlyCommon) {
122240             var graph = context.graph();
122241             var childs = [];
122242
122243             for (var i = 0; i < selectedIDs.length; i++) {
122244               var entity = context.hasEntity(selectedIDs[i]);
122245
122246               if (!entity || !['area', 'line'].includes(entity.geometry(graph))) {
122247                 return []; // selection includes non-area/non-line
122248               }
122249
122250               var currChilds = graph.childNodes(entity).map(function (node) {
122251                 return node.id;
122252               });
122253
122254               if (!childs.length) {
122255                 childs = currChilds;
122256                 continue;
122257               }
122258
122259               childs = (onlyCommon ? utilArrayIntersection : utilArrayUnion)(childs, currChilds);
122260
122261               if (!childs.length) {
122262                 return [];
122263               }
122264             }
122265
122266             return childs;
122267           }
122268
122269           function checkFocusedParent() {
122270             if (_focusedParentWayId) {
122271               var parents = parentWaysIdsOfSelection(true);
122272               if (parents.indexOf(_focusedParentWayId) === -1) _focusedParentWayId = null;
122273             }
122274           }
122275
122276           function parentWayIdForVertexNavigation() {
122277             var parentIds = parentWaysIdsOfSelection(true);
122278
122279             if (_focusedParentWayId && parentIds.indexOf(_focusedParentWayId) !== -1) {
122280               // prefer the previously seen parent
122281               return _focusedParentWayId;
122282             }
122283
122284             return parentIds.length ? parentIds[0] : null;
122285           }
122286
122287           mode.selectedIDs = function (val) {
122288             if (!arguments.length) return selectedIDs;
122289             selectedIDs = val;
122290             return mode;
122291           };
122292
122293           mode.zoomToSelected = function () {
122294             context.map().zoomToEase(selectedEntities());
122295           };
122296
122297           mode.newFeature = function (val) {
122298             if (!arguments.length) return _newFeature;
122299             _newFeature = val;
122300             return mode;
122301           };
122302
122303           mode.selectBehavior = function (val) {
122304             if (!arguments.length) return _selectBehavior;
122305             _selectBehavior = val;
122306             return mode;
122307           };
122308
122309           mode.follow = function (val) {
122310             if (!arguments.length) return _follow;
122311             _follow = val;
122312             return mode;
122313           };
122314
122315           function loadOperations() {
122316             _operations.forEach(function (operation) {
122317               if (operation.behavior) {
122318                 context.uninstall(operation.behavior);
122319               }
122320             });
122321
122322             _operations = Object.values(Operations).map(function (o) {
122323               return o(context, selectedIDs);
122324             }).filter(function (o) {
122325               return o.id !== 'delete' && o.id !== 'downgrade' && o.id !== 'copy';
122326             }).concat([// group copy/downgrade/delete operation together at the end of the list
122327             operationCopy(context, selectedIDs), operationDowngrade(context, selectedIDs), operationDelete(context, selectedIDs)]).filter(function (operation) {
122328               return operation.available();
122329             });
122330
122331             _operations.forEach(function (operation) {
122332               if (operation.behavior) {
122333                 context.install(operation.behavior);
122334               }
122335             }); // remove any displayed menu
122336
122337
122338             context.ui().closeEditMenu();
122339           }
122340
122341           mode.operations = function () {
122342             return _operations;
122343           };
122344
122345           mode.enter = function () {
122346             if (!checkSelectedIDs()) return;
122347             context.features().forceVisible(selectedIDs);
122348
122349             _modeDragNode.restoreSelectedIDs(selectedIDs);
122350
122351             loadOperations();
122352
122353             if (!_behaviors.length) {
122354               if (!_selectBehavior) _selectBehavior = behaviorSelect(context);
122355               _behaviors = [behaviorPaste(context), _breatheBehavior, behaviorHover(context).on('hover', context.ui().sidebar.hoverModeSelect), _selectBehavior, behaviorLasso(context), _modeDragNode.behavior, modeDragNote(context).behavior];
122356             }
122357
122358             _behaviors.forEach(context.install);
122359
122360             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) {
122361               return uiCmd('⇧' + key);
122362             }), scaleSelection(1.05)).on(utilKeybinding.plusKeys.map(function (key) {
122363               return uiCmd('⇧⌥' + key);
122364             }), scaleSelection(Math.pow(1.05, 5))).on(utilKeybinding.minusKeys.map(function (key) {
122365               return uiCmd('⇧' + key);
122366             }), scaleSelection(1 / 1.05)).on(utilKeybinding.minusKeys.map(function (key) {
122367               return uiCmd('⇧⌥' + key);
122368             }), scaleSelection(1 / Math.pow(1.05, 5))).on(['\\', 'pause'], focusNextParent).on(uiCmd('⌘↑'), selectParent).on(uiCmd('⌘↓'), selectChild).on('⎋', esc, true);
122369             select(document).call(keybinding);
122370             context.ui().sidebar.select(selectedIDs, _newFeature);
122371             context.history().on('change.select', function () {
122372               loadOperations(); // reselect after change in case relation members were removed or added
122373
122374               selectElements();
122375             }).on('undone.select', checkSelectedIDs).on('redone.select', checkSelectedIDs);
122376             context.map().on('drawn.select', selectElements).on('crossEditableZoom.select', function () {
122377               selectElements();
122378
122379               _breatheBehavior.restartIfNeeded(context.surface());
122380             });
122381             context.map().doubleUpHandler().on('doubleUp.modeSelect', didDoubleUp);
122382             selectElements();
122383
122384             if (_follow) {
122385               var extent = geoExtent();
122386               var graph = context.graph();
122387               selectedIDs.forEach(function (id) {
122388                 var entity = context.entity(id);
122389
122390                 extent._extend(entity.extent(graph));
122391               });
122392               var loc = extent.center();
122393               context.map().centerEase(loc); // we could enter the mode multiple times, so reset follow for next time
122394
122395               _follow = false;
122396             }
122397
122398             function nudgeSelection(delta) {
122399               return function () {
122400                 // prevent nudging during low zoom selection
122401                 if (!context.map().withinEditableZoom()) return;
122402                 var moveOp = operationMove(context, selectedIDs);
122403
122404                 if (moveOp.disabled()) {
122405                   context.ui().flash.duration(4000).iconName('#iD-operation-' + moveOp.id).iconClass('operation disabled').label(moveOp.tooltip)();
122406                 } else {
122407                   context.perform(actionMove(selectedIDs, delta, context.projection), moveOp.annotation());
122408                   context.validator().validate();
122409                 }
122410               };
122411             }
122412
122413             function scaleSelection(factor) {
122414               return function () {
122415                 // prevent scaling during low zoom selection
122416                 if (!context.map().withinEditableZoom()) return;
122417                 var nodes = utilGetAllNodes(selectedIDs, context.graph());
122418                 var isUp = factor > 1; // can only scale if multiple nodes are selected
122419
122420                 if (nodes.length <= 1) return;
122421                 var extent = utilTotalExtent(selectedIDs, context.graph()); // These disabled checks would normally be handled by an operation
122422                 // object, but we don't want an actual scale operation at this point.
122423
122424                 function scalingDisabled() {
122425                   if (tooSmall()) {
122426                     return 'too_small';
122427                   } else if (extent.percentContainedIn(context.map().extent()) < 0.8) {
122428                     return 'too_large';
122429                   } else if (someMissing() || selectedIDs.some(incompleteRelation)) {
122430                     return 'not_downloaded';
122431                   } else if (selectedIDs.some(context.hasHiddenConnections)) {
122432                     return 'connected_to_hidden';
122433                   }
122434
122435                   return false;
122436
122437                   function tooSmall() {
122438                     if (isUp) return false;
122439                     var dLon = Math.abs(extent[1][0] - extent[0][0]);
122440                     var dLat = Math.abs(extent[1][1] - extent[0][1]);
122441                     return dLon < geoMetersToLon(1, extent[1][1]) && dLat < geoMetersToLat(1);
122442                   }
122443
122444                   function someMissing() {
122445                     if (context.inIntro()) return false;
122446                     var osm = context.connection();
122447
122448                     if (osm) {
122449                       var missing = nodes.filter(function (n) {
122450                         return !osm.isDataLoaded(n.loc);
122451                       });
122452
122453                       if (missing.length) {
122454                         missing.forEach(function (loc) {
122455                           context.loadTileAtLoc(loc);
122456                         });
122457                         return true;
122458                       }
122459                     }
122460
122461                     return false;
122462                   }
122463
122464                   function incompleteRelation(id) {
122465                     var entity = context.entity(id);
122466                     return entity.type === 'relation' && !entity.isComplete(context.graph());
122467                   }
122468                 }
122469
122470                 var disabled = scalingDisabled();
122471
122472                 if (disabled) {
122473                   var multi = selectedIDs.length === 1 ? 'single' : 'multiple';
122474                   context.ui().flash.duration(4000).iconName('#iD-icon-no').iconClass('operation disabled').label(_t.html('operations.scale.' + disabled + '.' + multi))();
122475                 } else {
122476                   var pivot = context.projection(extent.center());
122477                   var annotation = _t('operations.scale.annotation.' + (isUp ? 'up' : 'down') + '.feature', {
122478                     n: selectedIDs.length
122479                   });
122480                   context.perform(actionScale(selectedIDs, pivot, factor, context.projection), annotation);
122481                   context.validator().validate();
122482                 }
122483               };
122484             }
122485
122486             function didDoubleUp(d3_event, loc) {
122487               if (!context.map().withinEditableZoom()) return;
122488               var target = select(d3_event.target);
122489               var datum = target.datum();
122490               var entity = datum && datum.properties && datum.properties.entity;
122491               if (!entity) return;
122492
122493               if (entity instanceof osmWay && target.classed('target')) {
122494                 var choice = geoChooseEdge(context.graph().childNodes(entity), loc, context.projection);
122495                 var prev = entity.nodes[choice.index - 1];
122496                 var next = entity.nodes[choice.index];
122497                 context.perform(actionAddMidpoint({
122498                   loc: choice.loc,
122499                   edge: [prev, next]
122500                 }, osmNode()), _t('operations.add.annotation.vertex'));
122501                 context.validator().validate();
122502               } else if (entity.type === 'midpoint') {
122503                 context.perform(actionAddMidpoint({
122504                   loc: entity.loc,
122505                   edge: entity.edge
122506                 }, osmNode()), _t('operations.add.annotation.vertex'));
122507                 context.validator().validate();
122508               }
122509             }
122510
122511             function selectElements() {
122512               if (!checkSelectedIDs()) return;
122513               var surface = context.surface();
122514               surface.selectAll('.selected-member').classed('selected-member', false);
122515               surface.selectAll('.selected').classed('selected', false);
122516               surface.selectAll('.related').classed('related', false); // reload `_focusedParentWayId` based on the current selection
122517
122518               checkFocusedParent();
122519
122520               if (_focusedParentWayId) {
122521                 surface.selectAll(utilEntitySelector([_focusedParentWayId])).classed('related', true);
122522               }
122523
122524               if (context.map().withinEditableZoom()) {
122525                 // Apply selection styling if not in wide selection
122526                 surface.selectAll(utilDeepMemberSelector(selectedIDs, context.graph(), true
122527                 /* skipMultipolgonMembers */
122528                 )).classed('selected-member', true);
122529                 surface.selectAll(utilEntityOrDeepMemberSelector(selectedIDs, context.graph())).classed('selected', true);
122530               }
122531             }
122532
122533             function esc() {
122534               if (context.container().select('.combobox').size()) return;
122535               context.enter(modeBrowse(context));
122536             }
122537
122538             function firstVertex(d3_event) {
122539               d3_event.preventDefault();
122540               var entity = singular();
122541               var parentId = parentWayIdForVertexNavigation();
122542               var way;
122543
122544               if (entity && entity.type === 'way') {
122545                 way = entity;
122546               } else if (parentId) {
122547                 way = context.entity(parentId);
122548               }
122549
122550               _focusedParentWayId = way && way.id;
122551
122552               if (way) {
122553                 context.enter(mode.selectedIDs([way.first()]).follow(true));
122554               }
122555             }
122556
122557             function lastVertex(d3_event) {
122558               d3_event.preventDefault();
122559               var entity = singular();
122560               var parentId = parentWayIdForVertexNavigation();
122561               var way;
122562
122563               if (entity && entity.type === 'way') {
122564                 way = entity;
122565               } else if (parentId) {
122566                 way = context.entity(parentId);
122567               }
122568
122569               _focusedParentWayId = way && way.id;
122570
122571               if (way) {
122572                 context.enter(mode.selectedIDs([way.last()]).follow(true));
122573               }
122574             }
122575
122576             function previousVertex(d3_event) {
122577               d3_event.preventDefault();
122578               var parentId = parentWayIdForVertexNavigation();
122579               _focusedParentWayId = parentId;
122580               if (!parentId) return;
122581               var way = context.entity(parentId);
122582               var length = way.nodes.length;
122583               var curr = way.nodes.indexOf(selectedIDs[0]);
122584               var index = -1;
122585
122586               if (curr > 0) {
122587                 index = curr - 1;
122588               } else if (way.isClosed()) {
122589                 index = length - 2;
122590               }
122591
122592               if (index !== -1) {
122593                 context.enter(mode.selectedIDs([way.nodes[index]]).follow(true));
122594               }
122595             }
122596
122597             function nextVertex(d3_event) {
122598               d3_event.preventDefault();
122599               var parentId = parentWayIdForVertexNavigation();
122600               _focusedParentWayId = parentId;
122601               if (!parentId) return;
122602               var way = context.entity(parentId);
122603               var length = way.nodes.length;
122604               var curr = way.nodes.indexOf(selectedIDs[0]);
122605               var index = -1;
122606
122607               if (curr < length - 1) {
122608                 index = curr + 1;
122609               } else if (way.isClosed()) {
122610                 index = 0;
122611               }
122612
122613               if (index !== -1) {
122614                 context.enter(mode.selectedIDs([way.nodes[index]]).follow(true));
122615               }
122616             }
122617
122618             function focusNextParent(d3_event) {
122619               d3_event.preventDefault();
122620               var parents = parentWaysIdsOfSelection(true);
122621               if (!parents || parents.length < 2) return;
122622               var index = parents.indexOf(_focusedParentWayId);
122623
122624               if (index < 0 || index > parents.length - 2) {
122625                 _focusedParentWayId = parents[0];
122626               } else {
122627                 _focusedParentWayId = parents[index + 1];
122628               }
122629
122630               var surface = context.surface();
122631               surface.selectAll('.related').classed('related', false);
122632
122633               if (_focusedParentWayId) {
122634                 surface.selectAll(utilEntitySelector([_focusedParentWayId])).classed('related', true);
122635               }
122636             }
122637
122638             function selectParent(d3_event) {
122639               d3_event.preventDefault();
122640               var currentSelectedIds = mode.selectedIDs();
122641               var parentIds = _focusedParentWayId ? [_focusedParentWayId] : parentWaysIdsOfSelection(false);
122642               if (!parentIds.length) return;
122643               context.enter(mode.selectedIDs(parentIds)); // set this after re-entering the selection since we normally want it cleared on exit
122644
122645               _focusedVertexIds = currentSelectedIds;
122646             }
122647
122648             function selectChild(d3_event) {
122649               d3_event.preventDefault();
122650               var currentSelectedIds = mode.selectedIDs();
122651               var childIds = _focusedVertexIds ? _focusedVertexIds.filter(function (id) {
122652                 return context.hasEntity(id);
122653               }) : childNodeIdsOfSelection(true);
122654               if (!childIds || !childIds.length) return;
122655               if (currentSelectedIds.length === 1) _focusedParentWayId = currentSelectedIds[0];
122656               context.enter(mode.selectedIDs(childIds));
122657             }
122658           };
122659
122660           mode.exit = function () {
122661             // we could enter the mode multiple times but it's only new the first time
122662             _newFeature = false;
122663             _focusedVertexIds = null;
122664
122665             _operations.forEach(function (operation) {
122666               if (operation.behavior) {
122667                 context.uninstall(operation.behavior);
122668               }
122669             });
122670
122671             _operations = [];
122672
122673             _behaviors.forEach(context.uninstall);
122674
122675             select(document).call(keybinding.unbind);
122676             context.ui().closeEditMenu();
122677             context.history().on('change.select', null).on('undone.select', null).on('redone.select', null);
122678             var surface = context.surface();
122679             surface.selectAll('.selected-member').classed('selected-member', false);
122680             surface.selectAll('.selected').classed('selected', false);
122681             surface.selectAll('.highlighted').classed('highlighted', false);
122682             surface.selectAll('.related').classed('related', false);
122683             context.map().on('drawn.select', null);
122684             context.ui().sidebar.hide();
122685             context.features().forceVisible([]);
122686             var entity = singular();
122687
122688             if (_newFeature && entity && entity.type === 'relation' && // no tags
122689             Object.keys(entity.tags).length === 0 && // no parent relations
122690             context.graph().parentRelations(entity).length === 0 && ( // no members or one member with no role
122691             entity.members.length === 0 || entity.members.length === 1 && !entity.members[0].role)) {
122692               // the user added this relation but didn't edit it at all, so just delete it
122693               var deleteAction = actionDeleteRelation(entity.id, true
122694               /* don't delete untagged members */
122695               );
122696               context.perform(deleteAction, _t('operations.delete.annotation.relation'));
122697               context.validator().validate();
122698             }
122699           };
122700
122701           return mode;
122702         }
122703
122704         function behaviorLasso(context) {
122705           // use pointer events on supported platforms; fallback to mouse events
122706           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
122707
122708           var behavior = function behavior(selection) {
122709             var lasso;
122710
122711             function pointerdown(d3_event) {
122712               var button = 0; // left
122713
122714               if (d3_event.button === button && d3_event.shiftKey === true) {
122715                 lasso = null;
122716                 select(window).on(_pointerPrefix + 'move.lasso', pointermove).on(_pointerPrefix + 'up.lasso', pointerup);
122717                 d3_event.stopPropagation();
122718               }
122719             }
122720
122721             function pointermove() {
122722               if (!lasso) {
122723                 lasso = uiLasso(context);
122724                 context.surface().call(lasso);
122725               }
122726
122727               lasso.p(context.map().mouse());
122728             }
122729
122730             function normalize(a, b) {
122731               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])]];
122732             }
122733
122734             function lassoed() {
122735               if (!lasso) return [];
122736               var graph = context.graph();
122737               var limitToNodes;
122738
122739               if (context.map().editableDataEnabled(true
122740               /* skipZoomCheck */
122741               ) && context.map().isInWideSelection()) {
122742                 // only select from the visible nodes
122743                 limitToNodes = new Set(utilGetAllNodes(context.selectedIDs(), graph));
122744               } else if (!context.map().editableDataEnabled()) {
122745                 return [];
122746               }
122747
122748               var bounds = lasso.extent().map(context.projection.invert);
122749               var extent = geoExtent(normalize(bounds[0], bounds[1]));
122750               var intersects = context.history().intersects(extent).filter(function (entity) {
122751                 return entity.type === 'node' && (!limitToNodes || limitToNodes.has(entity)) && geoPointInPolygon(context.projection(entity.loc), lasso.coordinates) && !context.features().isHidden(entity, graph, entity.geometry(graph));
122752               }); // sort the lassoed nodes as best we can
122753
122754               intersects.sort(function (node1, node2) {
122755                 var parents1 = graph.parentWays(node1);
122756                 var parents2 = graph.parentWays(node2);
122757
122758                 if (parents1.length && parents2.length) {
122759                   // both nodes are vertices
122760                   var sharedParents = utilArrayIntersection(parents1, parents2);
122761
122762                   if (sharedParents.length) {
122763                     var sharedParentNodes = sharedParents[0].nodes; // vertices are members of the same way; sort them in their listed order
122764
122765                     return sharedParentNodes.indexOf(node1.id) - sharedParentNodes.indexOf(node2.id);
122766                   } else {
122767                     // vertices do not share a way; group them by their respective parent ways
122768                     return parseFloat(parents1[0].id.slice(1)) - parseFloat(parents2[0].id.slice(1));
122769                   }
122770                 } else if (parents1.length || parents2.length) {
122771                   // only one node is a vertex; sort standalone points before vertices
122772                   return parents1.length - parents2.length;
122773                 } // both nodes are standalone points; sort left to right
122774
122775
122776                 return node1.loc[0] - node2.loc[0];
122777               });
122778               return intersects.map(function (entity) {
122779                 return entity.id;
122780               });
122781             }
122782
122783             function pointerup() {
122784               select(window).on(_pointerPrefix + 'move.lasso', null).on(_pointerPrefix + 'up.lasso', null);
122785               if (!lasso) return;
122786               var ids = lassoed();
122787               lasso.close();
122788
122789               if (ids.length) {
122790                 context.enter(modeSelect(context, ids));
122791               }
122792             }
122793
122794             selection.on(_pointerPrefix + 'down.lasso', pointerdown);
122795           };
122796
122797           behavior.off = function (selection) {
122798             selection.on(_pointerPrefix + 'down.lasso', null);
122799           };
122800
122801           return behavior;
122802         }
122803
122804         function modeBrowse(context) {
122805           var mode = {
122806             button: 'browse',
122807             id: 'browse',
122808             title: _t('modes.browse.title'),
122809             description: _t('modes.browse.description')
122810           };
122811           var sidebar;
122812
122813           var _selectBehavior;
122814
122815           var _behaviors = [];
122816
122817           mode.selectBehavior = function (val) {
122818             if (!arguments.length) return _selectBehavior;
122819             _selectBehavior = val;
122820             return mode;
122821           };
122822
122823           mode.enter = function () {
122824             if (!_behaviors.length) {
122825               if (!_selectBehavior) _selectBehavior = behaviorSelect(context);
122826               _behaviors = [behaviorPaste(context), behaviorHover(context).on('hover', context.ui().sidebar.hover), _selectBehavior, behaviorLasso(context), modeDragNode(context).behavior, modeDragNote(context).behavior];
122827             }
122828
122829             _behaviors.forEach(context.install); // Get focus on the body.
122830
122831
122832             if (document.activeElement && document.activeElement.blur) {
122833               document.activeElement.blur();
122834             }
122835
122836             if (sidebar) {
122837               context.ui().sidebar.show(sidebar);
122838             } else {
122839               context.ui().sidebar.select(null);
122840             }
122841           };
122842
122843           mode.exit = function () {
122844             context.ui().sidebar.hover.cancel();
122845
122846             _behaviors.forEach(context.uninstall);
122847
122848             if (sidebar) {
122849               context.ui().sidebar.hide();
122850             }
122851           };
122852
122853           mode.sidebar = function (_) {
122854             if (!arguments.length) return sidebar;
122855             sidebar = _;
122856             return mode;
122857           };
122858
122859           mode.operations = function () {
122860             return [operationPaste(context)];
122861           };
122862
122863           return mode;
122864         }
122865
122866         function behaviorAddWay(context) {
122867           var dispatch = dispatch$8('start', 'startFromWay', 'startFromNode');
122868           var draw = behaviorDraw(context);
122869
122870           function behavior(surface) {
122871             draw.on('click', function () {
122872               dispatch.apply('start', this, arguments);
122873             }).on('clickWay', function () {
122874               dispatch.apply('startFromWay', this, arguments);
122875             }).on('clickNode', function () {
122876               dispatch.apply('startFromNode', this, arguments);
122877             }).on('cancel', behavior.cancel).on('finish', behavior.cancel);
122878             context.map().dblclickZoomEnable(false);
122879             surface.call(draw);
122880           }
122881
122882           behavior.off = function (surface) {
122883             surface.call(draw.off);
122884           };
122885
122886           behavior.cancel = function () {
122887             window.setTimeout(function () {
122888               context.map().dblclickZoomEnable(true);
122889             }, 1000);
122890             context.enter(modeBrowse(context));
122891           };
122892
122893           return utilRebind(behavior, dispatch, 'on');
122894         }
122895
122896         function behaviorHash(context) {
122897           // cached window.location.hash
122898           var _cachedHash = null; // allowable latitude range
122899
122900           var _latitudeLimit = 90 - 1e-8;
122901
122902           function computedHashParameters() {
122903             var map = context.map();
122904             var center = map.center();
122905             var zoom = map.zoom();
122906             var precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));
122907             var oldParams = utilObjectOmit(utilStringQs(window.location.hash), ['comment', 'source', 'hashtags', 'walkthrough']);
122908             var newParams = {};
122909             delete oldParams.id;
122910             var selected = context.selectedIDs().filter(function (id) {
122911               return context.hasEntity(id);
122912             });
122913
122914             if (selected.length) {
122915               newParams.id = selected.join(',');
122916             }
122917
122918             newParams.map = zoom.toFixed(2) + '/' + center[1].toFixed(precision) + '/' + center[0].toFixed(precision);
122919             return Object.assign(oldParams, newParams);
122920           }
122921
122922           function computedHash() {
122923             return '#' + utilQsString(computedHashParameters(), true);
122924           }
122925
122926           function computedTitle(includeChangeCount) {
122927             var baseTitle = context.documentTitleBase() || 'iD';
122928             var contextual;
122929             var changeCount;
122930             var titleID;
122931             var selected = context.selectedIDs().filter(function (id) {
122932               return context.hasEntity(id);
122933             });
122934
122935             if (selected.length) {
122936               var firstLabel = utilDisplayLabel(context.entity(selected[0]), context.graph());
122937
122938               if (selected.length > 1) {
122939                 contextual = _t('title.labeled_and_more', {
122940                   labeled: firstLabel,
122941                   count: selected.length - 1
122942                 });
122943               } else {
122944                 contextual = firstLabel;
122945               }
122946
122947               titleID = 'context';
122948             }
122949
122950             if (includeChangeCount) {
122951               changeCount = context.history().difference().summary().length;
122952
122953               if (changeCount > 0) {
122954                 titleID = contextual ? 'changes_context' : 'changes';
122955               }
122956             }
122957
122958             if (titleID) {
122959               return _t('title.format.' + titleID, {
122960                 changes: changeCount,
122961                 base: baseTitle,
122962                 context: contextual
122963               });
122964             }
122965
122966             return baseTitle;
122967           }
122968
122969           function updateTitle(includeChangeCount) {
122970             if (!context.setsDocumentTitle()) return;
122971             var newTitle = computedTitle(includeChangeCount);
122972
122973             if (document.title !== newTitle) {
122974               document.title = newTitle;
122975             }
122976           }
122977
122978           function updateHashIfNeeded() {
122979             if (context.inIntro()) return;
122980             var latestHash = computedHash();
122981
122982             if (_cachedHash !== latestHash) {
122983               _cachedHash = latestHash; // Update the URL hash without affecting the browser navigation stack,
122984               // though unavoidably creating a browser history entry
122985
122986               window.history.replaceState(null, computedTitle(false
122987               /* includeChangeCount */
122988               ), latestHash); // set the title we want displayed for the browser tab/window
122989
122990               updateTitle(true
122991               /* includeChangeCount */
122992               );
122993             }
122994           }
122995
122996           var _throttledUpdate = throttle(updateHashIfNeeded, 500);
122997
122998           var _throttledUpdateTitle = throttle(function () {
122999             updateTitle(true
123000             /* includeChangeCount */
123001             );
123002           }, 500);
123003
123004           function hashchange() {
123005             // ignore spurious hashchange events
123006             if (window.location.hash === _cachedHash) return;
123007             _cachedHash = window.location.hash;
123008             var q = utilStringQs(_cachedHash);
123009             var mapArgs = (q.map || '').split('/').map(Number);
123010
123011             if (mapArgs.length < 3 || mapArgs.some(isNaN)) {
123012               // replace bogus hash
123013               updateHashIfNeeded();
123014             } else {
123015               // don't update if the new hash already reflects the state of iD
123016               if (_cachedHash === computedHash()) return;
123017               var mode = context.mode();
123018               context.map().centerZoom([mapArgs[2], Math.min(_latitudeLimit, Math.max(-_latitudeLimit, mapArgs[1]))], mapArgs[0]);
123019
123020               if (q.id && mode) {
123021                 var ids = q.id.split(',').filter(function (id) {
123022                   return context.hasEntity(id);
123023                 });
123024
123025                 if (ids.length && (mode.id === 'browse' || mode.id === 'select' && !utilArrayIdentical(mode.selectedIDs(), ids))) {
123026                   context.enter(modeSelect(context, ids));
123027                   return;
123028                 }
123029               }
123030
123031               var center = context.map().center();
123032               var dist = geoSphericalDistance(center, [mapArgs[2], mapArgs[1]]);
123033               var maxdist = 500; // Don't allow the hash location to change too much while drawing
123034               // This can happen if the user accidentally hit the back button.  #3996
123035
123036               if (mode && mode.id.match(/^draw/) !== null && dist > maxdist) {
123037                 context.enter(modeBrowse(context));
123038                 return;
123039               }
123040             }
123041           }
123042
123043           function behavior() {
123044             context.map().on('move.behaviorHash', _throttledUpdate);
123045             context.history().on('change.behaviorHash', _throttledUpdateTitle);
123046             context.on('enter.behaviorHash', _throttledUpdate);
123047             select(window).on('hashchange.behaviorHash', hashchange);
123048
123049             if (window.location.hash) {
123050               var q = utilStringQs(window.location.hash);
123051
123052               if (q.id) {
123053                 //if (!context.history().hasRestorableChanges()) {
123054                 // targeting specific features: download, select, and zoom to them
123055                 context.zoomToEntity(q.id.split(',')[0], !q.map); //}
123056               }
123057
123058               if (q.walkthrough === 'true') {
123059                 behavior.startWalkthrough = true;
123060               }
123061
123062               if (q.map) {
123063                 behavior.hadHash = true;
123064               }
123065
123066               hashchange();
123067               updateTitle(false);
123068             }
123069           }
123070
123071           behavior.off = function () {
123072             _throttledUpdate.cancel();
123073
123074             _throttledUpdateTitle.cancel();
123075
123076             context.map().on('move.behaviorHash', null);
123077             context.on('enter.behaviorHash', null);
123078             select(window).on('hashchange.behaviorHash', null);
123079             window.location.hash = '';
123080           };
123081
123082           return behavior;
123083         }
123084
123085         // This is only done in testing because of the performance penalty.
123086
123087         var debug = false; // Reexport just what our tests use, see #4379
123088         var d3 = {
123089           dispatch: dispatch$8,
123090           geoMercator: mercator,
123091           geoProjection: projection,
123092           polygonArea: d3_polygonArea,
123093           polygonCentroid: d3_polygonCentroid,
123094           select: select,
123095           selectAll: selectAll,
123096           timerFlush: timerFlush
123097         };
123098
123099         var iD = /*#__PURE__*/Object.freeze({
123100                 __proto__: null,
123101                 debug: debug,
123102                 d3: d3,
123103                 actionAddEntity: actionAddEntity,
123104                 actionAddMember: actionAddMember,
123105                 actionAddMidpoint: actionAddMidpoint,
123106                 actionAddVertex: actionAddVertex,
123107                 actionChangeMember: actionChangeMember,
123108                 actionChangePreset: actionChangePreset,
123109                 actionChangeTags: actionChangeTags,
123110                 actionCircularize: actionCircularize,
123111                 actionConnect: actionConnect,
123112                 actionCopyEntities: actionCopyEntities,
123113                 actionDeleteMember: actionDeleteMember,
123114                 actionDeleteMultiple: actionDeleteMultiple,
123115                 actionDeleteNode: actionDeleteNode,
123116                 actionDeleteRelation: actionDeleteRelation,
123117                 actionDeleteWay: actionDeleteWay,
123118                 actionDiscardTags: actionDiscardTags,
123119                 actionDisconnect: actionDisconnect,
123120                 actionExtract: actionExtract,
123121                 actionJoin: actionJoin,
123122                 actionMerge: actionMerge,
123123                 actionMergeNodes: actionMergeNodes,
123124                 actionMergePolygon: actionMergePolygon,
123125                 actionMergeRemoteChanges: actionMergeRemoteChanges,
123126                 actionMove: actionMove,
123127                 actionMoveMember: actionMoveMember,
123128                 actionMoveNode: actionMoveNode,
123129                 actionNoop: actionNoop,
123130                 actionOrthogonalize: actionOrthogonalize,
123131                 actionRestrictTurn: actionRestrictTurn,
123132                 actionReverse: actionReverse,
123133                 actionRevert: actionRevert,
123134                 actionRotate: actionRotate,
123135                 actionScale: actionScale,
123136                 actionSplit: actionSplit,
123137                 actionStraightenNodes: actionStraightenNodes,
123138                 actionStraightenWay: actionStraightenWay,
123139                 actionUnrestrictTurn: actionUnrestrictTurn,
123140                 actionReflect: actionReflect,
123141                 actionUpgradeTags: actionUpgradeTags,
123142                 behaviorAddWay: behaviorAddWay,
123143                 behaviorBreathe: behaviorBreathe,
123144                 behaviorDrag: behaviorDrag,
123145                 behaviorDrawWay: behaviorDrawWay,
123146                 behaviorDraw: behaviorDraw,
123147                 behaviorEdit: behaviorEdit,
123148                 behaviorHash: behaviorHash,
123149                 behaviorHover: behaviorHover,
123150                 behaviorLasso: behaviorLasso,
123151                 behaviorOperation: behaviorOperation,
123152                 behaviorPaste: behaviorPaste,
123153                 behaviorSelect: behaviorSelect,
123154                 coreContext: coreContext,
123155                 coreFileFetcher: coreFileFetcher,
123156                 fileFetcher: _mainFileFetcher,
123157                 coreDifference: coreDifference,
123158                 coreGraph: coreGraph,
123159                 coreHistory: coreHistory,
123160                 coreLocalizer: coreLocalizer,
123161                 t: _t,
123162                 localizer: _mainLocalizer,
123163                 coreLocations: coreLocations,
123164                 locationManager: _mainLocations,
123165                 prefs: corePreferences,
123166                 coreTree: coreTree,
123167                 coreUploader: coreUploader,
123168                 coreValidator: coreValidator,
123169                 geoExtent: geoExtent,
123170                 geoLatToMeters: geoLatToMeters,
123171                 geoLonToMeters: geoLonToMeters,
123172                 geoMetersToLat: geoMetersToLat,
123173                 geoMetersToLon: geoMetersToLon,
123174                 geoMetersToOffset: geoMetersToOffset,
123175                 geoOffsetToMeters: geoOffsetToMeters,
123176                 geoScaleToZoom: geoScaleToZoom,
123177                 geoSphericalClosestNode: geoSphericalClosestNode,
123178                 geoSphericalDistance: geoSphericalDistance,
123179                 geoZoomToScale: geoZoomToScale,
123180                 geoAngle: geoAngle,
123181                 geoChooseEdge: geoChooseEdge,
123182                 geoEdgeEqual: geoEdgeEqual,
123183                 geoGetSmallestSurroundingRectangle: geoGetSmallestSurroundingRectangle,
123184                 geoHasLineIntersections: geoHasLineIntersections,
123185                 geoHasSelfIntersections: geoHasSelfIntersections,
123186                 geoRotate: geoRotate,
123187                 geoLineIntersection: geoLineIntersection,
123188                 geoPathHasIntersections: geoPathHasIntersections,
123189                 geoPathIntersections: geoPathIntersections,
123190                 geoPathLength: geoPathLength,
123191                 geoPointInPolygon: geoPointInPolygon,
123192                 geoPolygonContainsPolygon: geoPolygonContainsPolygon,
123193                 geoPolygonIntersectsPolygon: geoPolygonIntersectsPolygon,
123194                 geoViewportEdge: geoViewportEdge,
123195                 geoRawMercator: geoRawMercator,
123196                 geoVecAdd: geoVecAdd,
123197                 geoVecAngle: geoVecAngle,
123198                 geoVecCross: geoVecCross,
123199                 geoVecDot: geoVecDot,
123200                 geoVecEqual: geoVecEqual,
123201                 geoVecFloor: geoVecFloor,
123202                 geoVecInterp: geoVecInterp,
123203                 geoVecLength: geoVecLength,
123204                 geoVecLengthSquare: geoVecLengthSquare,
123205                 geoVecNormalize: geoVecNormalize,
123206                 geoVecNormalizedDot: geoVecNormalizedDot,
123207                 geoVecProject: geoVecProject,
123208                 geoVecSubtract: geoVecSubtract,
123209                 geoVecScale: geoVecScale,
123210                 geoOrthoNormalizedDotProduct: geoOrthoNormalizedDotProduct,
123211                 geoOrthoCalcScore: geoOrthoCalcScore,
123212                 geoOrthoMaxOffsetAngle: geoOrthoMaxOffsetAngle,
123213                 geoOrthoCanOrthogonalize: geoOrthoCanOrthogonalize,
123214                 modeAddArea: modeAddArea,
123215                 modeAddLine: modeAddLine,
123216                 modeAddPoint: modeAddPoint,
123217                 modeAddNote: modeAddNote,
123218                 modeBrowse: modeBrowse,
123219                 modeDragNode: modeDragNode,
123220                 modeDragNote: modeDragNote,
123221                 modeDrawArea: modeDrawArea,
123222                 modeDrawLine: modeDrawLine,
123223                 modeMove: modeMove,
123224                 modeRotate: modeRotate,
123225                 modeSave: modeSave,
123226                 modeSelect: modeSelect,
123227                 modeSelectData: modeSelectData,
123228                 modeSelectError: modeSelectError,
123229                 modeSelectNote: modeSelectNote,
123230                 operationCircularize: operationCircularize,
123231                 operationContinue: operationContinue,
123232                 operationCopy: operationCopy,
123233                 operationDelete: operationDelete,
123234                 operationDisconnect: operationDisconnect,
123235                 operationDowngrade: operationDowngrade,
123236                 operationExtract: operationExtract,
123237                 operationMerge: operationMerge,
123238                 operationMove: operationMove,
123239                 operationOrthogonalize: operationOrthogonalize,
123240                 operationPaste: operationPaste,
123241                 operationReflectShort: operationReflectShort,
123242                 operationReflectLong: operationReflectLong,
123243                 operationReverse: operationReverse,
123244                 operationRotate: operationRotate,
123245                 operationSplit: operationSplit,
123246                 operationStraighten: operationStraighten,
123247                 osmChangeset: osmChangeset,
123248                 osmEntity: osmEntity,
123249                 osmNode: osmNode,
123250                 osmNote: osmNote,
123251                 osmRelation: osmRelation,
123252                 osmWay: osmWay,
123253                 QAItem: QAItem,
123254                 osmIntersection: osmIntersection,
123255                 osmTurn: osmTurn,
123256                 osmInferRestriction: osmInferRestriction,
123257                 osmLanes: osmLanes,
123258                 osmOldMultipolygonOuterMemberOfRelation: osmOldMultipolygonOuterMemberOfRelation,
123259                 osmIsOldMultipolygonOuterMember: osmIsOldMultipolygonOuterMember,
123260                 osmOldMultipolygonOuterMember: osmOldMultipolygonOuterMember,
123261                 osmJoinWays: osmJoinWays,
123262                 get osmAreaKeys () { return osmAreaKeys; },
123263                 osmSetAreaKeys: osmSetAreaKeys,
123264                 osmTagSuggestingArea: osmTagSuggestingArea,
123265                 get osmPointTags () { return osmPointTags; },
123266                 osmSetPointTags: osmSetPointTags,
123267                 get osmVertexTags () { return osmVertexTags; },
123268                 osmSetVertexTags: osmSetVertexTags,
123269                 osmNodeGeometriesForTags: osmNodeGeometriesForTags,
123270                 osmOneWayTags: osmOneWayTags,
123271                 osmPavedTags: osmPavedTags,
123272                 osmIsInterestingTag: osmIsInterestingTag,
123273                 osmRoutableHighwayTagValues: osmRoutableHighwayTagValues,
123274                 osmFlowingWaterwayTagValues: osmFlowingWaterwayTagValues,
123275                 osmRailwayTrackTagValues: osmRailwayTrackTagValues,
123276                 presetCategory: presetCategory,
123277                 presetCollection: presetCollection,
123278                 presetField: presetField,
123279                 presetPreset: presetPreset,
123280                 presetManager: _mainPresetIndex,
123281                 presetIndex: presetIndex,
123282                 rendererBackgroundSource: rendererBackgroundSource,
123283                 rendererBackground: rendererBackground,
123284                 rendererFeatures: rendererFeatures,
123285                 rendererMap: rendererMap,
123286                 rendererPhotos: rendererPhotos,
123287                 rendererTileLayer: rendererTileLayer,
123288                 services: services,
123289                 serviceKeepRight: serviceKeepRight,
123290                 serviceImproveOSM: serviceImproveOSM,
123291                 serviceOsmose: serviceOsmose,
123292                 serviceMapillary: serviceMapillary,
123293                 serviceMapRules: serviceMapRules,
123294                 serviceNominatim: serviceNominatim,
123295                 serviceNsi: serviceNsi,
123296                 serviceKartaview: serviceKartaview,
123297                 serviceOsm: serviceOsm,
123298                 serviceOsmWikibase: serviceOsmWikibase,
123299                 serviceStreetside: serviceStreetside,
123300                 serviceTaginfo: serviceTaginfo,
123301                 serviceVectorTile: serviceVectorTile,
123302                 serviceWikidata: serviceWikidata,
123303                 serviceWikipedia: serviceWikipedia,
123304                 svgAreas: svgAreas,
123305                 svgData: svgData,
123306                 svgDebug: svgDebug,
123307                 svgDefs: svgDefs,
123308                 svgKeepRight: svgKeepRight,
123309                 svgIcon: svgIcon,
123310                 svgGeolocate: svgGeolocate,
123311                 svgLabels: svgLabels,
123312                 svgLayers: svgLayers,
123313                 svgLines: svgLines,
123314                 svgMapillaryImages: svgMapillaryImages,
123315                 svgMapillarySigns: svgMapillarySigns,
123316                 svgMidpoints: svgMidpoints,
123317                 svgNotes: svgNotes,
123318                 svgMarkerSegments: svgMarkerSegments,
123319                 svgKartaviewImages: svgKartaviewImages,
123320                 svgOsm: svgOsm,
123321                 svgPassiveVertex: svgPassiveVertex,
123322                 svgPath: svgPath,
123323                 svgPointTransform: svgPointTransform,
123324                 svgPoints: svgPoints,
123325                 svgRelationMemberTags: svgRelationMemberTags,
123326                 svgSegmentWay: svgSegmentWay,
123327                 svgStreetside: svgStreetside,
123328                 svgTagClasses: svgTagClasses,
123329                 svgTagPattern: svgTagPattern,
123330                 svgTouch: svgTouch,
123331                 svgTurns: svgTurns,
123332                 svgVertices: svgVertices,
123333                 uiFieldDefaultCheck: uiFieldCheck,
123334                 uiFieldOnewayCheck: uiFieldCheck,
123335                 uiFieldCheck: uiFieldCheck,
123336                 uiFieldManyCombo: uiFieldCombo,
123337                 uiFieldMultiCombo: uiFieldCombo,
123338                 uiFieldNetworkCombo: uiFieldCombo,
123339                 uiFieldSemiCombo: uiFieldCombo,
123340                 uiFieldTypeCombo: uiFieldCombo,
123341                 uiFieldCombo: uiFieldCombo,
123342                 uiFieldUrl: uiFieldText,
123343                 uiFieldIdentifier: uiFieldText,
123344                 uiFieldNumber: uiFieldText,
123345                 uiFieldTel: uiFieldText,
123346                 uiFieldEmail: uiFieldText,
123347                 uiFieldText: uiFieldText,
123348                 uiFieldAccess: uiFieldAccess,
123349                 uiFieldAddress: uiFieldAddress,
123350                 uiFieldCycleway: uiFieldCycleway,
123351                 uiFieldLanes: uiFieldLanes,
123352                 uiFieldLocalized: uiFieldLocalized,
123353                 uiFieldRoadheight: uiFieldRoadheight,
123354                 uiFieldRoadspeed: uiFieldRoadspeed,
123355                 uiFieldStructureRadio: uiFieldRadio,
123356                 uiFieldRadio: uiFieldRadio,
123357                 uiFieldRestrictions: uiFieldRestrictions,
123358                 uiFieldTextarea: uiFieldTextarea,
123359                 uiFieldWikidata: uiFieldWikidata,
123360                 uiFieldWikipedia: uiFieldWikipedia,
123361                 uiFields: uiFields,
123362                 uiIntro: uiIntro,
123363                 uiPanelBackground: uiPanelBackground,
123364                 uiPanelHistory: uiPanelHistory,
123365                 uiPanelLocation: uiPanelLocation,
123366                 uiPanelMeasurement: uiPanelMeasurement,
123367                 uiInfoPanels: uiInfoPanels,
123368                 uiPaneBackground: uiPaneBackground,
123369                 uiPaneHelp: uiPaneHelp,
123370                 uiPaneIssues: uiPaneIssues,
123371                 uiPaneMapData: uiPaneMapData,
123372                 uiPanePreferences: uiPanePreferences,
123373                 uiSectionBackgroundDisplayOptions: uiSectionBackgroundDisplayOptions,
123374                 uiSectionBackgroundList: uiSectionBackgroundList,
123375                 uiSectionBackgroundOffset: uiSectionBackgroundOffset,
123376                 uiSectionChanges: uiSectionChanges,
123377                 uiSectionDataLayers: uiSectionDataLayers,
123378                 uiSectionEntityIssues: uiSectionEntityIssues,
123379                 uiSectionFeatureType: uiSectionFeatureType,
123380                 uiSectionMapFeatures: uiSectionMapFeatures,
123381                 uiSectionMapStyleOptions: uiSectionMapStyleOptions,
123382                 uiSectionOverlayList: uiSectionOverlayList,
123383                 uiSectionPhotoOverlays: uiSectionPhotoOverlays,
123384                 uiSectionPresetFields: uiSectionPresetFields,
123385                 uiSectionPrivacy: uiSectionPrivacy,
123386                 uiSectionRawMemberEditor: uiSectionRawMemberEditor,
123387                 uiSectionRawMembershipEditor: uiSectionRawMembershipEditor,
123388                 uiSectionRawTagEditor: uiSectionRawTagEditor,
123389                 uiSectionSelectionList: uiSectionSelectionList,
123390                 uiSectionValidationIssues: uiSectionValidationIssues,
123391                 uiSectionValidationOptions: uiSectionValidationOptions,
123392                 uiSectionValidationRules: uiSectionValidationRules,
123393                 uiSectionValidationStatus: uiSectionValidationStatus,
123394                 uiSettingsCustomBackground: uiSettingsCustomBackground,
123395                 uiSettingsCustomData: uiSettingsCustomData,
123396                 uiInit: uiInit,
123397                 uiAccount: uiAccount,
123398                 uiAttribution: uiAttribution,
123399                 uiChangesetEditor: uiChangesetEditor,
123400                 uiCmd: uiCmd,
123401                 uiCombobox: uiCombobox,
123402                 uiCommit: uiCommit,
123403                 uiCommitWarnings: uiCommitWarnings,
123404                 uiConfirm: uiConfirm,
123405                 uiConflicts: uiConflicts,
123406                 uiContributors: uiContributors,
123407                 uiCurtain: uiCurtain,
123408                 uiDataEditor: uiDataEditor,
123409                 uiDataHeader: uiDataHeader,
123410                 uiDisclosure: uiDisclosure,
123411                 uiEditMenu: uiEditMenu,
123412                 uiEntityEditor: uiEntityEditor,
123413                 uiFeatureInfo: uiFeatureInfo,
123414                 uiFeatureList: uiFeatureList,
123415                 uiField: uiField,
123416                 uiFieldHelp: uiFieldHelp,
123417                 uiFlash: uiFlash,
123418                 uiFormFields: uiFormFields,
123419                 uiFullScreen: uiFullScreen,
123420                 uiGeolocate: uiGeolocate,
123421                 uiImproveOsmComments: uiImproveOsmComments,
123422                 uiImproveOsmDetails: uiImproveOsmDetails,
123423                 uiImproveOsmEditor: uiImproveOsmEditor,
123424                 uiImproveOsmHeader: uiImproveOsmHeader,
123425                 uiInfo: uiInfo,
123426                 uiInspector: uiInspector,
123427                 uiIssuesInfo: uiIssuesInfo,
123428                 uiKeepRightDetails: uiKeepRightDetails,
123429                 uiKeepRightEditor: uiKeepRightEditor,
123430                 uiKeepRightHeader: uiKeepRightHeader,
123431                 uiLasso: uiLasso,
123432                 uiLoading: uiLoading,
123433                 uiMapInMap: uiMapInMap,
123434                 uiModal: uiModal,
123435                 uiNotice: uiNotice,
123436                 uiNoteComments: uiNoteComments,
123437                 uiNoteEditor: uiNoteEditor,
123438                 uiNoteHeader: uiNoteHeader,
123439                 uiNoteReport: uiNoteReport,
123440                 uiPopover: uiPopover,
123441                 uiPresetIcon: uiPresetIcon,
123442                 uiPresetList: uiPresetList,
123443                 uiRestore: uiRestore,
123444                 uiScale: uiScale,
123445                 uiSidebar: uiSidebar,
123446                 uiSourceSwitch: uiSourceSwitch,
123447                 uiSpinner: uiSpinner,
123448                 uiSplash: uiSplash,
123449                 uiStatus: uiStatus,
123450                 uiSuccess: uiSuccess,
123451                 uiTagReference: uiTagReference,
123452                 uiToggle: uiToggle,
123453                 uiTooltip: uiTooltip,
123454                 uiVersion: uiVersion,
123455                 uiViewOnOSM: uiViewOnOSM,
123456                 uiViewOnKeepRight: uiViewOnKeepRight,
123457                 uiZoom: uiZoom,
123458                 utilAesEncrypt: utilAesEncrypt,
123459                 utilAesDecrypt: utilAesDecrypt,
123460                 utilArrayChunk: utilArrayChunk,
123461                 utilArrayDifference: utilArrayDifference,
123462                 utilArrayFlatten: utilArrayFlatten,
123463                 utilArrayGroupBy: utilArrayGroupBy,
123464                 utilArrayIdentical: utilArrayIdentical,
123465                 utilArrayIntersection: utilArrayIntersection,
123466                 utilArrayUnion: utilArrayUnion,
123467                 utilArrayUniq: utilArrayUniq,
123468                 utilArrayUniqBy: utilArrayUniqBy,
123469                 utilAsyncMap: utilAsyncMap,
123470                 utilCleanTags: utilCleanTags,
123471                 utilCombinedTags: utilCombinedTags,
123472                 utilDeepMemberSelector: utilDeepMemberSelector,
123473                 utilDetect: utilDetect,
123474                 utilDisplayName: utilDisplayName,
123475                 utilDisplayNameForPath: utilDisplayNameForPath,
123476                 utilDisplayType: utilDisplayType,
123477                 utilDisplayLabel: utilDisplayLabel,
123478                 utilEntityRoot: utilEntityRoot,
123479                 utilEditDistance: utilEditDistance,
123480                 utilEntityAndDeepMemberIDs: utilEntityAndDeepMemberIDs,
123481                 utilEntityOrMemberSelector: utilEntityOrMemberSelector,
123482                 utilEntityOrDeepMemberSelector: utilEntityOrDeepMemberSelector,
123483                 utilEntitySelector: utilEntitySelector,
123484                 utilFastMouse: utilFastMouse,
123485                 utilFunctor: utilFunctor,
123486                 utilGetAllNodes: utilGetAllNodes,
123487                 utilGetSetValue: utilGetSetValue,
123488                 utilHashcode: utilHashcode,
123489                 utilHighlightEntities: utilHighlightEntities,
123490                 utilKeybinding: utilKeybinding,
123491                 utilNoAuto: utilNoAuto,
123492                 utilObjectOmit: utilObjectOmit,
123493                 utilCompareIDs: utilCompareIDs,
123494                 utilOldestID: utilOldestID,
123495                 utilPrefixCSSProperty: utilPrefixCSSProperty,
123496                 utilPrefixDOMProperty: utilPrefixDOMProperty,
123497                 utilQsString: utilQsString,
123498                 utilRebind: utilRebind,
123499                 utilSafeClassName: utilSafeClassName,
123500                 utilSetTransform: utilSetTransform,
123501                 utilSessionMutex: utilSessionMutex,
123502                 utilStringQs: utilStringQs,
123503                 utilTagDiff: utilTagDiff,
123504                 utilTagText: utilTagText,
123505                 utilTiler: utilTiler,
123506                 utilTotalExtent: utilTotalExtent,
123507                 utilTriggerEvent: utilTriggerEvent,
123508                 utilUnicodeCharsCount: utilUnicodeCharsCount,
123509                 utilUnicodeCharsTruncated: utilUnicodeCharsTruncated,
123510                 utilUniqueDomId: utilUniqueDomId,
123511                 utilWrap: utilWrap,
123512                 validationAlmostJunction: validationAlmostJunction,
123513                 validationCloseNodes: validationCloseNodes,
123514                 validationCrossingWays: validationCrossingWays,
123515                 validationDisconnectedWay: validationDisconnectedWay,
123516                 validationFormatting: validationFormatting,
123517                 validationHelpRequest: validationHelpRequest,
123518                 validationImpossibleOneway: validationImpossibleOneway,
123519                 validationIncompatibleSource: validationIncompatibleSource,
123520                 validationMaprules: validationMaprules,
123521                 validationMismatchedGeometry: validationMismatchedGeometry,
123522                 validationMissingRole: validationMissingRole,
123523                 validationMissingTag: validationMissingTag,
123524                 validationOutdatedTags: validationOutdatedTags,
123525                 validationPrivateData: validationPrivateData,
123526                 validationSuspiciousName: validationSuspiciousName,
123527                 validationUnsquareWay: validationUnsquareWay
123528         });
123529
123530         window.requestIdleCallback = window.requestIdleCallback || function (cb) {
123531           var start = Date.now();
123532           return window.requestAnimationFrame(function () {
123533             cb({
123534               didTimeout: false,
123535               timeRemaining: function timeRemaining() {
123536                 return Math.max(0, 50 - (Date.now() - start));
123537               }
123538             });
123539           });
123540         };
123541
123542         window.cancelIdleCallback = window.cancelIdleCallback || function (id) {
123543           window.cancelAnimationFrame(id);
123544         };
123545         window.iD = iD;
123546
123547 }());