summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2019-05-21 04:28:47 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2019-05-21 04:28:47 +0000
commitd2ec17d30e86f0026a59966856952bfbd6390a2f (patch)
treedc3f99a92ff948d97e2ebba4090afa933c3c7cb2
parentAdding upstream version 3.1.1. (diff)
downloadbrowserpass-d2ec17d30e86f0026a59966856952bfbd6390a2f.tar.xz
browserpass-d2ec17d30e86f0026a59966856952bfbd6390a2f.zip
Adding debian version 3.1.1-1.debian/3.1.1-1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
-rw-r--r--debian/README.source4
-rw-r--r--debian/background.dist.js.diff21
-rw-r--r--debian/changelog57
-rw-r--r--debian/compat1
-rw-r--r--debian/control29
-rw-r--r--debian/copyright81
-rw-r--r--debian/dirs5
-rw-r--r--debian/install10
-rw-r--r--debian/js/background.dist.js7264
-rw-r--r--debian/js/inject.dist.js417
-rw-r--r--debian/js/options.dist.js2138
-rw-r--r--debian/js/popup.dist.js12243
-rw-r--r--debian/links11
-rw-r--r--debian/maintscript3
-rw-r--r--debian/node_modules/README.txt16
-rw-r--r--debian/node_modules/charenc/LICENSE.mkd27
-rw-r--r--debian/node_modules/charenc/README.js1
-rw-r--r--debian/node_modules/charenc/charenc.js33
-rw-r--r--debian/node_modules/charenc/package.json54
-rw-r--r--debian/node_modules/chrome-extension-async/.babelrc5
-rw-r--r--debian/node_modules/chrome-extension-async/CODE_OF_CONDUCT.md46
-rw-r--r--debian/node_modules/chrome-extension-async/LICENSE21
-rw-r--r--debian/node_modules/chrome-extension-async/README.md262
-rw-r--r--debian/node_modules/chrome-extension-async/bower.json24
-rw-r--r--debian/node_modules/chrome-extension-async/chrome-extension-async.d.ts7709
-rw-r--r--debian/node_modules/chrome-extension-async/chrome-extension-async.js242
-rw-r--r--debian/node_modules/chrome-extension-async/execute-async-function.d.ts20
-rw-r--r--debian/node_modules/chrome-extension-async/execute-async-function.es5.js207
-rw-r--r--debian/node_modules/chrome-extension-async/execute-async-function.js111
-rw-r--r--debian/node_modules/chrome-extension-async/package.json60
-rw-r--r--debian/node_modules/crypt/LICENSE.mkd27
-rw-r--r--debian/node_modules/crypt/README.mkd1
-rw-r--r--debian/node_modules/crypt/crypt.js96
-rw-r--r--debian/node_modules/crypt/package.json52
-rw-r--r--debian/node_modules/sha1/.npmignore1
-rw-r--r--debian/node_modules/sha1/.travis.yml4
-rw-r--r--debian/node_modules/sha1/LICENSE27
-rw-r--r--debian/node_modules/sha1/README.md88
-rw-r--r--debian/node_modules/sha1/package.json67
-rw-r--r--debian/node_modules/sha1/sha1.js82
-rw-r--r--debian/node_modules/sha1/test.js25
-rw-r--r--debian/patches/extension_makefile.diff33
-rw-r--r--debian/patches/series2
-rwxr-xr-xdebian/rules28
-rw-r--r--debian/source/format1
-rw-r--r--debian/source/lintian-overrides6
-rw-r--r--debian/watch7
47 files changed, 31669 insertions, 0 deletions
diff --git a/debian/README.source b/debian/README.source
new file mode 100644
index 0000000..aac19ec
--- /dev/null
+++ b/debian/README.source
@@ -0,0 +1,4 @@
+The file background.js is generated by browserify. Unfortunately as of this
+writing browserify is not packaged for Debian, therefore a preprocessed version
+is provided as debian/background.js. It is build from the sources provided here.
+
diff --git a/debian/background.dist.js.diff b/debian/background.dist.js.diff
new file mode 100644
index 0000000..7d308b7
--- /dev/null
+++ b/debian/background.dist.js.diff
@@ -0,0 +1,21 @@
+--- a/debian/js/background.dist.js 2019-04-23 20:00:23.083380545 +0200
++++ a/debian/js/background.dist.js 2019-04-23 20:05:00.572614189 +0200
+@@ -1062,12 +1062,12 @@
+ if (details.reason === "install") {
+ if (localStorage.getItem("installed") === null) {
+ localStorage.setItem("installed", Date.now());
+- show(
+- "installed",
+- "browserpass: Install native host app",
+- "Remember to install the complementary native host app to use this extension.\n" +
+- "Instructions here: https://github.com/browserpass/browserpass-native"
+- );
++// show(
++// "installed",
++// "browserpass: Install native host app",
++// "Remember to install the complementary native host app to use this extension.\n" +
++// "Instructions here: https://github.com/browserpass/browserpass-native"
++// );
+ }
+ } else if (details.reason === "update") {
+ var changelog = {
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..5d0b3d3
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,57 @@
+browserpass (3.1.1-1) unstable; urgency=medium
+
+ * New upstream version
+ * Updated watch file for new split archives.
+ * Updated go import path to new split archive.
+ * Adjust packaging to the new archive layout.
+ * browserify-lite creates non functioning javascript, so we go with the
+ browserified files provided by upstream.
+
+ -- Michael Meskes <meskes@debian.org> Wed, 17 Apr 2019 13:33:59 +0200
+
+browserpass (2.0.22-2) unstable; urgency=medium
+
+ * Document provided background.js file and remove superfluous manifest.json.
+ (Closes: #921484)
+ * With chromium now including all extensions there is no need anymore for us
+ to provide a solution.
+ * tldjs is in the archive now, no need to ship it with brwoserpass anymore.
+ * Bumped Standards-Version, no changes needed.
+
+ -- Michael Meskes <meskes@debian.org> Wed, 06 Feb 2019 10:29:50 +0100
+
+browserpass (2.0.22-1) unstable; urgency=medium
+
+ * Set Built-Using field.
+ Thanks to Michael Stapelberg <stapelberg@debian.org> (Closes: #892118)
+ * New upstream version 2.0.22 (Closes: #903050)
+ * Added tldjs sources while the package is still in NEW.
+
+ -- Michael Meskes <meskes@debian.org> Fri, 30 Mar 2018 20:14:46 +0100
+
+browserpass (2.0.11+dfsg-2) unstable; urgency=medium
+
+ * Fixed typo in Depends line
+
+ -- Michael Meskes <meskes@debian.org> Mon, 19 Feb 2018 10:25:56 +0100
+
+browserpass (2.0.11+dfsg-1) unstable; urgency=medium
+
+ * Repack to get rid of unused nodejs modules some of which were partly
+ minified.
+ * Added firefox-esr as alternative (Closes: #890729)
+ * Added file to load all extension into chromium
+ * Fix path of example installation
+ * Added all contributors to copyright file (Closes: #890717)
+ * Fixed watch file for re-packaged version number.
+ * Removed empty /usr/bin directory.
+ * Document which files were excluded from the released tarball.
+ * Re-added lost shared library dependencies
+
+ -- Michael Meskes <meskes@debian.org> Sun, 18 Feb 2018 10:56:29 +0100
+
+browserpass (2.0.11-1) unstable; urgency=medium
+
+ * Initial release (Closes: #890331)
+
+ -- Michael Meskes <meskes@debian.org> Thu, 15 Feb 2018 09:45:09 +0100
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..b4de394
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+11
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..f7e4241
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,29 @@
+Source: browserpass
+Section: web
+Priority: optional
+Maintainer: Debian Mozilla Extension Maintainers <pkg-mozext-maintainers@lists.alioth.debian.org>
+Uploaders: Michael Meskes <meskes@debian.org>
+Build-Depends: debhelper (>= 11),
+ dh-golang,
+ golang-go,
+ golang-github-gokyle-twofactor-dev,
+ golang-github-mattn-go-zglob-dev,
+ golang-github-sahilm-fuzzy-dev,
+ node-less
+Standards-Version: 4.3.0
+Homepage: https://github.com/browserpass
+Vcs-Git: https://salsa.debian.org/webext-team/browserpass.git
+Vcs-Browser: https://salsa.debian.org/webext-team/browserpass
+XS-Go-Import-Path: github.com/browserpass
+
+Package: webext-browserpass
+Architecture: any
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Recommends: firefox (>= 50) | firefox-esr (>= 50) | chromium
+Built-Using: ${misc:Built-Using}
+Description: web extension for the password manager pass
+ webext-browserpass is a Firefox/Chromium extension for the password manager
+ pass. It retrieves your decrypted passwords for the current domain and allows
+ you to auto-fill login forms, as well as copy it to clipboard. If you have
+ multiple logins for the current site, the extension shows you a list of
+ usernames to choose from.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..03bbb1c
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,81 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: browserpass
+Source: https://github.com/dannyvankooten/browserpass
+Files-Excluded: node_modules/*
+
+Files: *
+Copyright: 2016 Danny van Kooten <dannyvankooten@gmail.com>
+ 2017 Maxim Baz <github@maximbaz.com>
+ Aaron Bieber <aaron@bolddaemon.com>
+ Artur Krajewski <mid@kc.com.pl>
+ Christoph Böhmwalder <christoph@boehmwalder.at>
+ Erik Terpstra <erterpstra@gmail.com>
+ Felix Bechstein <f@ub0r.de>
+ Heiko Carrasco <heiko.carrasco@yahoo.com>
+ Iwan Timmer <irtimmer@gmail.com>
+ Jannick Fahlbusch <git@jf-projects.de>
+ Jan-Philipp Litza <janphilipp@litza.de>
+ Kieran Colford <kieran@kcolford.com>
+ Marek Fajkus <marek.faj@gmail.com>
+ Paul Bienkowski <pb@opatut.de>
+ Thor77 <thor77@thor77.org>
+ Weker01 <weker01@gmail.com>
+License: MIT
+
+Files: debian/*
+Copyright: 2018 Michael Meskes <meskes@debian.org>
+License: GPL-2+
+ This package is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ .
+ This package is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ .
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>
+ .
+ On Debian systems, the complete text of the GNU General
+ Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
+
+Files: debian/background.js
+Copyright: 2016 Danny van Kooten <dannyvankooten@gmail.com>
+ 2017 Maxim Baz <github@maximbaz.com>
+ Aaron Bieber <aaron@bolddaemon.com>
+ Artur Krajewski <mid@kc.com.pl>
+ Christoph Böhmwalder <christoph@boehmwalder.at>
+ Erik Terpstra <erterpstra@gmail.com>
+ Felix Bechstein <f@ub0r.de>
+ Heiko Carrasco <heiko.carrasco@yahoo.com>
+ Iwan Timmer <irtimmer@gmail.com>
+ Jannick Fahlbusch <git@jf-projects.de>
+ Jan-Philipp Litza <janphilipp@litza.de>
+ Kieran Colford <kieran@kcolford.com>
+ Marek Fajkus <marek.faj@gmail.com>
+ Paul Bienkowski <pb@opatut.de>
+ Thor77 <thor77@thor77.org>
+ Weker01 <weker01@gmail.com>
+License: MIT
+
+License: MIT
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights to
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is furnished to do
+ so, subject to the following conditions:
+ .
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+ .
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+
diff --git a/debian/dirs b/debian/dirs
new file mode 100644
index 0000000..6937043
--- /dev/null
+++ b/debian/dirs
@@ -0,0 +1,5 @@
+/usr/lib/browserpass
+/usr/share/chromium/extensions/
+/etc/chromium/native-messaging-hosts/
+/usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/fonts
+/usr/lib/mozilla/native-messaging-hosts/
diff --git a/debian/install b/debian/install
new file mode 100644
index 0000000..5dc6e5d
--- /dev/null
+++ b/debian/install
@@ -0,0 +1,10 @@
+chromium/css /usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/browserpass@maximbaz.com
+chromium/icon.png /usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/browserpass@maximbaz.com
+chromium/icon16.png /usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/browserpass@maximbaz.com
+chromium/options /usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/browserpass@maximbaz.com
+chromium/popup /usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/browserpass@maximbaz.com
+chromium/icon.svg /usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/browserpass@maximbaz.com
+
+firefox/manifest.json /usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/browserpass@maximbaz.com
+
+chromium/manifest.json /usr/share/chromium/extensions/browserpass
diff --git a/debian/js/background.dist.js b/debian/js/background.dist.js
new file mode 100644
index 0000000..eacb78e
--- /dev/null
+++ b/debian/js/background.dist.js
@@ -0,0 +1,7264 @@
+(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
+//-------------------------------- Background initialisation --------------------------------//
+"use strict";
+
+require("chrome-extension-async");
+const sha1 = require("sha1");
+const idb = require("idb");
+const helpers = require("./helpers");
+
+// native application id
+var appID = "com.github.browserpass.native";
+
+// OTP extension id
+var otpID = [
+ "afjjoildnccgmjbblnklbohcbjehjaph", // webstore releases
+ "jbnpmhhgnchcoljeobafpinmchnpdpin", // github releases
+ "fcmmcnalhjjejhpnlfnddimcdlmpkbdf", // local unpacked
+ "browserpass-otp@maximbaz.com" // firefox
+];
+
+// default settings
+var defaultSettings = {
+ autoSubmit: false,
+ gpgPath: null,
+ stores: {},
+ foreignFills: {},
+ username: null
+};
+
+var authListeners = {};
+
+chrome.browserAction.setBadgeBackgroundColor({
+ color: "#666"
+});
+
+// watch for tab updates
+chrome.tabs.onUpdated.addListener((tabId, info) => {
+ // unregister any auth listeners for this tab
+ if (info.status === "complete") {
+ if (authListeners[tabId]) {
+ chrome.webRequest.onAuthRequired.removeListener(authListeners[tabId]);
+ delete authListeners[tabId];
+ }
+ }
+
+ // refresh badge counter when url in a tab changes
+ if (info.url) {
+ updateMatchingPasswordsCount(tabId);
+ }
+});
+
+// handle incoming messages
+chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
+ receiveMessage(message, sender, sendResponse);
+
+ // allow async responses after this function returns
+ return true;
+});
+
+// handle keyboard shortcuts
+chrome.commands.onCommand.addListener(async command => {
+ switch (command) {
+ case "fillBest":
+ try {
+ const settings = await getFullSettings();
+ if (settings.tab.url.match(/^(chrome|about):/)) {
+ // only fill on real domains
+ return;
+ }
+ handleMessage(settings, { action: "listFiles" }, listResults => {
+ const logins = helpers.prepareLogins(listResults.files, settings);
+ const bestLogin = helpers.filterSortLogins(logins, "", true)[0];
+ if (bestLogin) {
+ handleMessage(settings, { action: "fill", login: bestLogin }, () => {});
+ }
+ });
+ } catch (e) {
+ console.log(e);
+ }
+ break;
+ }
+});
+
+chrome.runtime.onInstalled.addListener(onExtensionInstalled);
+
+//----------------------------------- Function definitions ----------------------------------//
+
+/**
+ * Set badge text with the number of matching password entries
+ *
+ * @since 3.0.0
+ *
+ * @param int tabId Tab id
+ * @return void
+ */
+async function updateMatchingPasswordsCount(tabId) {
+ try {
+ const settings = await getFullSettings();
+ var response = await hostAction(settings, "list");
+ if (response.status != "ok") {
+ throw new Error(JSON.stringify(response));
+ }
+
+ // Get tab info
+ try {
+ const tab = await chrome.tabs.get(tabId);
+ settings.host = new URL(tab.url).hostname;
+ } catch (e) {
+ throw new Error(`Unable to determine domain of the tab with id ${tabId}`);
+ }
+
+ const logins = helpers.prepareLogins(response.data.files, settings);
+ const matchedPasswordsCount = logins.reduce(
+ (acc, login) => acc + (login.recent.count || login.inCurrentDomain ? 1 : 0),
+ 0
+ );
+
+ if (matchedPasswordsCount) {
+ // Set badge for the current tab
+ chrome.browserAction.setBadgeText({
+ text: "" + matchedPasswordsCount,
+ tabId: tabId
+ });
+ }
+ } catch (e) {
+ console.log(e);
+ }
+}
+
+/**
+ * Copy text to clipboard
+ *
+ * @since 3.0.0
+ *
+ * @param string text Text to copy
+ * @return void
+ */
+function copyToClipboard(text) {
+ document.addEventListener(
+ "copy",
+ function(e) {
+ e.clipboardData.setData("text/plain", text);
+ e.preventDefault();
+ },
+ { once: true }
+ );
+ document.execCommand("copy");
+}
+
+/**
+ * Save login to recent list for current domain
+ *
+ * @since 3.0.0
+ *
+ * @param object settings Settings object
+ * @param string host Hostname
+ * @param object login Login object
+ * @param bool remove Remove this item from recent history
+ * @return void
+ */
+async function saveRecent(settings, login, remove = false) {
+ var ignoreInterval = 60000; // 60 seconds - don't increment counter twice within this window
+
+ // save store timestamp
+ localStorage.setItem("recent:" + login.store.id, JSON.stringify(Date.now()));
+
+ // update login usage count & timestamp
+ if (Date.now() > login.recent.when + ignoreInterval) {
+ login.recent.count++;
+ }
+ login.recent.when = Date.now();
+ settings.recent[sha1(settings.host + sha1(login.store.id + sha1(login.login)))] = login.recent;
+
+ // save to local storage
+ localStorage.setItem("recent", JSON.stringify(settings.recent));
+
+ // a new entry was added to the popup matching list, need to refresh the count
+ if (!login.inCurrentDomain && login.recent.count === 1) {
+ updateMatchingPasswordsCount(settings.tab.id);
+ }
+
+ // save to usage log
+ try {
+ const DB_VERSION = 1;
+ const db = await idb.openDB("browserpass", DB_VERSION, {
+ upgrade(db) {
+ db.createObjectStore("log", { keyPath: "time" });
+ }
+ });
+ await db.add("log", { time: Date.now(), host: settings.host, login: login.login });
+ } catch {
+ // ignore any errors and proceed without saving a log entry to Indexed DB
+ }
+}
+
+/**
+ * Call injected code to fill the form
+ *
+ * @param object settings Settings object
+ * @param object request Request details
+ * @param boolean allFrames Dispatch to all frames
+ * @param boolean allowForeign Allow foreign-origin iframes
+ * @param boolean allowNoSecret Allow forms that don't contain a password field
+ * @return array list of filled fields
+ */
+async function dispatchFill(settings, request, allFrames, allowForeign, allowNoSecret) {
+ request = Object.assign(deepCopy(request), {
+ allowForeign: allowForeign,
+ allowNoSecret: allowNoSecret,
+ foreignFills: settings.foreignFills[settings.host] || {}
+ });
+
+ let perFrameResults = await chrome.tabs.executeScript(settings.tab.id, {
+ allFrames: allFrames,
+ code: `window.browserpass.fillLogin(${JSON.stringify(request)});`
+ });
+
+ // merge filled fields into a single array
+ let filledFields = perFrameResults
+ .reduce((merged, frameResult) => merged.concat(frameResult.filledFields), [])
+ .filter((val, i, merged) => merged.indexOf(val) === i);
+
+ // if user answered a foreign-origin confirmation,
+ // store the answers in the settings
+ let foreignFillsChanged = false;
+ for (let frame of perFrameResults) {
+ if (typeof frame.foreignFill !== "undefined") {
+ if (typeof settings.foreignFills[settings.host] === "undefined") {
+ settings.foreignFills[settings.host] = {};
+ }
+ settings.foreignFills[settings.host][frame.foreignOrigin] = frame.foreignFill;
+ foreignFillsChanged = true;
+ }
+ }
+ if (foreignFillsChanged) {
+ await saveSettings(settings);
+ }
+
+ return filledFields;
+}
+
+/**
+ * Call injected code to focus or submit the form
+ *
+ * @param object settings Settings object
+ * @param object request Request details
+ * @param boolean allFrames Dispatch to all frames
+ * @param boolean allowForeign Allow foreign-origin iframes
+ * @return void
+ */
+async function dispatchFocusOrSubmit(settings, request, allFrames, allowForeign) {
+ request = Object.assign(deepCopy(request), {
+ allowForeign: allowForeign,
+ foreignFills: settings.foreignFills[settings.host] || {}
+ });
+
+ let perFrameResults = await chrome.tabs.executeScript(settings.tab.id, {
+ allFrames: allFrames,
+ code: `window.browserpass.focusOrSubmit(${JSON.stringify(request)});`
+ });
+
+ // if necessary, dispatch Enter keypress to autosubmit the form
+ // currently only works on Chromium and requires debugger permission
+ try {
+ for (let frame of perFrameResults) {
+ if (frame.needPressEnter) {
+ chrome.debugger.attach({ tabId: settings.tab.id }, "1.2");
+ for (let type of ["keyDown", "keyUp"]) {
+ chrome.debugger.sendCommand(
+ { tabId: settings.tab.id },
+ "Input.dispatchKeyEvent",
+ {
+ type: type,
+ windowsVirtualKeyCode: 13,
+ nativeVirtualKeyCode: 13
+ }
+ );
+ }
+ chrome.debugger.detach({ tabId: settings.tab.id });
+ break;
+ }
+ }
+ } catch (e) {}
+}
+
+/**
+ * Inject script
+ *
+ * @param object settings Settings object
+ * @param boolean allFrames Inject in all frames
+ * @return object Cancellable promise
+ */
+async function injectScript(settings, allFrames) {
+ const MAX_WAIT = 1000;
+
+ return new Promise(async (resolve, reject) => {
+ const waitTimeout = setTimeout(reject, MAX_WAIT);
+ await chrome.tabs.executeScript(settings.tab.id, {
+ allFrames: allFrames,
+ file: "js/inject.dist.js"
+ });
+ clearTimeout(waitTimeout);
+ resolve(true);
+ });
+}
+
+/**
+ * Fill form fields
+ *
+ * @param object settings Settings object
+ * @param object login Login object
+ * @param array fields List of fields to fill
+ * @return array List of filled fields
+ */
+async function fillFields(settings, login, fields) {
+ // inject script
+ try {
+ await injectScript(settings, false);
+ } catch {
+ throw new Error("Unable to inject script in the top frame");
+ }
+
+ let injectedAllFrames = false;
+ try {
+ await injectScript(settings, true);
+ injectedAllFrames = true;
+ } catch {
+ // we'll proceed with trying to fill only the top frame
+ }
+
+ // build fill request
+ var fillRequest = {
+ origin: new URL(settings.tab.url).origin,
+ login: login,
+ fields: fields
+ };
+
+ let allFrames = false;
+ let allowForeign = false;
+ let allowNoSecret = !fields.includes("secret");
+ let filledFields = [];
+ let importantFieldToFill = fields.includes("openid") ? "openid" : "secret";
+
+ // fill form via injected script
+ filledFields = filledFields.concat(
+ await dispatchFill(settings, fillRequest, allFrames, allowForeign, allowNoSecret)
+ );
+
+ if (injectedAllFrames) {
+ // try again using same-origin frames if we couldn't fill an "important" field
+ if (!filledFields.includes(importantFieldToFill)) {
+ allFrames = true;
+ filledFields = filledFields.concat(
+ await dispatchFill(settings, fillRequest, allFrames, allowForeign, allowNoSecret)
+ );
+ }
+
+ // try again using all available frames if we couldn't fill an "important" field
+ if (
+ !filledFields.includes(importantFieldToFill) &&
+ settings.foreignFills[settings.host] !== false
+ ) {
+ allowForeign = true;
+ filledFields = filledFields.concat(
+ await dispatchFill(settings, fillRequest, allFrames, allowForeign, allowNoSecret)
+ );
+ }
+ }
+
+ // try again, but don't require a password field (if it was required until now)
+ if (!allowNoSecret) {
+ allowNoSecret = true;
+
+ // try again using only the top frame
+ if (!filledFields.length) {
+ allFrames = false;
+ allowForeign = false;
+ filledFields = filledFields.concat(
+ await dispatchFill(settings, fillRequest, allFrames, allowForeign, allowNoSecret)
+ );
+ }
+
+ if (injectedAllFrames) {
+ // try again using same-origin frames
+ if (!filledFields.length) {
+ allFrames = true;
+ filledFields = filledFields.concat(
+ await dispatchFill(
+ settings,
+ fillRequest,
+ allFrames,
+ allowForeign,
+ allowNoSecret
+ )
+ );
+ }
+
+ // try again using all available frames
+ if (!filledFields.length && settings.foreignFills[settings.host] !== false) {
+ allowForeign = true;
+ filledFields = filledFields.concat(
+ await dispatchFill(
+ settings,
+ fillRequest,
+ allFrames,
+ allowForeign,
+ allowNoSecret
+ )
+ );
+ }
+ }
+ }
+
+ if (!filledFields.length) {
+ throw new Error(`No fillable forms available for fields: ${fields.join(", ")}`);
+ }
+
+ // build focus or submit request
+ let focusOrSubmitRequest = {
+ origin: new URL(settings.tab.url).origin,
+ autoSubmit: getSetting("autoSubmit", login, settings),
+ filledFields: filledFields
+ };
+
+ // try to focus or submit form with the settings that were used to fill it
+ await dispatchFocusOrSubmit(settings, focusOrSubmitRequest, allFrames, allowForeign);
+
+ return filledFields;
+}
+
+/**
+ * Get Local settings from the extension
+ *
+ * @since 3.0.0
+ *
+ * @return object Local settings from the extension
+ */
+function getLocalSettings() {
+ var settings = deepCopy(defaultSettings);
+ for (var key in settings) {
+ var value = localStorage.getItem(key);
+ if (value !== null) {
+ settings[key] = JSON.parse(value);
+ }
+ }
+
+ return settings;
+}
+
+/**
+ * Get full settings from the extension and host application
+ *
+ * @since 3.0.0
+ *
+ * @return object Full settings object
+ */
+async function getFullSettings() {
+ var settings = getLocalSettings();
+ var configureSettings = Object.assign(deepCopy(settings), {
+ defaultStore: {}
+ });
+ var response = await hostAction(configureSettings, "configure");
+ if (response.status != "ok") {
+ settings.hostError = response;
+ }
+ settings.version = response.version;
+
+ // Fill store settings, only makes sense if 'configure' succeeded
+ if (response.status === "ok") {
+ if (Object.keys(settings.stores).length > 0) {
+ // there are user-configured stores present
+ for (var storeId in settings.stores) {
+ if (response.data.storeSettings.hasOwnProperty(storeId)) {
+ var fileSettings = JSON.parse(response.data.storeSettings[storeId]);
+ if (typeof settings.stores[storeId].settings !== "object") {
+ settings.stores[storeId].settings = {};
+ }
+ var storeSettings = settings.stores[storeId].settings;
+ for (var settingKey in fileSettings) {
+ if (!storeSettings.hasOwnProperty(settingKey)) {
+ storeSettings[settingKey] = fileSettings[settingKey];
+ }
+ }
+ }
+ }
+ } else {
+ // no user-configured stores, so use the default store
+ settings.stores.default = {
+ id: "default",
+ name: "pass",
+ path: response.data.defaultStore.path
+ };
+ var fileSettings = JSON.parse(response.data.defaultStore.settings);
+ if (typeof settings.stores.default.settings !== "object") {
+ settings.stores.default.settings = {};
+ }
+ var storeSettings = settings.stores.default.settings;
+ for (var settingKey in fileSettings) {
+ if (!storeSettings.hasOwnProperty(settingKey)) {
+ storeSettings[settingKey] = fileSettings[settingKey];
+ }
+ }
+ }
+ }
+
+ // Fill recent data
+ for (var storeId in settings.stores) {
+ var when = localStorage.getItem("recent:" + storeId);
+ if (when) {
+ settings.stores[storeId].when = JSON.parse(when);
+ } else {
+ settings.stores[storeId].when = 0;
+ }
+ }
+ settings.recent = localStorage.getItem("recent");
+ if (settings.recent) {
+ settings.recent = JSON.parse(settings.recent);
+ } else {
+ settings.recent = {};
+ }
+
+ // Fill current tab info
+ try {
+ settings.tab = (await chrome.tabs.query({ active: true, currentWindow: true }))[0];
+ settings.host = new URL(settings.tab.url).hostname;
+ } catch (e) {}
+
+ return settings;
+}
+
+/**
+ * Get most relevant setting value
+ *
+ * @param string key Setting key
+ * @param object login Login object
+ * @param object settings Settings object
+ * @return object Setting value
+ */
+function getSetting(key, login, settings) {
+ if (typeof login.settings[key] !== "undefined") {
+ return login.settings[key];
+ }
+ if (typeof settings.stores[login.store.id].settings[key] !== "undefined") {
+ return settings.stores[login.store.id].settings[key];
+ }
+
+ return settings[key];
+}
+
+/**
+ * Deep copy an object
+ *
+ * @since 3.0.0
+ *
+ * @param object obj an object to copy
+ * @return object a new deep copy
+ */
+function deepCopy(obj) {
+ return JSON.parse(JSON.stringify(obj));
+}
+
+/**
+ * Handle modal authentication requests (e.g. HTTP basic)
+ *
+ * @since 3.0.0
+ *
+ * @param object requestDetails Auth request details
+ * @return object Authentication credentials or {}
+ */
+function handleModalAuth(requestDetails) {
+ var launchHost = requestDetails.url.match(/:\/\/([^\/]+)/)[1];
+
+ // don't attempt authentication against the same login more than once
+ if (!this.login.allowFill) {
+ return {};
+ }
+ this.login.allowFill = false;
+
+ // don't attempt authentication outside the main frame
+ if (requestDetails.type !== "main_frame") {
+ return {};
+ }
+
+ // ensure the auth domain is the same, or ask the user for permissions to continue
+ if (launchHost !== requestDetails.challenger.host) {
+ var message =
+ "You are about to send login credentials to a domain that is different than " +
+ "the one you lauched from the browserpass extension. Do you wish to proceed?\n\n" +
+ "Realm: " +
+ requestDetails.realm +
+ "\n" +
+ "Launched URL: " +
+ this.url +
+ "\n" +
+ "Authentication URL: " +
+ requestDetails.url;
+ if (!confirm(message)) {
+ return {};
+ }
+ }
+
+ // ask the user before sending credentials over an insecure connection
+ if (!requestDetails.url.match(/^https:/i)) {
+ var message =
+ "You are about to send login credentials via an insecure connection!\n\n" +
+ "Are you sure you want to do this? If there is an attacker watching your " +
+ "network traffic, they may be able to see your username and password.\n\n" +
+ "URL: " +
+ requestDetails.url;
+ if (!confirm(message)) {
+ return {};
+ }
+ }
+
+ // supply credentials
+ return {
+ authCredentials: {
+ username: this.login.fields.login,
+ password: this.login.fields.secret
+ }
+ };
+}
+
+/**
+ * Handle a message from elsewhere within the extension
+ *
+ * @since 3.0.0
+ *
+ * @param object settings Settings object
+ * @param mixed message Incoming message
+ * @param function(mixed) sendResponse Callback to send response
+ * @return void
+ */
+async function handleMessage(settings, message, sendResponse) {
+ // check that action is present
+ if (typeof message !== "object" || !message.hasOwnProperty("action")) {
+ sendResponse({ status: "error", message: "Action is missing" });
+ return;
+ }
+
+ // fetch file & parse fields if a login entry is present
+ try {
+ if (typeof message.login !== "undefined") {
+ await parseFields(settings, message.login);
+ }
+ } catch (e) {
+ sendResponse({
+ status: "error",
+ message: "Unable to fetch and parse login fields: " + e.toString()
+ });
+ return;
+ }
+
+ // route action
+ switch (message.action) {
+ case "getSettings":
+ sendResponse({
+ status: "ok",
+ settings: settings
+ });
+ break;
+ case "saveSettings":
+ try {
+ await saveSettings(message.settings);
+ sendResponse({ status: "ok" });
+ } catch (e) {
+ sendResponse({
+ status: "error",
+ message: e.message
+ });
+ }
+ break;
+ case "listFiles":
+ try {
+ var response = await hostAction(settings, "list");
+ if (response.status != "ok") {
+ throw new Error(JSON.stringify(response)); // TODO handle host error
+ }
+ sendResponse({ status: "ok", files: response.data.files });
+ } catch (e) {
+ sendResponse({
+ status: "error",
+ message: "Unable to enumerate password files" + e.toString()
+ });
+ }
+ break;
+ case "copyPassword":
+ try {
+ copyToClipboard(message.login.fields.secret);
+ await saveRecent(settings, message.login);
+ sendResponse({ status: "ok" });
+ } catch (e) {
+ sendResponse({
+ status: "error",
+ message: "Unable to copy password"
+ });
+ }
+ break;
+ case "copyUsername":
+ try {
+ copyToClipboard(message.login.fields.login);
+ await saveRecent(settings, message.login);
+ sendResponse({ status: "ok" });
+ } catch (e) {
+ sendResponse({
+ status: "error",
+ message: "Unable to copy username"
+ });
+ }
+ break;
+
+ case "launch":
+ case "launchInNewTab":
+ try {
+ var url = message.login.fields.url || message.login.domain;
+ if (!url) {
+ throw new Error("No URL is defined for this entry");
+ }
+ if (!url.match(/:\/\//)) {
+ url = "http://" + url;
+ }
+
+ const tab =
+ message.action === "launch"
+ ? await chrome.tabs.update(settings.tab.id, { url: url })
+ : await chrome.tabs.create({ url: url });
+
+ if (authListeners[tab.id]) {
+ chrome.tabs.onUpdated.removeListener(authListeners[tab.id]);
+ delete authListeners[tab.id];
+ }
+ authListeners[tab.id] = handleModalAuth.bind({
+ url: url,
+ login: message.login
+ });
+ chrome.webRequest.onAuthRequired.addListener(
+ authListeners[tab.id],
+ { urls: ["*://*/*"], tabId: tab.id },
+ ["blocking"]
+ );
+ sendResponse({ status: "ok" });
+ } catch (e) {
+ sendResponse({
+ status: "error",
+ message: "Unable to launch URL: " + e.toString()
+ });
+ }
+ break;
+ case "fill":
+ try {
+ let fields = message.login.fields.openid ? ["openid"] : ["login", "secret"];
+
+ // dispatch initial fill request
+ var filledFields = await fillFields(settings, message.login, fields);
+ await saveRecent(settings, message.login);
+
+ // no need to check filledFields, because fillFields() already throws an error if empty
+ sendResponse({ status: "ok", filledFields: filledFields });
+ } catch (e) {
+ try {
+ sendResponse({
+ status: "error",
+ message: e.toString()
+ });
+ } catch (e) {
+ // TODO An error here is typically a closed message port, due to a popup taking focus
+ // away from the extension menu and the menu closing as a result. Need to investigate
+ // whether triggering the extension menu from the background script is possible.
+ console.log(e);
+ }
+ }
+ break;
+ case "clearUsageData":
+ try {
+ await clearUsageData();
+ sendResponse({ status: "ok" });
+ } catch (e) {
+ sendResponse({
+ status: "error",
+ message: e.message
+ });
+ }
+ break;
+ default:
+ sendResponse({
+ status: "error",
+ message: "Unknown action: " + message.action
+ });
+ break;
+ }
+
+ // trigger browserpass-otp
+ if (typeof message.login !== "undefined" && message.login.fields.hasOwnProperty("otp")) {
+ triggerOTPExtension(settings, message.action, message.login.fields.otp);
+ }
+}
+
+/**
+ * Send a request to the host app
+ *
+ * @since 3.0.0
+ *
+ * @param object settings Live settings object
+ * @param string action Action to run
+ * @param params object Additional params to pass to the host app
+ * @return Promise
+ */
+function hostAction(settings, action, params = {}) {
+ var request = {
+ settings: settings,
+ action: action
+ };
+ for (var key in params) {
+ request[key] = params[key];
+ }
+
+ return chrome.runtime.sendNativeMessage(appID, request);
+}
+
+/**
+ * Fetch file & parse fields
+ *
+ * @since 3.0.0
+ *
+ * @param object settings Settings object
+ * @param object login Login object
+ * @return void
+ */
+async function parseFields(settings, login) {
+ var response = await hostAction(settings, "fetch", {
+ storeId: login.store.id,
+ file: login.login + ".gpg"
+ });
+ if (response.status != "ok") {
+ throw new Error(JSON.stringify(response)); // TODO handle host error
+ }
+
+ // save raw data inside login
+ login.raw = response.data.contents;
+
+ // parse lines
+ login.fields = {
+ secret: ["secret", "password", "pass"],
+ login: ["login", "username", "user"],
+ openid: ["openid"],
+ otp: ["otp", "totp", "hotp"],
+ url: ["url", "uri", "website", "site", "link", "launch"]
+ };
+ login.settings = {
+ autoSubmit: { name: "autosubmit", type: "bool" }
+ };
+ var lines = login.raw.split(/[\r\n]+/).filter(line => line.trim().length > 0);
+ lines.forEach(function(line) {
+ // check for uri-encoded otp
+ if (line.match(/^otpauth:\/\/.+/)) {
+ login.fields.otp = { key: null, data: line };
+ return;
+ }
+
+ // split key / value & ignore non-k/v lines
+ var parts = line.match(/^(.+?):(.+)$/);
+ if (parts === null) {
+ return;
+ }
+ parts = parts
+ .slice(1)
+ .map(value => value.trim())
+ .filter(value => value.length);
+ if (parts.length != 2) {
+ return;
+ }
+
+ // assign to fields
+ for (var key in login.fields) {
+ if (
+ Array.isArray(login.fields[key]) &&
+ login.fields[key].includes(parts[0].toLowerCase())
+ ) {
+ if (key === "otp") {
+ login.fields[key] = { key: parts[0].toLowerCase(), data: parts[1] };
+ } else {
+ login.fields[key] = parts[1];
+ }
+ break;
+ }
+ }
+
+ // assign to settings
+ for (var key in login.settings) {
+ if (
+ typeof login.settings[key].type !== "undefined" &&
+ login.settings[key].name === parts[0].toLowerCase()
+ ) {
+ if (login.settings[key].type === "bool") {
+ login.settings[key] = ["true", "yes"].includes(parts[1].toLowerCase());
+ } else {
+ login.settings[key] = parts[1];
+ }
+
+ break;
+ }
+ }
+ });
+
+ // clean up unassigned fields
+ for (var key in login.fields) {
+ if (Array.isArray(login.fields[key])) {
+ if (key === "secret" && lines.length) {
+ login.fields.secret = lines[0];
+ } else if (key === "login") {
+ const defaultUsername = getSetting("username", login, settings);
+ login.fields[key] = defaultUsername || login.login.match(/([^\/]+)$/)[1];
+ } else {
+ delete login.fields[key];
+ }
+ }
+ }
+ for (var key in login.settings) {
+ if (typeof login.settings[key].type !== "undefined") {
+ delete login.settings[key];
+ }
+ }
+}
+
+/**
+ * Wrap inbound messages to fetch native configuration
+ *
+ * @since 3.0.0
+ *
+ * @param mixed message Incoming message
+ * @param MessageSender sender Message sender
+ * @param function(mixed) sendResponse Callback to send response
+ * @return void
+ */
+async function receiveMessage(message, sender, sendResponse) {
+ // restrict messages to this extension only
+ if (sender.id !== chrome.runtime.id) {
+ // silently exit without responding when the source is foreign
+ return;
+ }
+
+ try {
+ const settings = await getFullSettings();
+ handleMessage(settings, message, sendResponse);
+ } catch (e) {
+ // handle error
+ console.log(e);
+ sendResponse({ status: "error", message: e.toString() });
+ }
+}
+
+/**
+ * Clear usage data
+ *
+ * @since 3.0.10
+ *
+ * @return void
+ */
+async function clearUsageData() {
+ // clear local storage
+ localStorage.removeItem("foreignFills");
+ localStorage.removeItem("recent");
+ Object.keys(localStorage).forEach(key => {
+ if (key.startsWith("recent:")) {
+ localStorage.removeItem(key);
+ }
+ });
+
+ // clear Indexed DB
+ await idb.deleteDB("browserpass");
+}
+
+/**
+ * Save settings if they are valid
+ *
+ * @since 3.0.0
+ *
+ * @param object Final settings object
+ * @return void
+ */
+async function saveSettings(settings) {
+ let settingsToSave = deepCopy(settings);
+
+ // 'default' is our reserved name for the default store
+ delete settingsToSave.stores.default;
+
+ // verify that the native host is happy with the provided settings
+ var response = await hostAction(settingsToSave, "configure");
+ if (response.status != "ok") {
+ throw new Error(`${response.params.message}: ${response.params.error}`);
+ }
+
+ // before save, make sure to remove store settings that we receive from the host app
+ if (typeof settingsToSave.stores === "object") {
+ for (var store in settingsToSave.stores) {
+ delete settingsToSave.stores[store].settings;
+ }
+ }
+
+ for (var key in defaultSettings) {
+ if (settingsToSave.hasOwnProperty(key)) {
+ localStorage.setItem(key, JSON.stringify(settingsToSave[key]));
+ }
+ }
+}
+
+/**
+ * Trigger OTP extension (browserpass-otp)
+ *
+ * @since 3.0.13
+ *
+ * @param object settings Settings object
+ * @param string action Browserpass action
+ * @param object otp OTP field data
+ * @return void
+ */
+function triggerOTPExtension(settings, action, otp) {
+ // trigger otp extension
+ for (let targetID of otpID) {
+ chrome.runtime
+ .sendMessage(targetID, {
+ version: chrome.runtime.getManifest().version,
+ action: action,
+ otp: otp,
+ settings: {
+ host: settings.host,
+ tab: settings.tab
+ }
+ })
+ // Both response & error are noop functions, because we don't care about
+ // the response, and if there's an error it just means the otp extension
+ // is probably not installed. We can't detect that without requesting the
+ // management permission, so this is an acceptable workaround.
+ .then(noop => null, noop => null);
+ }
+}
+
+/**
+ * Handle browser extension installation and updates
+ *
+ * @since 3.0.0
+ *
+ * @param object Event details
+ * @return void
+ */
+function onExtensionInstalled(details) {
+ // No permissions
+ if (!chrome.notifications) {
+ return;
+ }
+
+ var show = (id, title, message) => {
+ chrome.notifications.create(id, {
+ title: title,
+ message: message,
+ iconUrl: "icon.png",
+ type: "basic"
+ });
+ };
+
+ if (details.reason === "install") {
+ if (localStorage.getItem("installed") === null) {
+ localStorage.setItem("installed", Date.now());
+ show(
+ "installed",
+ "browserpass: Install native host app",
+ "Remember to install the complementary native host app to use this extension.\n" +
+ "Instructions here: https://github.com/browserpass/browserpass-native"
+ );
+ }
+ } else if (details.reason === "update") {
+ var changelog = {
+ 3000000:
+ "New major update is out, please update the native host app to v3.\n" +
+ "Instructions here: https://github.com/browserpass/browserpass-native"
+ };
+
+ var parseVersion = version => {
+ var [major, minor, patch] = version.split(".");
+ return parseInt(major) * 1000000 + parseInt(minor) * 1000 + parseInt(patch);
+ };
+ var newVersion = parseVersion(chrome.runtime.getManifest().version);
+ var prevVersion = parseVersion(details.previousVersion);
+
+ Object.keys(changelog)
+ .sort()
+ .forEach(function(version) {
+ if (prevVersion < version && newVersion >= version) {
+ show(version.toString(), "browserpass: Important changes", changelog[version]);
+ }
+ });
+ }
+}
+
+},{"./helpers":2,"chrome-extension-async":6,"idb":10,"sha1":17}],2:[function(require,module,exports){
+//------------------------------------- Initialisation --------------------------------------//
+"use strict";
+
+const FuzzySort = require("fuzzysort");
+const TldJS = require("tldjs");
+const sha1 = require("sha1");
+
+module.exports = {
+ pathToDomain,
+ prepareLogins,
+ filterSortLogins
+};
+
+//----------------------------------- Function definitions ----------------------------------//
+
+/**
+ * Get the deepest available domain component of a path
+ *
+ * @since 3.0.0
+ *
+ * @param string path Path to parse
+ * @param string currentHost Current hostname for the active tab
+ * @return string|null Extracted domain
+ */
+function pathToDomain(path, currentHost) {
+ var parts = path.split(/\//).reverse();
+ for (var key in parts) {
+ if (parts[key].indexOf("@") >= 0) {
+ continue;
+ }
+ var t = TldJS.parse(parts[key]);
+ if (
+ t.isValid &&
+ ((t.tldExists && t.domain !== null) ||
+ t.hostname === currentHost ||
+ currentHost.endsWith(`.${t.hostname}`))
+ ) {
+ return t.hostname;
+ }
+ }
+
+ return null;
+}
+
+/**
+ * Prepare list of logins based on provided files
+ *
+ * @since 3.1.0
+ *
+ * @param string array List of password files
+ * @param string object Settings object
+ * @return array List of logins
+ */
+function prepareLogins(files, settings) {
+ const logins = [];
+ let index = 0;
+
+ for (let storeId in files) {
+ for (let key in files[storeId]) {
+ // set login fields
+ const login = {
+ index: index++,
+ store: settings.stores[storeId],
+ login: files[storeId][key].replace(/\.gpg$/i, ""),
+ allowFill: true
+ };
+ login.domain = pathToDomain(storeId + "/" + login.login, settings.host);
+ login.inCurrentDomain =
+ settings.host == login.domain || settings.host.endsWith("." + login.domain);
+ login.recent =
+ settings.recent[sha1(settings.host + sha1(login.store.id + sha1(login.login)))];
+ if (!login.recent) {
+ login.recent = {
+ when: 0,
+ count: 0
+ };
+ }
+
+ logins.push(login);
+ }
+ }
+
+ return logins;
+}
+
+/**
+ * Filter and sort logins
+ *
+ * @since 3.1.0
+ *
+ * @param string array List of logins
+ * @param string object Settings object
+ * @return array Filtered and sorted list of logins
+ */
+function filterSortLogins(logins, searchQuery, currentDomainOnly) {
+ var fuzzyFirstWord = searchQuery.substr(0, 1) !== " ";
+ searchQuery = searchQuery.trim();
+
+ // get candidate list
+ var candidates = logins.map(candidate => {
+ let lastSlashIndex = candidate.login.lastIndexOf("/") + 1;
+ return Object.assign(candidate, {
+ path: candidate.login.substr(0, lastSlashIndex),
+ display: candidate.login.substr(lastSlashIndex)
+ });
+ });
+
+ var mostRecent = null;
+ if (currentDomainOnly) {
+ var recent = candidates.filter(function(login) {
+ if (login.recent.count > 0) {
+ // find most recently used login
+ if (!mostRecent || login.recent.when > mostRecent.recent.when) {
+ mostRecent = login;
+ }
+ return true;
+ }
+ return false;
+ });
+ var remainingInCurrentDomain = candidates.filter(
+ login => login.inCurrentDomain && !login.recent.count
+ );
+ candidates = recent.concat(remainingInCurrentDomain);
+ }
+
+ candidates.sort((a, b) => {
+ // show most recent first
+ if (a === mostRecent) {
+ return -1;
+ }
+ if (b === mostRecent) {
+ return 1;
+ }
+
+ // sort by frequency
+ var countDiff = b.recent.count - a.recent.count;
+ if (countDiff) {
+ return countDiff;
+ }
+
+ // sort by specificity, only if filtering for one domain
+ if (currentDomainOnly) {
+ var domainLevelsDiff =
+ (b.login.match(/\./g) || []).length - (a.login.match(/\./g) || []).length;
+ if (domainLevelsDiff) {
+ return domainLevelsDiff;
+ }
+ }
+
+ // sort alphabetically
+ return a.login.localeCompare(b.login);
+ });
+
+ if (searchQuery.length) {
+ let filter = searchQuery.split(/\s+/);
+ let fuzzyFilter = fuzzyFirstWord ? filter[0] : "";
+ let substringFilters = filter.slice(fuzzyFirstWord ? 1 : 0).map(w => w.toLowerCase());
+
+ // First reduce the list by running the substring search
+ substringFilters.forEach(function(word) {
+ candidates = candidates.filter(c => c.login.toLowerCase().indexOf(word) >= 0);
+ });
+
+ // Then run the fuzzy filter
+ let fuzzyResults = {};
+ if (fuzzyFilter) {
+ candidates = FuzzySort.go(fuzzyFilter, candidates, {
+ keys: ["login", "store.name"],
+ allowTypo: false
+ }).map(result => {
+ fuzzyResults[result.obj.login] = result;
+ return result.obj;
+ });
+ }
+
+ // Finally highlight all matches
+ candidates = candidates.map(c => highlightMatches(c, fuzzyResults, substringFilters));
+ }
+
+ // Prefix root entries with slash to let them have some visible path
+ candidates.forEach(c => {
+ c.path = c.path || "/";
+ });
+
+ return candidates;
+}
+
+//----------------------------------- Private functions ----------------------------------//
+
+/**
+ * Highlight filter matches
+ *
+ * @since 3.0.0
+ *
+ * @param object entry password entry
+ * @param object fuzzyResults positions of fuzzy filter matches
+ * @param array substringFilters list of substring filters applied
+ * @return object entry with highlighted matches
+ */
+function highlightMatches(entry, fuzzyResults, substringFilters) {
+ // Add all positions of the fuzzy search to the array
+ let matches = (fuzzyResults[entry.login] && fuzzyResults[entry.login][0]
+ ? fuzzyResults[entry.login][0].indexes
+ : []
+ ).slice();
+
+ // Add all positions of substring searches to the array
+ let login = entry.login.toLowerCase();
+ for (let word of substringFilters) {
+ let startIndex = login.indexOf(word);
+ for (let i = 0; i < word.length; i++) {
+ matches.push(startIndex + i);
+ }
+ }
+
+ // Prepare the final array of matches before
+ matches = sortUnique(matches, (a, b) => a - b);
+
+ const OPEN = "<em>";
+ const CLOSE = "</em>";
+ let highlighted = "";
+ var matchesIndex = 0;
+ var opened = false;
+ for (var i = 0; i < entry.login.length; ++i) {
+ var char = entry.login[i];
+
+ if (i == entry.path.length) {
+ if (opened) {
+ highlighted += CLOSE;
+ }
+ var path = highlighted;
+ highlighted = "";
+ if (opened) {
+ highlighted += OPEN;
+ }
+ }
+
+ if (matches[matchesIndex] === i) {
+ matchesIndex++;
+ if (!opened) {
+ opened = true;
+ highlighted += OPEN;
+ }
+ } else {
+ if (opened) {
+ opened = false;
+ highlighted += CLOSE;
+ }
+ }
+ highlighted += char;
+ }
+ if (opened) {
+ opened = false;
+ highlighted += CLOSE;
+ }
+ let display = highlighted;
+
+ return Object.assign(entry, {
+ path: path,
+ display: display
+ });
+}
+
+/**
+ * Sort and remove duplicates
+ *
+ * @since 3.0.0
+ *
+ * @param array array items to sort
+ * @param function comparator sort comparator
+ * @return array sorted items without duplicates
+ */
+function sortUnique(array, comparator) {
+ return array
+ .sort(comparator)
+ .filter((elem, index, arr) => index == !arr.length || arr[index - 1] != elem);
+}
+
+},{"fuzzysort":8,"sha1":17,"tldjs":19}],3:[function(require,module,exports){
+'use strict'
+
+exports.byteLength = byteLength
+exports.toByteArray = toByteArray
+exports.fromByteArray = fromByteArray
+
+var lookup = []
+var revLookup = []
+var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
+
+var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
+for (var i = 0, len = code.length; i < len; ++i) {
+ lookup[i] = code[i]
+ revLookup[code.charCodeAt(i)] = i
+}
+
+// Support decoding URL-safe base64 strings, as Node.js does.
+// See: https://en.wikipedia.org/wiki/Base64#URL_applications
+revLookup['-'.charCodeAt(0)] = 62
+revLookup['_'.charCodeAt(0)] = 63
+
+function getLens (b64) {
+ var len = b64.length
+
+ if (len % 4 > 0) {
+ throw new Error('Invalid string. Length must be a multiple of 4')
+ }
+
+ // Trim off extra bytes after placeholder bytes are found
+ // See: https://github.com/beatgammit/base64-js/issues/42
+ var validLen = b64.indexOf('=')
+ if (validLen === -1) validLen = len
+
+ var placeHoldersLen = validLen === len
+ ? 0
+ : 4 - (validLen % 4)
+
+ return [validLen, placeHoldersLen]
+}
+
+// base64 is 4/3 + up to two characters of the original data
+function byteLength (b64) {
+ var lens = getLens(b64)
+ var validLen = lens[0]
+ var placeHoldersLen = lens[1]
+ return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
+}
+
+function _byteLength (b64, validLen, placeHoldersLen) {
+ return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
+}
+
+function toByteArray (b64) {
+ var tmp
+ var lens = getLens(b64)
+ var validLen = lens[0]
+ var placeHoldersLen = lens[1]
+
+ var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))
+
+ var curByte = 0
+
+ // if there are placeholders, only get up to the last complete 4 chars
+ var len = placeHoldersLen > 0
+ ? validLen - 4
+ : validLen
+
+ for (var i = 0; i < len; i += 4) {
+ tmp =
+ (revLookup[b64.charCodeAt(i)] << 18) |
+ (revLookup[b64.charCodeAt(i + 1)] << 12) |
+ (revLookup[b64.charCodeAt(i + 2)] << 6) |
+ revLookup[b64.charCodeAt(i + 3)]
+ arr[curByte++] = (tmp >> 16) & 0xFF
+ arr[curByte++] = (tmp >> 8) & 0xFF
+ arr[curByte++] = tmp & 0xFF
+ }
+
+ if (placeHoldersLen === 2) {
+ tmp =
+ (revLookup[b64.charCodeAt(i)] << 2) |
+ (revLookup[b64.charCodeAt(i + 1)] >> 4)
+ arr[curByte++] = tmp & 0xFF
+ }
+
+ if (placeHoldersLen === 1) {
+ tmp =
+ (revLookup[b64.charCodeAt(i)] << 10) |
+ (revLookup[b64.charCodeAt(i + 1)] << 4) |
+ (revLookup[b64.charCodeAt(i + 2)] >> 2)
+ arr[curByte++] = (tmp >> 8) & 0xFF
+ arr[curByte++] = tmp & 0xFF
+ }
+
+ return arr
+}
+
+function tripletToBase64 (num) {
+ return lookup[num >> 18 & 0x3F] +
+ lookup[num >> 12 & 0x3F] +
+ lookup[num >> 6 & 0x3F] +
+ lookup[num & 0x3F]
+}
+
+function encodeChunk (uint8, start, end) {
+ var tmp
+ var output = []
+ for (var i = start; i < end; i += 3) {
+ tmp =
+ ((uint8[i] << 16) & 0xFF0000) +
+ ((uint8[i + 1] << 8) & 0xFF00) +
+ (uint8[i + 2] & 0xFF)
+ output.push(tripletToBase64(tmp))
+ }
+ return output.join('')
+}
+
+function fromByteArray (uint8) {
+ var tmp
+ var len = uint8.length
+ var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
+ var parts = []
+ var maxChunkLength = 16383 // must be multiple of 3
+
+ // go through the array every three bytes, we'll deal with trailing stuff later
+ for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
+ parts.push(encodeChunk(
+ uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)
+ ))
+ }
+
+ // pad the end with zeros, but make sure to not forget the extra bytes
+ if (extraBytes === 1) {
+ tmp = uint8[len - 1]
+ parts.push(
+ lookup[tmp >> 2] +
+ lookup[(tmp << 4) & 0x3F] +
+ '=='
+ )
+ } else if (extraBytes === 2) {
+ tmp = (uint8[len - 2] << 8) + uint8[len - 1]
+ parts.push(
+ lookup[tmp >> 10] +
+ lookup[(tmp >> 4) & 0x3F] +
+ lookup[(tmp << 2) & 0x3F] +
+ '='
+ )
+ }
+
+ return parts.join('')
+}
+
+},{}],4:[function(require,module,exports){
+/*!
+ * The buffer module from node.js, for the browser.
+ *
+ * @author Feross Aboukhadijeh <https://feross.org>
+ * @license MIT
+ */
+/* eslint-disable no-proto */
+
+'use strict'
+
+var base64 = require('base64-js')
+var ieee754 = require('ieee754')
+
+exports.Buffer = Buffer
+exports.SlowBuffer = SlowBuffer
+exports.INSPECT_MAX_BYTES = 50
+
+var K_MAX_LENGTH = 0x7fffffff
+exports.kMaxLength = K_MAX_LENGTH
+
+/**
+ * If `Buffer.TYPED_ARRAY_SUPPORT`:
+ * === true Use Uint8Array implementation (fastest)
+ * === false Print warning and recommend using `buffer` v4.x which has an Object
+ * implementation (most compatible, even IE6)
+ *
+ * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
+ * Opera 11.6+, iOS 4.2+.
+ *
+ * We report that the browser does not support typed arrays if the are not subclassable
+ * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array`
+ * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support
+ * for __proto__ and has a buggy typed array implementation.
+ */
+Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport()
+
+if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' &&
+ typeof console.error === 'function') {
+ console.error(
+ 'This browser lacks typed array (Uint8Array) support which is required by ' +
+ '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.'
+ )
+}
+
+function typedArraySupport () {
+ // Can typed array instances can be augmented?
+ try {
+ var arr = new Uint8Array(1)
+ arr.__proto__ = { __proto__: Uint8Array.prototype, foo: function () { return 42 } }
+ return arr.foo() === 42
+ } catch (e) {
+ return false
+ }
+}
+
+Object.defineProperty(Buffer.prototype, 'parent', {
+ enumerable: true,
+ get: function () {
+ if (!Buffer.isBuffer(this)) return undefined
+ return this.buffer
+ }
+})
+
+Object.defineProperty(Buffer.prototype, 'offset', {
+ enumerable: true,
+ get: function () {
+ if (!Buffer.isBuffer(this)) return undefined
+ return this.byteOffset
+ }
+})
+
+function createBuffer (length) {
+ if (length > K_MAX_LENGTH) {
+ throw new RangeError('The value "' + length + '" is invalid for option "size"')
+ }
+ // Return an augmented `Uint8Array` instance
+ var buf = new Uint8Array(length)
+ buf.__proto__ = Buffer.prototype
+ return buf
+}
+
+/**
+ * The Buffer constructor returns instances of `Uint8Array` that have their
+ * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
+ * `Uint8Array`, so the returned instances will have all the node `Buffer` methods
+ * and the `Uint8Array` methods. Square bracket notation works as expected -- it
+ * returns a single octet.
+ *
+ * The `Uint8Array` prototype remains unmodified.
+ */
+
+function Buffer (arg, encodingOrOffset, length) {
+ // Common case.
+ if (typeof arg === 'number') {
+ if (typeof encodingOrOffset === 'string') {
+ throw new TypeError(
+ 'The "string" argument must be of type string. Received type number'
+ )
+ }
+ return allocUnsafe(arg)
+ }
+ return from(arg, encodingOrOffset, length)
+}
+
+// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97
+if (typeof Symbol !== 'undefined' && Symbol.species != null &&
+ Buffer[Symbol.species] === Buffer) {
+ Object.defineProperty(Buffer, Symbol.species, {
+ value: null,
+ configurable: true,
+ enumerable: false,
+ writable: false
+ })
+}
+
+Buffer.poolSize = 8192 // not used by this implementation
+
+function from (value, encodingOrOffset, length) {
+ if (typeof value === 'string') {
+ return fromString(value, encodingOrOffset)
+ }
+
+ if (ArrayBuffer.isView(value)) {
+ return fromArrayLike(value)
+ }
+
+ if (value == null) {
+ throw TypeError(
+ 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' +
+ 'or Array-like Object. Received type ' + (typeof value)
+ )
+ }
+
+ if (isInstance(value, ArrayBuffer) ||
+ (value && isInstance(value.buffer, ArrayBuffer))) {
+ return fromArrayBuffer(value, encodingOrOffset, length)
+ }
+
+ if (typeof value === 'number') {
+ throw new TypeError(
+ 'The "value" argument must not be of type number. Received type number'
+ )
+ }
+
+ var valueOf = value.valueOf && value.valueOf()
+ if (valueOf != null && valueOf !== value) {
+ return Buffer.from(valueOf, encodingOrOffset, length)
+ }
+
+ var b = fromObject(value)
+ if (b) return b
+
+ if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null &&
+ typeof value[Symbol.toPrimitive] === 'function') {
+ return Buffer.from(
+ value[Symbol.toPrimitive]('string'), encodingOrOffset, length
+ )
+ }
+
+ throw new TypeError(
+ 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' +
+ 'or Array-like Object. Received type ' + (typeof value)
+ )
+}
+
+/**
+ * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError
+ * if value is a number.
+ * Buffer.from(str[, encoding])
+ * Buffer.from(array)
+ * Buffer.from(buffer)
+ * Buffer.from(arrayBuffer[, byteOffset[, length]])
+ **/
+Buffer.from = function (value, encodingOrOffset, length) {
+ return from(value, encodingOrOffset, length)
+}
+
+// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug:
+// https://github.com/feross/buffer/pull/148
+Buffer.prototype.__proto__ = Uint8Array.prototype
+Buffer.__proto__ = Uint8Array
+
+function assertSize (size) {
+ if (typeof size !== 'number') {
+ throw new TypeError('"size" argument must be of type number')
+ } else if (size < 0) {
+ throw new RangeError('The value "' + size + '" is invalid for option "size"')
+ }
+}
+
+function alloc (size, fill, encoding) {
+ assertSize(size)
+ if (size <= 0) {
+ return createBuffer(size)
+ }
+ if (fill !== undefined) {
+ // Only pay attention to encoding if it's a string. This
+ // prevents accidentally sending in a number that would
+ // be interpretted as a start offset.
+ return typeof encoding === 'string'
+ ? createBuffer(size).fill(fill, encoding)
+ : createBuffer(size).fill(fill)
+ }
+ return createBuffer(size)
+}
+
+/**
+ * Creates a new filled Buffer instance.
+ * alloc(size[, fill[, encoding]])
+ **/
+Buffer.alloc = function (size, fill, encoding) {
+ return alloc(size, fill, encoding)
+}
+
+function allocUnsafe (size) {
+ assertSize(size)
+ return createBuffer(size < 0 ? 0 : checked(size) | 0)
+}
+
+/**
+ * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
+ * */
+Buffer.allocUnsafe = function (size) {
+ return allocUnsafe(size)
+}
+/**
+ * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
+ */
+Buffer.allocUnsafeSlow = function (size) {
+ return allocUnsafe(size)
+}
+
+function fromString (string, encoding) {
+ if (typeof encoding !== 'string' || encoding === '') {
+ encoding = 'utf8'
+ }
+
+ if (!Buffer.isEncoding(encoding)) {
+ throw new TypeError('Unknown encoding: ' + encoding)
+ }
+
+ var length = byteLength(string, encoding) | 0
+ var buf = createBuffer(length)
+
+ var actual = buf.write(string, encoding)
+
+ if (actual !== length) {
+ // Writing a hex string, for example, that contains invalid characters will
+ // cause everything after the first invalid character to be ignored. (e.g.
+ // 'abxxcd' will be treated as 'ab')
+ buf = buf.slice(0, actual)
+ }
+
+ return buf
+}
+
+function fromArrayLike (array) {
+ var length = array.length < 0 ? 0 : checked(array.length) | 0
+ var buf = createBuffer(length)
+ for (var i = 0; i < length; i += 1) {
+ buf[i] = array[i] & 255
+ }
+ return buf
+}
+
+function fromArrayBuffer (array, byteOffset, length) {
+ if (byteOffset < 0 || array.byteLength < byteOffset) {
+ throw new RangeError('"offset" is outside of buffer bounds')
+ }
+
+ if (array.byteLength < byteOffset + (length || 0)) {
+ throw new RangeError('"length" is outside of buffer bounds')
+ }
+
+ var buf
+ if (byteOffset === undefined && length === undefined) {
+ buf = new Uint8Array(array)
+ } else if (length === undefined) {
+ buf = new Uint8Array(array, byteOffset)
+ } else {
+ buf = new Uint8Array(array, byteOffset, length)
+ }
+
+ // Return an augmented `Uint8Array` instance
+ buf.__proto__ = Buffer.prototype
+ return buf
+}
+
+function fromObject (obj) {
+ if (Buffer.isBuffer(obj)) {
+ var len = checked(obj.length) | 0
+ var buf = createBuffer(len)
+
+ if (buf.length === 0) {
+ return buf
+ }
+
+ obj.copy(buf, 0, 0, len)
+ return buf
+ }
+
+ if (obj.length !== undefined) {
+ if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) {
+ return createBuffer(0)
+ }
+ return fromArrayLike(obj)
+ }
+
+ if (obj.type === 'Buffer' && Array.isArray(obj.data)) {
+ return fromArrayLike(obj.data)
+ }
+}
+
+function checked (length) {
+ // Note: cannot use `length < K_MAX_LENGTH` here because that fails when
+ // length is NaN (which is otherwise coerced to zero.)
+ if (length >= K_MAX_LENGTH) {
+ throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
+ 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes')
+ }
+ return length | 0
+}
+
+function SlowBuffer (length) {
+ if (+length != length) { // eslint-disable-line eqeqeq
+ length = 0
+ }
+ return Buffer.alloc(+length)
+}
+
+Buffer.isBuffer = function isBuffer (b) {
+ return b != null && b._isBuffer === true &&
+ b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false
+}
+
+Buffer.compare = function compare (a, b) {
+ if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength)
+ if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength)
+ if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
+ throw new TypeError(
+ 'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array'
+ )
+ }
+
+ if (a === b) return 0
+
+ var x = a.length
+ var y = b.length
+
+ for (var i = 0, len = Math.min(x, y); i < len; ++i) {
+ if (a[i] !== b[i]) {
+ x = a[i]
+ y = b[i]
+ break
+ }
+ }
+
+ if (x < y) return -1
+ if (y < x) return 1
+ return 0
+}
+
+Buffer.isEncoding = function isEncoding (encoding) {
+ switch (String(encoding).toLowerCase()) {
+ case 'hex':
+ case 'utf8':
+ case 'utf-8':
+ case 'ascii':
+ case 'latin1':
+ case 'binary':
+ case 'base64':
+ case 'ucs2':
+ case 'ucs-2':
+ case 'utf16le':
+ case 'utf-16le':
+ return true
+ default:
+ return false
+ }
+}
+
+Buffer.concat = function concat (list, length) {
+ if (!Array.isArray(list)) {
+ throw new TypeError('"list" argument must be an Array of Buffers')
+ }
+
+ if (list.length === 0) {
+ return Buffer.alloc(0)
+ }
+
+ var i
+ if (length === undefined) {
+ length = 0
+ for (i = 0; i < list.length; ++i) {
+ length += list[i].length
+ }
+ }
+
+ var buffer = Buffer.allocUnsafe(length)
+ var pos = 0
+ for (i = 0; i < list.length; ++i) {
+ var buf = list[i]
+ if (isInstance(buf, Uint8Array)) {
+ buf = Buffer.from(buf)
+ }
+ if (!Buffer.isBuffer(buf)) {
+ throw new TypeError('"list" argument must be an Array of Buffers')
+ }
+ buf.copy(buffer, pos)
+ pos += buf.length
+ }
+ return buffer
+}
+
+function byteLength (string, encoding) {
+ if (Buffer.isBuffer(string)) {
+ return string.length
+ }
+ if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) {
+ return string.byteLength
+ }
+ if (typeof string !== 'string') {
+ throw new TypeError(
+ 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' +
+ 'Received type ' + typeof string
+ )
+ }
+
+ var len = string.length
+ var mustMatch = (arguments.length > 2 && arguments[2] === true)
+ if (!mustMatch && len === 0) return 0
+
+ // Use a for loop to avoid recursion
+ var loweredCase = false
+ for (;;) {
+ switch (encoding) {
+ case 'ascii':
+ case 'latin1':
+ case 'binary':
+ return len
+ case 'utf8':
+ case 'utf-8':
+ return utf8ToBytes(string).length
+ case 'ucs2':
+ case 'ucs-2':
+ case 'utf16le':
+ case 'utf-16le':
+ return len * 2
+ case 'hex':
+ return len >>> 1
+ case 'base64':
+ return base64ToBytes(string).length
+ default:
+ if (loweredCase) {
+ return mustMatch ? -1 : utf8ToBytes(string).length // assume utf8
+ }
+ encoding = ('' + encoding).toLowerCase()
+ loweredCase = true
+ }
+ }
+}
+Buffer.byteLength = byteLength
+
+function slowToString (encoding, start, end) {
+ var loweredCase = false
+
+ // No need to verify that "this.length <= MAX_UINT32" since it's a read-only
+ // property of a typed array.
+
+ // This behaves neither like String nor Uint8Array in that we set start/end
+ // to their upper/lower bounds if the value passed is out of range.
+ // undefined is handled specially as per ECMA-262 6th Edition,
+ // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.
+ if (start === undefined || start < 0) {
+ start = 0
+ }
+ // Return early if start > this.length. Done here to prevent potential uint32
+ // coercion fail below.
+ if (start > this.length) {
+ return ''
+ }
+
+ if (end === undefined || end > this.length) {
+ end = this.length
+ }
+
+ if (end <= 0) {
+ return ''
+ }
+
+ // Force coersion to uint32. This will also coerce falsey/NaN values to 0.
+ end >>>= 0
+ start >>>= 0
+
+ if (end <= start) {
+ return ''
+ }
+
+ if (!encoding) encoding = 'utf8'
+
+ while (true) {
+ switch (encoding) {
+ case 'hex':
+ return hexSlice(this, start, end)
+
+ case 'utf8':
+ case 'utf-8':
+ return utf8Slice(this, start, end)
+
+ case 'ascii':
+ return asciiSlice(this, start, end)
+
+ case 'latin1':
+ case 'binary':
+ return latin1Slice(this, start, end)
+
+ case 'base64':
+ return base64Slice(this, start, end)
+
+ case 'ucs2':
+ case 'ucs-2':
+ case 'utf16le':
+ case 'utf-16le':
+ return utf16leSlice(this, start, end)
+
+ default:
+ if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
+ encoding = (encoding + '').toLowerCase()
+ loweredCase = true
+ }
+ }
+}
+
+// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package)
+// to detect a Buffer instance. It's not possible to use `instanceof Buffer`
+// reliably in a browserify context because there could be multiple different
+// copies of the 'buffer' package in use. This method works even for Buffer
+// instances that were created from another copy of the `buffer` package.
+// See: https://github.com/feross/buffer/issues/154
+Buffer.prototype._isBuffer = true
+
+function swap (b, n, m) {
+ var i = b[n]
+ b[n] = b[m]
+ b[m] = i
+}
+
+Buffer.prototype.swap16 = function swap16 () {
+ var len = this.length
+ if (len % 2 !== 0) {
+ throw new RangeError('Buffer size must be a multiple of 16-bits')
+ }
+ for (var i = 0; i < len; i += 2) {
+ swap(this, i, i + 1)
+ }
+ return this
+}
+
+Buffer.prototype.swap32 = function swap32 () {
+ var len = this.length
+ if (len % 4 !== 0) {
+ throw new RangeError('Buffer size must be a multiple of 32-bits')
+ }
+ for (var i = 0; i < len; i += 4) {
+ swap(this, i, i + 3)
+ swap(this, i + 1, i + 2)
+ }
+ return this
+}
+
+Buffer.prototype.swap64 = function swap64 () {
+ var len = this.length
+ if (len % 8 !== 0) {
+ throw new RangeError('Buffer size must be a multiple of 64-bits')
+ }
+ for (var i = 0; i < len; i += 8) {
+ swap(this, i, i + 7)
+ swap(this, i + 1, i + 6)
+ swap(this, i + 2, i + 5)
+ swap(this, i + 3, i + 4)
+ }
+ return this
+}
+
+Buffer.prototype.toString = function toString () {
+ var length = this.length
+ if (length === 0) return ''
+ if (arguments.length === 0) return utf8Slice(this, 0, length)
+ return slowToString.apply(this, arguments)
+}
+
+Buffer.prototype.toLocaleString = Buffer.prototype.toString
+
+Buffer.prototype.equals = function equals (b) {
+ if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
+ if (this === b) return true
+ return Buffer.compare(this, b) === 0
+}
+
+Buffer.prototype.inspect = function inspect () {
+ var str = ''
+ var max = exports.INSPECT_MAX_BYTES
+ str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim()
+ if (this.length > max) str += ' ... '
+ return '<Buffer ' + str + '>'
+}
+
+Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) {
+ if (isInstance(target, Uint8Array)) {
+ target = Buffer.from(target, target.offset, target.byteLength)
+ }
+ if (!Buffer.isBuffer(target)) {
+ throw new TypeError(
+ 'The "target" argument must be one of type Buffer or Uint8Array. ' +
+ 'Received type ' + (typeof target)
+ )
+ }
+
+ if (start === undefined) {
+ start = 0
+ }
+ if (end === undefined) {
+ end = target ? target.length : 0
+ }
+ if (thisStart === undefined) {
+ thisStart = 0
+ }
+ if (thisEnd === undefined) {
+ thisEnd = this.length
+ }
+
+ if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) {
+ throw new RangeError('out of range index')
+ }
+
+ if (thisStart >= thisEnd && start >= end) {
+ return 0
+ }
+ if (thisStart >= thisEnd) {
+ return -1
+ }
+ if (start >= end) {
+ return 1
+ }
+
+ start >>>= 0
+ end >>>= 0
+ thisStart >>>= 0
+ thisEnd >>>= 0
+
+ if (this === target) return 0
+
+ var x = thisEnd - thisStart
+ var y = end - start
+ var len = Math.min(x, y)
+
+ var thisCopy = this.slice(thisStart, thisEnd)
+ var targetCopy = target.slice(start, end)
+
+ for (var i = 0; i < len; ++i) {
+ if (thisCopy[i] !== targetCopy[i]) {
+ x = thisCopy[i]
+ y = targetCopy[i]
+ break
+ }
+ }
+
+ if (x < y) return -1
+ if (y < x) return 1
+ return 0
+}
+
+// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,
+// OR the last index of `val` in `buffer` at offset <= `byteOffset`.
+//
+// Arguments:
+// - buffer - a Buffer to search
+// - val - a string, Buffer, or number
+// - byteOffset - an index into `buffer`; will be clamped to an int32
+// - encoding - an optional encoding, relevant is val is a string
+// - dir - true for indexOf, false for lastIndexOf
+function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) {
+ // Empty buffer means no match
+ if (buffer.length === 0) return -1
+
+ // Normalize byteOffset
+ if (typeof byteOffset === 'string') {
+ encoding = byteOffset
+ byteOffset = 0
+ } else if (byteOffset > 0x7fffffff) {
+ byteOffset = 0x7fffffff
+ } else if (byteOffset < -0x80000000) {
+ byteOffset = -0x80000000
+ }
+ byteOffset = +byteOffset // Coerce to Number.
+ if (numberIsNaN(byteOffset)) {
+ // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer
+ byteOffset = dir ? 0 : (buffer.length - 1)
+ }
+
+ // Normalize byteOffset: negative offsets start from the end of the buffer
+ if (byteOffset < 0) byteOffset = buffer.length + byteOffset
+ if (byteOffset >= buffer.length) {
+ if (dir) return -1
+ else byteOffset = buffer.length - 1
+ } else if (byteOffset < 0) {
+ if (dir) byteOffset = 0
+ else return -1
+ }
+
+ // Normalize val
+ if (typeof val === 'string') {
+ val = Buffer.from(val, encoding)
+ }
+
+ // Finally, search either indexOf (if dir is true) or lastIndexOf
+ if (Buffer.isBuffer(val)) {
+ // Special case: looking for empty string/buffer always fails
+ if (val.length === 0) {
+ return -1
+ }
+ return arrayIndexOf(buffer, val, byteOffset, encoding, dir)
+ } else if (typeof val === 'number') {
+ val = val & 0xFF // Search for a byte value [0-255]
+ if (typeof Uint8Array.prototype.indexOf === 'function') {
+ if (dir) {
+ return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset)
+ } else {
+ return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset)
+ }
+ }
+ return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir)
+ }
+
+ throw new TypeError('val must be string, number or Buffer')
+}
+
+function arrayIndexOf (arr, val, byteOffset, encoding, dir) {
+ var indexSize = 1
+ var arrLength = arr.length
+ var valLength = val.length
+
+ if (encoding !== undefined) {
+ encoding = String(encoding).toLowerCase()
+ if (encoding === 'ucs2' || encoding === 'ucs-2' ||
+ encoding === 'utf16le' || encoding === 'utf-16le') {
+ if (arr.length < 2 || val.length < 2) {
+ return -1
+ }
+ indexSize = 2
+ arrLength /= 2
+ valLength /= 2
+ byteOffset /= 2
+ }
+ }
+
+ function read (buf, i) {
+ if (indexSize === 1) {
+ return buf[i]
+ } else {
+ return buf.readUInt16BE(i * indexSize)
+ }
+ }
+
+ var i
+ if (dir) {
+ var foundIndex = -1
+ for (i = byteOffset; i < arrLength; i++) {
+ if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {
+ if (foundIndex === -1) foundIndex = i
+ if (i - foundIndex + 1 === valLength) return foundIndex * indexSize
+ } else {
+ if (foundIndex !== -1) i -= i - foundIndex
+ foundIndex = -1
+ }
+ }
+ } else {
+ if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength
+ for (i = byteOffset; i >= 0; i--) {
+ var found = true
+ for (var j = 0; j < valLength; j++) {
+ if (read(arr, i + j) !== read(val, j)) {
+ found = false
+ break
+ }
+ }
+ if (found) return i
+ }
+ }
+
+ return -1
+}
+
+Buffer.prototype.includes = function includes (val, byteOffset, encoding) {
+ return this.indexOf(val, byteOffset, encoding) !== -1
+}
+
+Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) {
+ return bidirectionalIndexOf(this, val, byteOffset, encoding, true)
+}
+
+Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) {
+ return bidirectionalIndexOf(this, val, byteOffset, encoding, false)
+}
+
+function hexWrite (buf, string, offset, length) {
+ offset = Number(offset) || 0
+ var remaining = buf.length - offset
+ if (!length) {
+ length = remaining
+ } else {
+ length = Number(length)
+ if (length > remaining) {
+ length = remaining
+ }
+ }
+
+ var strLen = string.length
+
+ if (length > strLen / 2) {
+ length = strLen / 2
+ }
+ for (var i = 0; i < length; ++i) {
+ var parsed = parseInt(string.substr(i * 2, 2), 16)
+ if (numberIsNaN(parsed)) return i
+ buf[offset + i] = parsed
+ }
+ return i
+}
+
+function utf8Write (buf, string, offset, length) {
+ return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
+}
+
+function asciiWrite (buf, string, offset, length) {
+ return blitBuffer(asciiToBytes(string), buf, offset, length)
+}
+
+function latin1Write (buf, string, offset, length) {
+ return asciiWrite(buf, string, offset, length)
+}
+
+function base64Write (buf, string, offset, length) {
+ return blitBuffer(base64ToBytes(string), buf, offset, length)
+}
+
+function ucs2Write (buf, string, offset, length) {
+ return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
+}
+
+Buffer.prototype.write = function write (string, offset, length, encoding) {
+ // Buffer#write(string)
+ if (offset === undefined) {
+ encoding = 'utf8'
+ length = this.length
+ offset = 0
+ // Buffer#write(string, encoding)
+ } else if (length === undefined && typeof offset === 'string') {
+ encoding = offset
+ length = this.length
+ offset = 0
+ // Buffer#write(string, offset[, length][, encoding])
+ } else if (isFinite(offset)) {
+ offset = offset >>> 0
+ if (isFinite(length)) {
+ length = length >>> 0
+ if (encoding === undefined) encoding = 'utf8'
+ } else {
+ encoding = length
+ length = undefined
+ }
+ } else {
+ throw new Error(
+ 'Buffer.write(string, encoding, offset[, length]) is no longer supported'
+ )
+ }
+
+ var remaining = this.length - offset
+ if (length === undefined || length > remaining) length = remaining
+
+ if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
+ throw new RangeError('Attempt to write outside buffer bounds')
+ }
+
+ if (!encoding) encoding = 'utf8'
+
+ var loweredCase = false
+ for (;;) {
+ switch (encoding) {
+ case 'hex':
+ return hexWrite(this, string, offset, length)
+
+ case 'utf8':
+ case 'utf-8':
+ return utf8Write(this, string, offset, length)
+
+ case 'ascii':
+ return asciiWrite(this, string, offset, length)
+
+ case 'latin1':
+ case 'binary':
+ return latin1Write(this, string, offset, length)
+
+ case 'base64':
+ // Warning: maxLength not taken into account in base64Write
+ return base64Write(this, string, offset, length)
+
+ case 'ucs2':
+ case 'ucs-2':
+ case 'utf16le':
+ case 'utf-16le':
+ return ucs2Write(this, string, offset, length)
+
+ default:
+ if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
+ encoding = ('' + encoding).toLowerCase()
+ loweredCase = true
+ }
+ }
+}
+
+Buffer.prototype.toJSON = function toJSON () {
+ return {
+ type: 'Buffer',
+ data: Array.prototype.slice.call(this._arr || this, 0)
+ }
+}
+
+function base64Slice (buf, start, end) {
+ if (start === 0 && end === buf.length) {
+ return base64.fromByteArray(buf)
+ } else {
+ return base64.fromByteArray(buf.slice(start, end))
+ }
+}
+
+function utf8Slice (buf, start, end) {
+ end = Math.min(buf.length, end)
+ var res = []
+
+ var i = start
+ while (i < end) {
+ var firstByte = buf[i]
+ var codePoint = null
+ var bytesPerSequence = (firstByte > 0xEF) ? 4
+ : (firstByte > 0xDF) ? 3
+ : (firstByte > 0xBF) ? 2
+ : 1
+
+ if (i + bytesPerSequence <= end) {
+ var secondByte, thirdByte, fourthByte, tempCodePoint
+
+ switch (bytesPerSequence) {
+ case 1:
+ if (firstByte < 0x80) {
+ codePoint = firstByte
+ }
+ break
+ case 2:
+ secondByte = buf[i + 1]
+ if ((secondByte & 0xC0) === 0x80) {
+ tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
+ if (tempCodePoint > 0x7F) {
+ codePoint = tempCodePoint
+ }
+ }
+ break
+ case 3:
+ secondByte = buf[i + 1]
+ thirdByte = buf[i + 2]
+ if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
+ tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
+ if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
+ codePoint = tempCodePoint
+ }
+ }
+ break
+ case 4:
+ secondByte = buf[i + 1]
+ thirdByte = buf[i + 2]
+ fourthByte = buf[i + 3]
+ if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
+ tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
+ if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
+ codePoint = tempCodePoint
+ }
+ }
+ }
+ }
+
+ if (codePoint === null) {
+ // we did not generate a valid codePoint so insert a
+ // replacement char (U+FFFD) and advance only 1 byte
+ codePoint = 0xFFFD
+ bytesPerSequence = 1
+ } else if (codePoint > 0xFFFF) {
+ // encode to utf16 (surrogate pair dance)
+ codePoint -= 0x10000
+ res.push(codePoint >>> 10 & 0x3FF | 0xD800)
+ codePoint = 0xDC00 | codePoint & 0x3FF
+ }
+
+ res.push(codePoint)
+ i += bytesPerSequence
+ }
+
+ return decodeCodePointsArray(res)
+}
+
+// Based on http://stackoverflow.com/a/22747272/680742, the browser with
+// the lowest limit is Chrome, with 0x10000 args.
+// We go 1 magnitude less, for safety
+var MAX_ARGUMENTS_LENGTH = 0x1000
+
+function decodeCodePointsArray (codePoints) {
+ var len = codePoints.length
+ if (len <= MAX_ARGUMENTS_LENGTH) {
+ return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
+ }
+
+ // Decode in chunks to avoid "call stack size exceeded".
+ var res = ''
+ var i = 0
+ while (i < len) {
+ res += String.fromCharCode.apply(
+ String,
+ codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
+ )
+ }
+ return res
+}
+
+function asciiSlice (buf, start, end) {
+ var ret = ''
+ end = Math.min(buf.length, end)
+
+ for (var i = start; i < end; ++i) {
+ ret += String.fromCharCode(buf[i] & 0x7F)
+ }
+ return ret
+}
+
+function latin1Slice (buf, start, end) {
+ var ret = ''
+ end = Math.min(buf.length, end)
+
+ for (var i = start; i < end; ++i) {
+ ret += String.fromCharCode(buf[i])
+ }
+ return ret
+}
+
+function hexSlice (buf, start, end) {
+ var len = buf.length
+
+ if (!start || start < 0) start = 0
+ if (!end || end < 0 || end > len) end = len
+
+ var out = ''
+ for (var i = start; i < end; ++i) {
+ out += toHex(buf[i])
+ }
+ return out
+}
+
+function utf16leSlice (buf, start, end) {
+ var bytes = buf.slice(start, end)
+ var res = ''
+ for (var i = 0; i < bytes.length; i += 2) {
+ res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256))
+ }
+ return res
+}
+
+Buffer.prototype.slice = function slice (start, end) {
+ var len = this.length
+ start = ~~start
+ end = end === undefined ? len : ~~end
+
+ if (start < 0) {
+ start += len
+ if (start < 0) start = 0
+ } else if (start > len) {
+ start = len
+ }
+
+ if (end < 0) {
+ end += len
+ if (end < 0) end = 0
+ } else if (end > len) {
+ end = len
+ }
+
+ if (end < start) end = start
+
+ var newBuf = this.subarray(start, end)
+ // Return an augmented `Uint8Array` instance
+ newBuf.__proto__ = Buffer.prototype
+ return newBuf
+}
+
+/*
+ * Need to make sure that buffer isn't trying to write out of bounds.
+ */
+function checkOffset (offset, ext, length) {
+ if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
+ if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
+}
+
+Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
+ offset = offset >>> 0
+ byteLength = byteLength >>> 0
+ if (!noAssert) checkOffset(offset, byteLength, this.length)
+
+ var val = this[offset]
+ var mul = 1
+ var i = 0
+ while (++i < byteLength && (mul *= 0x100)) {
+ val += this[offset + i] * mul
+ }
+
+ return val
+}
+
+Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
+ offset = offset >>> 0
+ byteLength = byteLength >>> 0
+ if (!noAssert) {
+ checkOffset(offset, byteLength, this.length)
+ }
+
+ var val = this[offset + --byteLength]
+ var mul = 1
+ while (byteLength > 0 && (mul *= 0x100)) {
+ val += this[offset + --byteLength] * mul
+ }
+
+ return val
+}
+
+Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 1, this.length)
+ return this[offset]
+}
+
+Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 2, this.length)
+ return this[offset] | (this[offset + 1] << 8)
+}
+
+Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 2, this.length)
+ return (this[offset] << 8) | this[offset + 1]
+}
+
+Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 4, this.length)
+
+ return ((this[offset]) |
+ (this[offset + 1] << 8) |
+ (this[offset + 2] << 16)) +
+ (this[offset + 3] * 0x1000000)
+}
+
+Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 4, this.length)
+
+ return (this[offset] * 0x1000000) +
+ ((this[offset + 1] << 16) |
+ (this[offset + 2] << 8) |
+ this[offset + 3])
+}
+
+Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
+ offset = offset >>> 0
+ byteLength = byteLength >>> 0
+ if (!noAssert) checkOffset(offset, byteLength, this.length)
+
+ var val = this[offset]
+ var mul = 1
+ var i = 0
+ while (++i < byteLength && (mul *= 0x100)) {
+ val += this[offset + i] * mul
+ }
+ mul *= 0x80
+
+ if (val >= mul) val -= Math.pow(2, 8 * byteLength)
+
+ return val
+}
+
+Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
+ offset = offset >>> 0
+ byteLength = byteLength >>> 0
+ if (!noAssert) checkOffset(offset, byteLength, this.length)
+
+ var i = byteLength
+ var mul = 1
+ var val = this[offset + --i]
+ while (i > 0 && (mul *= 0x100)) {
+ val += this[offset + --i] * mul
+ }
+ mul *= 0x80
+
+ if (val >= mul) val -= Math.pow(2, 8 * byteLength)
+
+ return val
+}
+
+Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 1, this.length)
+ if (!(this[offset] & 0x80)) return (this[offset])
+ return ((0xff - this[offset] + 1) * -1)
+}
+
+Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 2, this.length)
+ var val = this[offset] | (this[offset + 1] << 8)
+ return (val & 0x8000) ? val | 0xFFFF0000 : val
+}
+
+Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 2, this.length)
+ var val = this[offset + 1] | (this[offset] << 8)
+ return (val & 0x8000) ? val | 0xFFFF0000 : val
+}
+
+Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 4, this.length)
+
+ return (this[offset]) |
+ (this[offset + 1] << 8) |
+ (this[offset + 2] << 16) |
+ (this[offset + 3] << 24)
+}
+
+Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 4, this.length)
+
+ return (this[offset] << 24) |
+ (this[offset + 1] << 16) |
+ (this[offset + 2] << 8) |
+ (this[offset + 3])
+}
+
+Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 4, this.length)
+ return ieee754.read(this, offset, true, 23, 4)
+}
+
+Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 4, this.length)
+ return ieee754.read(this, offset, false, 23, 4)
+}
+
+Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 8, this.length)
+ return ieee754.read(this, offset, true, 52, 8)
+}
+
+Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 8, this.length)
+ return ieee754.read(this, offset, false, 52, 8)
+}
+
+function checkInt (buf, value, offset, ext, max, min) {
+ if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance')
+ if (value > max || value < min) throw new RangeError('"value" argument is out of bounds')
+ if (offset + ext > buf.length) throw new RangeError('Index out of range')
+}
+
+Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ byteLength = byteLength >>> 0
+ if (!noAssert) {
+ var maxBytes = Math.pow(2, 8 * byteLength) - 1
+ checkInt(this, value, offset, byteLength, maxBytes, 0)
+ }
+
+ var mul = 1
+ var i = 0
+ this[offset] = value & 0xFF
+ while (++i < byteLength && (mul *= 0x100)) {
+ this[offset + i] = (value / mul) & 0xFF
+ }
+
+ return offset + byteLength
+}
+
+Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ byteLength = byteLength >>> 0
+ if (!noAssert) {
+ var maxBytes = Math.pow(2, 8 * byteLength) - 1
+ checkInt(this, value, offset, byteLength, maxBytes, 0)
+ }
+
+ var i = byteLength - 1
+ var mul = 1
+ this[offset + i] = value & 0xFF
+ while (--i >= 0 && (mul *= 0x100)) {
+ this[offset + i] = (value / mul) & 0xFF
+ }
+
+ return offset + byteLength
+}
+
+Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
+ this[offset] = (value & 0xff)
+ return offset + 1
+}
+
+Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
+ this[offset] = (value & 0xff)
+ this[offset + 1] = (value >>> 8)
+ return offset + 2
+}
+
+Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
+ this[offset] = (value >>> 8)
+ this[offset + 1] = (value & 0xff)
+ return offset + 2
+}
+
+Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
+ this[offset + 3] = (value >>> 24)
+ this[offset + 2] = (value >>> 16)
+ this[offset + 1] = (value >>> 8)
+ this[offset] = (value & 0xff)
+ return offset + 4
+}
+
+Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
+ this[offset] = (value >>> 24)
+ this[offset + 1] = (value >>> 16)
+ this[offset + 2] = (value >>> 8)
+ this[offset + 3] = (value & 0xff)
+ return offset + 4
+}
+
+Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) {
+ var limit = Math.pow(2, (8 * byteLength) - 1)
+
+ checkInt(this, value, offset, byteLength, limit - 1, -limit)
+ }
+
+ var i = 0
+ var mul = 1
+ var sub = 0
+ this[offset] = value & 0xFF
+ while (++i < byteLength && (mul *= 0x100)) {
+ if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {
+ sub = 1
+ }
+ this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
+ }
+
+ return offset + byteLength
+}
+
+Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) {
+ var limit = Math.pow(2, (8 * byteLength) - 1)
+
+ checkInt(this, value, offset, byteLength, limit - 1, -limit)
+ }
+
+ var i = byteLength - 1
+ var mul = 1
+ var sub = 0
+ this[offset + i] = value & 0xFF
+ while (--i >= 0 && (mul *= 0x100)) {
+ if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {
+ sub = 1
+ }
+ this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
+ }
+
+ return offset + byteLength
+}
+
+Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
+ if (value < 0) value = 0xff + value + 1
+ this[offset] = (value & 0xff)
+ return offset + 1
+}
+
+Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
+ this[offset] = (value & 0xff)
+ this[offset + 1] = (value >>> 8)
+ return offset + 2
+}
+
+Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
+ this[offset] = (value >>> 8)
+ this[offset + 1] = (value & 0xff)
+ return offset + 2
+}
+
+Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
+ this[offset] = (value & 0xff)
+ this[offset + 1] = (value >>> 8)
+ this[offset + 2] = (value >>> 16)
+ this[offset + 3] = (value >>> 24)
+ return offset + 4
+}
+
+Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
+ if (value < 0) value = 0xffffffff + value + 1
+ this[offset] = (value >>> 24)
+ this[offset + 1] = (value >>> 16)
+ this[offset + 2] = (value >>> 8)
+ this[offset + 3] = (value & 0xff)
+ return offset + 4
+}
+
+function checkIEEE754 (buf, value, offset, ext, max, min) {
+ if (offset + ext > buf.length) throw new RangeError('Index out of range')
+ if (offset < 0) throw new RangeError('Index out of range')
+}
+
+function writeFloat (buf, value, offset, littleEndian, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) {
+ checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
+ }
+ ieee754.write(buf, value, offset, littleEndian, 23, 4)
+ return offset + 4
+}
+
+Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
+ return writeFloat(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
+ return writeFloat(this, value, offset, false, noAssert)
+}
+
+function writeDouble (buf, value, offset, littleEndian, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) {
+ checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
+ }
+ ieee754.write(buf, value, offset, littleEndian, 52, 8)
+ return offset + 8
+}
+
+Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
+ return writeDouble(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
+ return writeDouble(this, value, offset, false, noAssert)
+}
+
+// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
+Buffer.prototype.copy = function copy (target, targetStart, start, end) {
+ if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer')
+ if (!start) start = 0
+ if (!end && end !== 0) end = this.length
+ if (targetStart >= target.length) targetStart = target.length
+ if (!targetStart) targetStart = 0
+ if (end > 0 && end < start) end = start
+
+ // Copy 0 bytes; we're done
+ if (end === start) return 0
+ if (target.length === 0 || this.length === 0) return 0
+
+ // Fatal error conditions
+ if (targetStart < 0) {
+ throw new RangeError('targetStart out of bounds')
+ }
+ if (start < 0 || start >= this.length) throw new RangeError('Index out of range')
+ if (end < 0) throw new RangeError('sourceEnd out of bounds')
+
+ // Are we oob?
+ if (end > this.length) end = this.length
+ if (target.length - targetStart < end - start) {
+ end = target.length - targetStart + start
+ }
+
+ var len = end - start
+
+ if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') {
+ // Use built-in when available, missing from IE11
+ this.copyWithin(targetStart, start, end)
+ } else if (this === target && start < targetStart && targetStart < end) {
+ // descending copy from end
+ for (var i = len - 1; i >= 0; --i) {
+ target[i + targetStart] = this[i + start]
+ }
+ } else {
+ Uint8Array.prototype.set.call(
+ target,
+ this.subarray(start, end),
+ targetStart
+ )
+ }
+
+ return len
+}
+
+// Usage:
+// buffer.fill(number[, offset[, end]])
+// buffer.fill(buffer[, offset[, end]])
+// buffer.fill(string[, offset[, end]][, encoding])
+Buffer.prototype.fill = function fill (val, start, end, encoding) {
+ // Handle string cases:
+ if (typeof val === 'string') {
+ if (typeof start === 'string') {
+ encoding = start
+ start = 0
+ end = this.length
+ } else if (typeof end === 'string') {
+ encoding = end
+ end = this.length
+ }
+ if (encoding !== undefined && typeof encoding !== 'string') {
+ throw new TypeError('encoding must be a string')
+ }
+ if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {
+ throw new TypeError('Unknown encoding: ' + encoding)
+ }
+ if (val.length === 1) {
+ var code = val.charCodeAt(0)
+ if ((encoding === 'utf8' && code < 128) ||
+ encoding === 'latin1') {
+ // Fast path: If `val` fits into a single byte, use that numeric value.
+ val = code
+ }
+ }
+ } else if (typeof val === 'number') {
+ val = val & 255
+ }
+
+ // Invalid ranges are not set to a default, so can range check early.
+ if (start < 0 || this.length < start || this.length < end) {
+ throw new RangeError('Out of range index')
+ }
+
+ if (end <= start) {
+ return this
+ }
+
+ start = start >>> 0
+ end = end === undefined ? this.length : end >>> 0
+
+ if (!val) val = 0
+
+ var i
+ if (typeof val === 'number') {
+ for (i = start; i < end; ++i) {
+ this[i] = val
+ }
+ } else {
+ var bytes = Buffer.isBuffer(val)
+ ? val
+ : Buffer.from(val, encoding)
+ var len = bytes.length
+ if (len === 0) {
+ throw new TypeError('The value "' + val +
+ '" is invalid for argument "value"')
+ }
+ for (i = 0; i < end - start; ++i) {
+ this[i + start] = bytes[i % len]
+ }
+ }
+
+ return this
+}
+
+// HELPER FUNCTIONS
+// ================
+
+var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g
+
+function base64clean (str) {
+ // Node takes equal signs as end of the Base64 encoding
+ str = str.split('=')[0]
+ // Node strips out invalid characters like \n and \t from the string, base64-js does not
+ str = str.trim().replace(INVALID_BASE64_RE, '')
+ // Node converts strings with length < 2 to ''
+ if (str.length < 2) return ''
+ // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
+ while (str.length % 4 !== 0) {
+ str = str + '='
+ }
+ return str
+}
+
+function toHex (n) {
+ if (n < 16) return '0' + n.toString(16)
+ return n.toString(16)
+}
+
+function utf8ToBytes (string, units) {
+ units = units || Infinity
+ var codePoint
+ var length = string.length
+ var leadSurrogate = null
+ var bytes = []
+
+ for (var i = 0; i < length; ++i) {
+ codePoint = string.charCodeAt(i)
+
+ // is surrogate component
+ if (codePoint > 0xD7FF && codePoint < 0xE000) {
+ // last char was a lead
+ if (!leadSurrogate) {
+ // no lead yet
+ if (codePoint > 0xDBFF) {
+ // unexpected trail
+ if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+ continue
+ } else if (i + 1 === length) {
+ // unpaired lead
+ if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+ continue
+ }
+
+ // valid lead
+ leadSurrogate = codePoint
+
+ continue
+ }
+
+ // 2 leads in a row
+ if (codePoint < 0xDC00) {
+ if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+ leadSurrogate = codePoint
+ continue
+ }
+
+ // valid surrogate pair
+ codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
+ } else if (leadSurrogate) {
+ // valid bmp char, but last char was a lead
+ if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+ }
+
+ leadSurrogate = null
+
+ // encode utf8
+ if (codePoint < 0x80) {
+ if ((units -= 1) < 0) break
+ bytes.push(codePoint)
+ } else if (codePoint < 0x800) {
+ if ((units -= 2) < 0) break
+ bytes.push(
+ codePoint >> 0x6 | 0xC0,
+ codePoint & 0x3F | 0x80
+ )
+ } else if (codePoint < 0x10000) {
+ if ((units -= 3) < 0) break
+ bytes.push(
+ codePoint >> 0xC | 0xE0,
+ codePoint >> 0x6 & 0x3F | 0x80,
+ codePoint & 0x3F | 0x80
+ )
+ } else if (codePoint < 0x110000) {
+ if ((units -= 4) < 0) break
+ bytes.push(
+ codePoint >> 0x12 | 0xF0,
+ codePoint >> 0xC & 0x3F | 0x80,
+ codePoint >> 0x6 & 0x3F | 0x80,
+ codePoint & 0x3F | 0x80
+ )
+ } else {
+ throw new Error('Invalid code point')
+ }
+ }
+
+ return bytes
+}
+
+function asciiToBytes (str) {
+ var byteArray = []
+ for (var i = 0; i < str.length; ++i) {
+ // Node's code seems to be doing this and not & 0x7F..
+ byteArray.push(str.charCodeAt(i) & 0xFF)
+ }
+ return byteArray
+}
+
+function utf16leToBytes (str, units) {
+ var c, hi, lo
+ var byteArray = []
+ for (var i = 0; i < str.length; ++i) {
+ if ((units -= 2) < 0) break
+
+ c = str.charCodeAt(i)
+ hi = c >> 8
+ lo = c % 256
+ byteArray.push(lo)
+ byteArray.push(hi)
+ }
+
+ return byteArray
+}
+
+function base64ToBytes (str) {
+ return base64.toByteArray(base64clean(str))
+}
+
+function blitBuffer (src, dst, offset, length) {
+ for (var i = 0; i < length; ++i) {
+ if ((i + offset >= dst.length) || (i >= src.length)) break
+ dst[i + offset] = src[i]
+ }
+ return i
+}
+
+// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass
+// the `instanceof` check but they should be treated as of that type.
+// See: https://github.com/feross/buffer/issues/166
+function isInstance (obj, type) {
+ return obj instanceof type ||
+ (obj != null && obj.constructor != null && obj.constructor.name != null &&
+ obj.constructor.name === type.name)
+}
+function numberIsNaN (obj) {
+ // For IE11 support
+ return obj !== obj // eslint-disable-line no-self-compare
+}
+
+},{"base64-js":3,"ieee754":11}],5:[function(require,module,exports){
+var charenc = {
+ // UTF-8 encoding
+ utf8: {
+ // Convert a string to a byte array
+ stringToBytes: function(str) {
+ return charenc.bin.stringToBytes(unescape(encodeURIComponent(str)));
+ },
+
+ // Convert a byte array to a string
+ bytesToString: function(bytes) {
+ return decodeURIComponent(escape(charenc.bin.bytesToString(bytes)));
+ }
+ },
+
+ // Binary encoding
+ bin: {
+ // Convert a string to a byte array
+ stringToBytes: function(str) {
+ for (var bytes = [], i = 0; i < str.length; i++)
+ bytes.push(str.charCodeAt(i) & 0xFF);
+ return bytes;
+ },
+
+ // Convert a byte array to a string
+ bytesToString: function(bytes) {
+ for (var str = [], i = 0; i < bytes.length; i++)
+ str.push(String.fromCharCode(bytes[i]));
+ return str.join('');
+ }
+ }
+};
+
+module.exports = charenc;
+
+},{}],6:[function(require,module,exports){
+/** Wrap an API that uses callbacks with Promises
+ * This expects the pattern function withCallback(arg1, arg2, ... argN, callback)
+ * @author Keith Henry <keith.henry@evolutionjobs.co.uk>
+ * @license MIT */
+(function () {
+ 'use strict';
+
+ /** Wrap a function with a callback with a Promise.
+ * @param {function} f The function to wrap, should be pattern: withCallback(arg1, arg2, ... argN, callback).
+ * @param {function} parseCB Optional function to parse multiple callback parameters into a single object.
+ * @returns {Promise} Promise that resolves when the callback fires. */
+ function promisify(f, parseCB) {
+ return (...args) => {
+ let safeArgs = args;
+ let callback;
+ // The Chrome API functions all use arguments, so we can't use f.length to check
+
+ // If there is a last arg
+ if (args && args.length > 0) {
+
+ // ... and the last arg is a function
+ const last = args[args.length - 1];
+ if (typeof last === 'function') {
+ // Trim the last callback arg if it's been passed
+ safeArgs = args.slice(0, args.length - 1);
+ callback = last;
+ }
+ }
+
+ // Return a promise
+ return new Promise((resolve, reject) => {
+ try {
+ // Try to run the original function, with the trimmed args list
+ f(...safeArgs, (...cbArgs) => {
+
+ // If a callback was passed at the end of the original arguments
+ if (callback) {
+ // Don't allow a bug in the callback to stop the promise resolving
+ try { callback(...cbArgs); }
+ catch (cbErr) { reject(cbErr); }
+ }
+
+ // Chrome extensions always fire the callback, but populate chrome.runtime.lastError with exception details
+ if (chrome.runtime.lastError)
+ // Return as an error for the awaited catch block
+ reject(new Error(chrome.runtime.lastError.message || `Error thrown by API ${chrome.runtime.lastError}`));
+ else {
+ if (parseCB) {
+ const cbObj = parseCB(...cbArgs);
+ resolve(cbObj);
+ }
+ else if (!cbArgs || cbArgs.length === 0)
+ resolve();
+ else if (cbArgs.length === 1)
+ resolve(cbArgs[0]);
+ else
+ resolve(cbArgs);
+ }
+ });
+ }
+ catch (err) { reject(err); }
+ });
+ }
+ }
+
+ /** Promisify all the known functions in the map
+ * @param {object} api The Chrome native API to extend
+ * @param {Array} apiMap Collection of sub-API and functions to promisify */
+ function applyMap(api, apiMap) {
+ if (!api)
+ // Not supported by current permissions
+ return;
+
+ for (let funcDef of apiMap) {
+ let funcName;
+ if (typeof funcDef === 'string')
+ funcName = funcDef;
+ else {
+ funcName = funcDef.n;
+ }
+
+ if (!api.hasOwnProperty(funcName))
+ // Member not in API
+ continue;
+
+ const m = api[funcName];
+ if (typeof m === 'function')
+ // This is a function, wrap in a promise
+ api[funcName] = promisify(m.bind(api), funcDef.cb);
+ else
+ // Sub-API, recurse this func with the mapped props
+ applyMap(m, funcDef.props);
+ }
+ }
+
+ /** Apply promise-maps to the Chrome native API.
+ * @param {object} apiMaps The API to apply. */
+ function applyMaps(apiMaps) {
+ for (let apiName in apiMaps) {
+ const callbackApi = chrome[apiName];
+ if (!callbackApi)
+ // Not supported by current permissions
+ continue;
+
+ const apiMap = apiMaps[apiName];
+ applyMap(callbackApi, apiMap);
+ }
+ }
+
+ // accessibilityFeatures https://developer.chrome.com/extensions/accessibilityFeatures
+ const knownA11ySetting = ['get', 'set', 'clear'];
+
+ // ContentSetting https://developer.chrome.com/extensions/contentSettings#type-ContentSetting
+ const knownInContentSetting = ['clear', 'get', 'set', 'getResourceIdentifiers'];
+
+ // StorageArea https://developer.chrome.com/extensions/storage#type-StorageArea
+ const knownInStorageArea = ['get', 'getBytesInUse', 'set', 'remove', 'clear'];
+
+ /** Map of API functions that follow the callback pattern that we can 'promisify' */
+ applyMaps({
+ accessibilityFeatures: [ // Todo: this should extend AccessibilityFeaturesSetting.prototype instead
+ { n: 'spokenFeedback', props: knownA11ySetting },
+ { n: 'largeCursor', props: knownA11ySetting },
+ { n: 'stickyKeys', props: knownA11ySetting },
+ { n: 'highContrast', props: knownA11ySetting },
+ { n: 'screenMagnifier', props: knownA11ySetting },
+ { n: 'autoclick', props: knownA11ySetting },
+ { n: 'virtualKeyboard', props: knownA11ySetting },
+ { n: 'animationPolicy', props: knownA11ySetting }],
+ alarms: ['get', 'getAll', 'clear', 'clearAll'],
+ bookmarks: [
+ 'get', 'getChildren', 'getRecent', 'getTree', 'getSubTree',
+ 'search', 'create', 'move', 'update', 'remove', 'removeTree'],
+ browser: ['openTab'],
+ browserAction: [
+ 'getTitle', 'setIcon', 'getPopup', 'getBadgeText', 'getBadgeBackgroundColor'],
+ browsingData: [
+ 'settings', 'remove', 'removeAppcache', 'removeCache',
+ 'removeCookies', 'removeDownloads', 'removeFileSystems',
+ 'removeFormData', 'removeHistory', 'removeIndexedDB',
+ 'removeLocalStorage', 'removePluginData', 'removePasswords',
+ 'removeWebSQL'],
+ commands: ['getAll'],
+ contentSettings: [ // Todo: this should extend ContentSetting.prototype instead
+ { n: 'cookies', props: knownInContentSetting },
+ { n: 'images', props: knownInContentSetting },
+ { n: 'javascript', props: knownInContentSetting },
+ { n: 'location', props: knownInContentSetting },
+ { n: 'plugins', props: knownInContentSetting },
+ { n: 'popups', props: knownInContentSetting },
+ { n: 'notifications', props: knownInContentSetting },
+ { n: 'fullscreen', props: knownInContentSetting },
+ { n: 'mouselock', props: knownInContentSetting },
+ { n: 'microphone', props: knownInContentSetting },
+ { n: 'camera', props: knownInContentSetting },
+ { n: 'unsandboxedPlugins', props: knownInContentSetting },
+ { n: 'automaticDownloads', props: knownInContentSetting }],
+ contextMenus: ['create', 'update', 'remove', 'removeAll'],
+ cookies: ['get', 'getAll', 'set', 'remove', 'getAllCookieStores'],
+ debugger: ['attach', 'detach', 'sendCommand', 'getTargets'],
+ desktopCapture: ['chooseDesktopMedia'],
+ // TODO: devtools.*
+ documentScan: ['scan'],
+ downloads: [
+ 'download', 'search', 'pause', 'resume', 'cancel',
+ 'getFileIcon', 'erase', 'removeFile', 'acceptDanger'],
+ enterprise: [{ n: 'platformKeys', props: ['getToken', 'getCertificates', 'importCertificate', 'removeCertificate'] }],
+ extension: ['isAllowedIncognitoAccess', 'isAllowedFileSchemeAccess'], // mostly deprecated in favour of runtime
+ fileBrowserHandler: ['selectFile'],
+ fileSystemProvider: ['mount', 'unmount', 'getAll', 'get', 'notify'],
+ fontSettings: [
+ 'setDefaultFontSize', 'getFont', 'getDefaultFontSize', 'getMinimumFontSize',
+ 'setMinimumFontSize', 'getDefaultFixedFontSize', 'clearDefaultFontSize',
+ 'setDefaultFixedFontSize', 'clearFont', 'setFont', 'clearMinimumFontSize',
+ 'getFontList', 'clearDefaultFixedFontSize'],
+ gcm: ['register', 'unregister', 'send'],
+ history: ['search', 'getVisits', 'addUrl', 'deleteUrl', 'deleteRange', 'deleteAll'],
+ i18n: ['getAcceptLanguages', 'detectLanguage'],
+ identity: [
+ 'getAuthToken', 'getProfileUserInfo', 'removeCachedAuthToken', 'launchWebAuthFlow'],
+ idle: ['queryState'],
+ input: [{
+ n: 'ime', props: [
+ 'setMenuItems', 'commitText', 'setCandidates', 'setComposition', 'updateMenuItems',
+ 'setCandidateWindowProperties', 'clearComposition', 'setCursorPosition', 'sendKeyEvents',
+ 'deleteSurroundingText']
+ }],
+ management: [
+ 'setEnabled', 'getPermissionWarningsById', 'get', 'getAll',
+ 'getPermissionWarningsByManifest', 'launchApp', 'uninstall', 'getSelf',
+ 'uninstallSelf', 'createAppShortcut', 'setLaunchType', 'generateAppForLink'],
+ networking: [{ n: 'config', props: ['setNetworkFilter', 'finishAuthentication'] }],
+ notifications: ['create', 'update', 'clear', 'getAll', 'getPermissionLevel'],
+ pageAction: ['getTitle', 'setIcon', 'getPopup'],
+ pageCapture: ['saveAsMHTML'],
+ permissions: ['getAll', 'contains', 'request', 'remove'],
+ platformKeys: ['selectClientCertificates', 'verifyTLSServerCertificate',
+ { n: "getKeyPair", cb: (publicKey, privateKey) => { return { publicKey, privateKey }; } }],
+ runtime: [
+ 'getBackgroundPage', 'openOptionsPage', 'setUninstallURL',
+ 'restartAfterDelay', 'sendMessage',
+ 'sendNativeMessage', 'getPlatformInfo', 'getPackageDirectoryEntry',
+ { n: "requestUpdateCheck", cb: (status, details) => { return { status, details }; } }],
+ scriptBadge: ['getPopup'],
+ sessions: ['getRecentlyClosed', 'getDevices', 'restore'],
+ storage: [ // Todo: this should extend StorageArea.prototype instead
+ { n: 'sync', props: knownInStorageArea },
+ { n: 'local', props: knownInStorageArea },
+ { n: 'managed', props: knownInStorageArea }],
+ socket: [
+ 'create', 'connect', 'bind', 'read', 'write', 'recvFrom', 'sendTo',
+ 'listen', 'accept', 'setKeepAlive', 'setNoDelay', 'getInfo', 'getNetworkList'],
+ sockets: [
+ { n: 'tcp', props: [
+ 'create','update','setPaused','setKeepAlive','setNoDelay','connect',
+ 'disconnect','secure','send','close','getInfo','getSockets'] },
+ { n: 'tcpServer', props: [
+ 'create','update','setPaused','listen','disconnect','close','getInfo','getSockets'] },
+ { n: 'udp', props: [
+ 'create','update','setPaused','bind','send','close','getInfo',
+ 'getSockets','joinGroup','leaveGroup','setMulticastTimeToLive',
+ 'setMulticastLoopbackMode','getJoinedGroups','setBroadcast'] }],
+ system: [
+ { n: 'cpu', props: ['getInfo'] },
+ { n: 'memory', props: ['getInfo'] },
+ { n: 'storage', props: ['getInfo', 'ejectDevice', 'getAvailableCapacity'] }],
+ tabCapture: ['capture', 'getCapturedTabs'],
+ tabs: [
+ 'get', 'getCurrent', 'sendMessage', 'create', 'duplicate',
+ 'query', 'highlight', 'update', 'move', 'reload', 'remove',
+ 'detectLanguage', 'captureVisibleTab', 'executeScript',
+ 'insertCSS', 'setZoom', 'getZoom', 'setZoomSettings',
+ 'getZoomSettings', 'discard'],
+ topSites: ['get'],
+ tts: ['isSpeaking', 'getVoices', 'speak'],
+ types: ['set', 'get', 'clear'],
+ vpnProvider: ['createConfig', 'destroyConfig', 'setParameters', 'sendPacket', 'notifyConnectionStateChanged'],
+ wallpaper: ['setWallpaper'],
+ webNavigation: ['getFrame', 'getAllFrames', 'handlerBehaviorChanged'],
+ windows: ['get', 'getCurrent', 'getLastFocused', 'getAll', 'create', 'update', 'remove']
+ });
+})();
+
+},{}],7:[function(require,module,exports){
+(function() {
+ var base64map
+ = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
+
+ crypt = {
+ // Bit-wise rotation left
+ rotl: function(n, b) {
+ return (n << b) | (n >>> (32 - b));
+ },
+
+ // Bit-wise rotation right
+ rotr: function(n, b) {
+ return (n << (32 - b)) | (n >>> b);
+ },
+
+ // Swap big-endian to little-endian and vice versa
+ endian: function(n) {
+ // If number given, swap endian
+ if (n.constructor == Number) {
+ return crypt.rotl(n, 8) & 0x00FF00FF | crypt.rotl(n, 24) & 0xFF00FF00;
+ }
+
+ // Else, assume array and swap all items
+ for (var i = 0; i < n.length; i++)
+ n[i] = crypt.endian(n[i]);
+ return n;
+ },
+
+ // Generate an array of any length of random bytes
+ randomBytes: function(n) {
+ for (var bytes = []; n > 0; n--)
+ bytes.push(Math.floor(Math.random() * 256));
+ return bytes;
+ },
+
+ // Convert a byte array to big-endian 32-bit words
+ bytesToWords: function(bytes) {
+ for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8)
+ words[b >>> 5] |= bytes[i] << (24 - b % 32);
+ return words;
+ },
+
+ // Convert big-endian 32-bit words to a byte array
+ wordsToBytes: function(words) {
+ for (var bytes = [], b = 0; b < words.length * 32; b += 8)
+ bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);
+ return bytes;
+ },
+
+ // Convert a byte array to a hex string
+ bytesToHex: function(bytes) {
+ for (var hex = [], i = 0; i < bytes.length; i++) {
+ hex.push((bytes[i] >>> 4).toString(16));
+ hex.push((bytes[i] & 0xF).toString(16));
+ }
+ return hex.join('');
+ },
+
+ // Convert a hex string to a byte array
+ hexToBytes: function(hex) {
+ for (var bytes = [], c = 0; c < hex.length; c += 2)
+ bytes.push(parseInt(hex.substr(c, 2), 16));
+ return bytes;
+ },
+
+ // Convert a byte array to a base-64 string
+ bytesToBase64: function(bytes) {
+ for (var base64 = [], i = 0; i < bytes.length; i += 3) {
+ var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
+ for (var j = 0; j < 4; j++)
+ if (i * 8 + j * 6 <= bytes.length * 8)
+ base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F));
+ else
+ base64.push('=');
+ }
+ return base64.join('');
+ },
+
+ // Convert a base-64 string to a byte array
+ base64ToBytes: function(base64) {
+ // Remove non-base-64 characters
+ base64 = base64.replace(/[^A-Z0-9+\/]/ig, '');
+
+ for (var bytes = [], i = 0, imod4 = 0; i < base64.length;
+ imod4 = ++i % 4) {
+ if (imod4 == 0) continue;
+ bytes.push(((base64map.indexOf(base64.charAt(i - 1))
+ & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2))
+ | (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2)));
+ }
+ return bytes;
+ }
+ };
+
+ module.exports = crypt;
+})();
+
+},{}],8:[function(require,module,exports){
+(function (setImmediate){
+/*
+WHAT: SublimeText-like Fuzzy Search
+
+USAGE:
+ fuzzysort.single('fs', 'Fuzzy Search') // {score: -16}
+ fuzzysort.single('test', 'test') // {score: 0}
+ fuzzysort.single('doesnt exist', 'target') // null
+
+ fuzzysort.go('mr', ['Monitor.cpp', 'MeshRenderer.cpp'])
+ // [{score: -18, target: "MeshRenderer.cpp"}, {score: -6009, target: "Monitor.cpp"}]
+
+ fuzzysort.highlight(fuzzysort.single('fs', 'Fuzzy Search'), '<b>', '</b>')
+ // <b>F</b>uzzy <b>S</b>earch
+*/
+
+// UMD (Universal Module Definition) for fuzzysort
+;(function(root, UMD) {
+ if(typeof define === 'function' && define.amd) define([], UMD)
+ else if(typeof module === 'object' && module.exports) module.exports = UMD()
+ else root.fuzzysort = UMD()
+})(this, function UMD() { function fuzzysortNew(instanceOptions) {
+
+ var fuzzysort = {
+
+ single: function(search, target, options) {
+ if(!search) return null
+ if(!isObj(search)) search = fuzzysort.getPreparedSearch(search)
+
+ if(!target) return null
+ if(!isObj(target)) target = fuzzysort.getPrepared(target)
+
+ var allowTypo = options && options.allowTypo!==undefined ? options.allowTypo
+ : instanceOptions && instanceOptions.allowTypo!==undefined ? instanceOptions.allowTypo
+ : true
+ var algorithm = allowTypo ? fuzzysort.algorithm : fuzzysort.algorithmNoTypo
+ return algorithm(search, target, search[0])
+ // var threshold = options && options.threshold || instanceOptions && instanceOptions.threshold || -9007199254740991
+ // var result = algorithm(search, target, search[0])
+ // if(result === null) return null
+ // if(result.score < threshold) return null
+ // return result
+ },
+
+ go: function(search, targets, options) {
+ if(!search) return noResults
+ search = fuzzysort.prepareSearch(search)
+ var searchLowerCode = search[0]
+
+ var threshold = options && options.threshold || instanceOptions && instanceOptions.threshold || -9007199254740991
+ var limit = options && options.limit || instanceOptions && instanceOptions.limit || 9007199254740991
+ var allowTypo = options && options.allowTypo!==undefined ? options.allowTypo
+ : instanceOptions && instanceOptions.allowTypo!==undefined ? instanceOptions.allowTypo
+ : true
+ var algorithm = allowTypo ? fuzzysort.algorithm : fuzzysort.algorithmNoTypo
+ var resultsLen = 0; var limitedCount = 0
+ var targetsLen = targets.length
+
+ // This code is copy/pasted 3 times for performance reasons [options.keys, options.key, no keys]
+
+ // options.keys
+ if(options && options.keys) {
+ var scoreFn = options.scoreFn || defaultScoreFn
+ var keys = options.keys
+ var keysLen = keys.length
+ for(var i = targetsLen - 1; i >= 0; --i) { var obj = targets[i]
+ var objResults = new Array(keysLen)
+ for (var keyI = keysLen - 1; keyI >= 0; --keyI) {
+ var key = keys[keyI]
+ var target = getValue(obj, key)
+ if(!target) { objResults[keyI] = null; continue }
+ if(!isObj(target)) target = fuzzysort.getPrepared(target)
+
+ objResults[keyI] = algorithm(search, target, searchLowerCode)
+ }
+ objResults.obj = obj // before scoreFn so scoreFn can use it
+ var score = scoreFn(objResults)
+ if(score === null) continue
+ if(score < threshold) continue
+ objResults.score = score
+ if(resultsLen < limit) { q.add(objResults); ++resultsLen }
+ else {
+ ++limitedCount
+ if(score > q.peek().score) q.replaceTop(objResults)
+ }
+ }
+
+ // options.key
+ } else if(options && options.key) {
+ var key = options.key
+ for(var i = targetsLen - 1; i >= 0; --i) { var obj = targets[i]
+ var target = getValue(obj, key)
+ if(!target) continue
+ if(!isObj(target)) target = fuzzysort.getPrepared(target)
+
+ var result = algorithm(search, target, searchLowerCode)
+ if(result === null) continue
+ if(result.score < threshold) continue
+
+ // have to clone result so duplicate targets from different obj can each reference the correct obj
+ result = {target:result.target, _targetLowerCodes:null, _nextBeginningIndexes:null, score:result.score, indexes:result.indexes, obj:obj} // hidden
+
+ if(resultsLen < limit) { q.add(result); ++resultsLen }
+ else {
+ ++limitedCount
+ if(result.score > q.peek().score) q.replaceTop(result)
+ }
+ }
+
+ // no keys
+ } else {
+ for(var i = targetsLen - 1; i >= 0; --i) { var target = targets[i]
+ if(!target) continue
+ if(!isObj(target)) target = fuzzysort.getPrepared(target)
+
+ var result = algorithm(search, target, searchLowerCode)
+ if(result === null) continue
+ if(result.score < threshold) continue
+ if(resultsLen < limit) { q.add(result); ++resultsLen }
+ else {
+ ++limitedCount
+ if(result.score > q.peek().score) q.replaceTop(result)
+ }
+ }
+ }
+
+ if(resultsLen === 0) return noResults
+ var results = new Array(resultsLen)
+ for(var i = resultsLen - 1; i >= 0; --i) results[i] = q.poll()
+ results.total = resultsLen + limitedCount
+ return results
+ },
+
+ goAsync: function(search, targets, options) {
+ var canceled = false
+ var p = new Promise(function(resolve, reject) {
+ if(!search) return resolve(noResults)
+ search = fuzzysort.prepareSearch(search)
+ var searchLowerCode = search[0]
+
+ var q = fastpriorityqueue()
+ var iCurrent = targets.length - 1
+ var threshold = options && options.threshold || instanceOptions && instanceOptions.threshold || -9007199254740991
+ var limit = options && options.limit || instanceOptions && instanceOptions.limit || 9007199254740991
+ var allowTypo = options && options.allowTypo!==undefined ? options.allowTypo
+ : instanceOptions && instanceOptions.allowTypo!==undefined ? instanceOptions.allowTypo
+ : true
+ var algorithm = allowTypo ? fuzzysort.algorithm : fuzzysort.algorithmNoTypo
+ var resultsLen = 0; var limitedCount = 0
+ function step() {
+ if(canceled) return reject('canceled')
+
+ var startMs = Date.now()
+
+ // This code is copy/pasted 3 times for performance reasons [options.keys, options.key, no keys]
+
+ // options.keys
+ if(options && options.keys) {
+ var scoreFn = options.scoreFn || defaultScoreFn
+ var keys = options.keys
+ var keysLen = keys.length
+ for(; iCurrent >= 0; --iCurrent) { var obj = targets[iCurrent]
+ var objResults = new Array(keysLen)
+ for (var keyI = keysLen - 1; keyI >= 0; --keyI) {
+ var key = keys[keyI]
+ var target = getValue(obj, key)
+ if(!target) { objResults[keyI] = null; continue }
+ if(!isObj(target)) target = fuzzysort.getPrepared(target)
+
+ objResults[keyI] = algorithm(search, target, searchLowerCode)
+ }
+ objResults.obj = obj // before scoreFn so scoreFn can use it
+ var score = scoreFn(objResults)
+ if(score === null) continue
+ if(score < threshold) continue
+ objResults.score = score
+ if(resultsLen < limit) { q.add(objResults); ++resultsLen }
+ else {
+ ++limitedCount
+ if(score > q.peek().score) q.replaceTop(objResults)
+ }
+
+ if(iCurrent%1000/*itemsPerCheck*/ === 0) {
+ if(Date.now() - startMs >= 10/*asyncInterval*/) {
+ isNode?setImmediate(step):setTimeout(step)
+ return
+ }
+ }
+ }
+
+ // options.key
+ } else if(options && options.key) {
+ var key = options.key
+ for(; iCurrent >= 0; --iCurrent) { var obj = targets[iCurrent]
+ var target = getValue(obj, key)
+ if(!target) continue
+ if(!isObj(target)) target = fuzzysort.getPrepared(target)
+
+ var result = algorithm(search, target, searchLowerCode)
+ if(result === null) continue
+ if(result.score < threshold) continue
+
+ // have to clone result so duplicate targets from different obj can each reference the correct obj
+ result = {target:result.target, _targetLowerCodes:null, _nextBeginningIndexes:null, score:result.score, indexes:result.indexes, obj:obj} // hidden
+
+ if(resultsLen < limit) { q.add(result); ++resultsLen }
+ else {
+ ++limitedCount
+ if(result.score > q.peek().score) q.replaceTop(result)
+ }
+
+ if(iCurrent%1000/*itemsPerCheck*/ === 0) {
+ if(Date.now() - startMs >= 10/*asyncInterval*/) {
+ isNode?setImmediate(step):setTimeout(step)
+ return
+ }
+ }
+ }
+
+ // no keys
+ } else {
+ for(; iCurrent >= 0; --iCurrent) { var target = targets[iCurrent]
+ if(!target) continue
+ if(!isObj(target)) target = fuzzysort.getPrepared(target)
+
+ var result = algorithm(search, target, searchLowerCode)
+ if(result === null) continue
+ if(result.score < threshold) continue
+ if(resultsLen < limit) { q.add(result); ++resultsLen }
+ else {
+ ++limitedCount
+ if(result.score > q.peek().score) q.replaceTop(result)
+ }
+
+ if(iCurrent%1000/*itemsPerCheck*/ === 0) {
+ if(Date.now() - startMs >= 10/*asyncInterval*/) {
+ isNode?setImmediate(step):setTimeout(step)
+ return
+ }
+ }
+ }
+ }
+
+ if(resultsLen === 0) return resolve(noResults)
+ var results = new Array(resultsLen)
+ for(var i = resultsLen - 1; i >= 0; --i) results[i] = q.poll()
+ results.total = resultsLen + limitedCount
+ resolve(results)
+ }
+
+ isNode?setImmediate(step):step()
+ })
+ p.cancel = function() { canceled = true }
+ return p
+ },
+
+ highlight: function(result, hOpen, hClose) {
+ if(result === null) return null
+ if(hOpen === undefined) hOpen = '<b>'
+ if(hClose === undefined) hClose = '</b>'
+ var highlighted = ''
+ var matchesIndex = 0
+ var opened = false
+ var target = result.target
+ var targetLen = target.length
+ var matchesBest = result.indexes
+ for(var i = 0; i < targetLen; ++i) { var char = target[i]
+ if(matchesBest[matchesIndex] === i) {
+ ++matchesIndex
+ if(!opened) { opened = true
+ highlighted += hOpen
+ }
+
+ if(matchesIndex === matchesBest.length) {
+ highlighted += char + hClose + target.substr(i+1)
+ break
+ }
+ } else {
+ if(opened) { opened = false
+ highlighted += hClose
+ }
+ }
+ highlighted += char
+ }
+
+ return highlighted
+ },
+
+ prepare: function(target) {
+ if(!target) return
+ return {target:target, _targetLowerCodes:fuzzysort.prepareLowerCodes(target), _nextBeginningIndexes:null, score:null, indexes:null, obj:null} // hidden
+ },
+ prepareSlow: function(target) {
+ if(!target) return
+ return {target:target, _targetLowerCodes:fuzzysort.prepareLowerCodes(target), _nextBeginningIndexes:fuzzysort.prepareNextBeginningIndexes(target), score:null, indexes:null, obj:null} // hidden
+ },
+ prepareSearch: function(search) {
+ if(!search) return
+ return fuzzysort.prepareLowerCodes(search)
+ },
+
+
+
+ // Below this point is only internal code
+ // Below this point is only internal code
+ // Below this point is only internal code
+ // Below this point is only internal code
+
+
+
+ getPrepared: function(target) {
+ if(target.length > 999) return fuzzysort.prepare(target) // don't cache huge targets
+ var targetPrepared = preparedCache.get(target)
+ if(targetPrepared !== undefined) return targetPrepared
+ targetPrepared = fuzzysort.prepare(target)
+ preparedCache.set(target, targetPrepared)
+ return targetPrepared
+ },
+ getPreparedSearch: function(search) {
+ if(search.length > 999) return fuzzysort.prepareSearch(search) // don't cache huge searches
+ var searchPrepared = preparedSearchCache.get(search)
+ if(searchPrepared !== undefined) return searchPrepared
+ searchPrepared = fuzzysort.prepareSearch(search)
+ preparedSearchCache.set(search, searchPrepared)
+ return searchPrepared
+ },
+
+ algorithm: function(searchLowerCodes, prepared, searchLowerCode) {
+ var targetLowerCodes = prepared._targetLowerCodes
+ var searchLen = searchLowerCodes.length
+ var targetLen = targetLowerCodes.length
+ var searchI = 0 // where we at
+ var targetI = 0 // where you at
+ var typoSimpleI = 0
+ var matchesSimpleLen = 0
+
+ // very basic fuzzy match; to remove non-matching targets ASAP!
+ // walk through target. find sequential matches.
+ // if all chars aren't found then exit
+ for(;;) {
+ var isMatch = searchLowerCode === targetLowerCodes[targetI]
+ if(isMatch) {
+ matchesSimple[matchesSimpleLen++] = targetI
+ ++searchI; if(searchI === searchLen) break
+ searchLowerCode = searchLowerCodes[typoSimpleI===0?searchI : (typoSimpleI===searchI?searchI+1 : (typoSimpleI===searchI-1?searchI-1 : searchI))]
+ }
+
+ ++targetI; if(targetI >= targetLen) { // Failed to find searchI
+ // Check for typo or exit
+ // we go as far as possible before trying to transpose
+ // then we transpose backwards until we reach the beginning
+ for(;;) {
+ if(searchI <= 1) return null // not allowed to transpose first char
+ if(typoSimpleI === 0) { // we haven't tried to transpose yet
+ --searchI
+ var searchLowerCodeNew = searchLowerCodes[searchI]
+ if(searchLowerCode === searchLowerCodeNew) continue // doesn't make sense to transpose a repeat char
+ typoSimpleI = searchI
+ } else {
+ if(typoSimpleI === 1) return null // reached the end of the line for transposing
+ --typoSimpleI
+ searchI = typoSimpleI
+ searchLowerCode = searchLowerCodes[searchI + 1]
+ var searchLowerCodeNew = searchLowerCodes[searchI]
+ if(searchLowerCode === searchLowerCodeNew) continue // doesn't make sense to transpose a repeat char
+ }
+ matchesSimpleLen = searchI
+ targetI = matchesSimple[matchesSimpleLen - 1] + 1
+ break
+ }
+ }
+ }
+
+ var searchI = 0
+ var typoStrictI = 0
+ var successStrict = false
+ var matchesStrictLen = 0
+
+ var nextBeginningIndexes = prepared._nextBeginningIndexes
+ if(nextBeginningIndexes === null) nextBeginningIndexes = prepared._nextBeginningIndexes = fuzzysort.prepareNextBeginningIndexes(prepared.target)
+ var firstPossibleI = targetI = matchesSimple[0]===0 ? 0 : nextBeginningIndexes[matchesSimple[0]-1]
+
+ // Our target string successfully matched all characters in sequence!
+ // Let's try a more advanced and strict test to improve the score
+ // only count it as a match if it's consecutive or a beginning character!
+ if(targetI !== targetLen) for(;;) {
+ if(targetI >= targetLen) {
+ // We failed to find a good spot for this search char, go back to the previous search char and force it forward
+ if(searchI <= 0) { // We failed to push chars forward for a better match
+ // transpose, starting from the beginning
+ ++typoStrictI; if(typoStrictI > searchLen-2) break
+ if(searchLowerCodes[typoStrictI] === searchLowerCodes[typoStrictI+1]) continue // doesn't make sense to transpose a repeat char
+ targetI = firstPossibleI
+ continue
+ }
+
+ --searchI
+ var lastMatch = matchesStrict[--matchesStrictLen]
+ targetI = nextBeginningIndexes[lastMatch]
+
+ } else {
+ var isMatch = searchLowerCodes[typoStrictI===0?searchI : (typoStrictI===searchI?searchI+1 : (typoStrictI===searchI-1?searchI-1 : searchI))] === targetLowerCodes[targetI]
+ if(isMatch) {
+ matchesStrict[matchesStrictLen++] = targetI
+ ++searchI; if(searchI === searchLen) { successStrict = true; break }
+ ++targetI
+ } else {
+ targetI = nextBeginningIndexes[targetI]
+ }
+ }
+ }
+
+ { // tally up the score & keep track of matches for highlighting later
+ if(successStrict) { var matchesBest = matchesStrict; var matchesBestLen = matchesStrictLen }
+ else { var matchesBest = matchesSimple; var matchesBestLen = matchesSimpleLen }
+ var score = 0
+ var lastTargetI = -1
+ for(var i = 0; i < searchLen; ++i) { var targetI = matchesBest[i]
+ // score only goes down if they're not consecutive
+ if(lastTargetI !== targetI - 1) score -= targetI
+ lastTargetI = targetI
+ }
+ if(!successStrict) {
+ score *= 1000
+ if(typoSimpleI !== 0) score += -20/*typoPenalty*/
+ } else {
+ if(typoStrictI !== 0) score += -20/*typoPenalty*/
+ }
+ score -= targetLen - searchLen
+ prepared.score = score
+ prepared.indexes = new Array(matchesBestLen); for(var i = matchesBestLen - 1; i >= 0; --i) prepared.indexes[i] = matchesBest[i]
+
+ return prepared
+ }
+ },
+
+ algorithmNoTypo: function(searchLowerCodes, prepared, searchLowerCode) {
+ var targetLowerCodes = prepared._targetLowerCodes
+ var searchLen = searchLowerCodes.length
+ var targetLen = targetLowerCodes.length
+ var searchI = 0 // where we at
+ var targetI = 0 // where you at
+ var matchesSimpleLen = 0
+
+ // very basic fuzzy match; to remove non-matching targets ASAP!
+ // walk through target. find sequential matches.
+ // if all chars aren't found then exit
+ for(;;) {
+ var isMatch = searchLowerCode === targetLowerCodes[targetI]
+ if(isMatch) {
+ matchesSimple[matchesSimpleLen++] = targetI
+ ++searchI; if(searchI === searchLen) break
+ searchLowerCode = searchLowerCodes[searchI]
+ }
+ ++targetI; if(targetI >= targetLen) return null // Failed to find searchI
+ }
+
+ var searchI = 0
+ var successStrict = false
+ var matchesStrictLen = 0
+
+ var nextBeginningIndexes = prepared._nextBeginningIndexes
+ if(nextBeginningIndexes === null) nextBeginningIndexes = prepared._nextBeginningIndexes = fuzzysort.prepareNextBeginningIndexes(prepared.target)
+ var firstPossibleI = targetI = matchesSimple[0]===0 ? 0 : nextBeginningIndexes[matchesSimple[0]-1]
+
+ // Our target string successfully matched all characters in sequence!
+ // Let's try a more advanced and strict test to improve the score
+ // only count it as a match if it's consecutive or a beginning character!
+ if(targetI !== targetLen) for(;;) {
+ if(targetI >= targetLen) {
+ // We failed to find a good spot for this search char, go back to the previous search char and force it forward
+ if(searchI <= 0) break // We failed to push chars forward for a better match
+
+ --searchI
+ var lastMatch = matchesStrict[--matchesStrictLen]
+ targetI = nextBeginningIndexes[lastMatch]
+
+ } else {
+ var isMatch = searchLowerCodes[searchI] === targetLowerCodes[targetI]
+ if(isMatch) {
+ matchesStrict[matchesStrictLen++] = targetI
+ ++searchI; if(searchI === searchLen) { successStrict = true; break }
+ ++targetI
+ } else {
+ targetI = nextBeginningIndexes[targetI]
+ }
+ }
+ }
+
+ { // tally up the score & keep track of matches for highlighting later
+ if(successStrict) { var matchesBest = matchesStrict; var matchesBestLen = matchesStrictLen }
+ else { var matchesBest = matchesSimple; var matchesBestLen = matchesSimpleLen }
+ var score = 0
+ var lastTargetI = -1
+ for(var i = 0; i < searchLen; ++i) { var targetI = matchesBest[i]
+ // score only goes down if they're not consecutive
+ if(lastTargetI !== targetI - 1) score -= targetI
+ lastTargetI = targetI
+ }
+ if(!successStrict) score *= 1000
+ score -= targetLen - searchLen
+ prepared.score = score
+ prepared.indexes = new Array(matchesBestLen); for(var i = matchesBestLen - 1; i >= 0; --i) prepared.indexes[i] = matchesBest[i]
+
+ return prepared
+ }
+ },
+
+ prepareLowerCodes: function(str) {
+ var strLen = str.length
+ var lowerCodes = [] // new Array(strLen) sparse array is too slow
+ var lower = str.toLowerCase()
+ for(var i = 0; i < strLen; ++i) lowerCodes[i] = lower.charCodeAt(i)
+ return lowerCodes
+ },
+ prepareBeginningIndexes: function(target) {
+ var targetLen = target.length
+ var beginningIndexes = []; var beginningIndexesLen = 0
+ var wasUpper = false
+ var wasAlphanum = false
+ for(var i = 0; i < targetLen; ++i) {
+ var targetCode = target.charCodeAt(i)
+ var isUpper = targetCode>=65&&targetCode<=90
+ var isAlphanum = isUpper || targetCode>=97&&targetCode<=122 || targetCode>=48&&targetCode<=57
+ var isBeginning = isUpper && !wasUpper || !wasAlphanum || !isAlphanum
+ wasUpper = isUpper
+ wasAlphanum = isAlphanum
+ if(isBeginning) beginningIndexes[beginningIndexesLen++] = i
+ }
+ return beginningIndexes
+ },
+ prepareNextBeginningIndexes: function(target) {
+ var targetLen = target.length
+ var beginningIndexes = fuzzysort.prepareBeginningIndexes(target)
+ var nextBeginningIndexes = [] // new Array(targetLen) sparse array is too slow
+ var lastIsBeginning = beginningIndexes[0]
+ var lastIsBeginningI = 0
+ for(var i = 0; i < targetLen; ++i) {
+ if(lastIsBeginning > i) {
+ nextBeginningIndexes[i] = lastIsBeginning
+ } else {
+ lastIsBeginning = beginningIndexes[++lastIsBeginningI]
+ nextBeginningIndexes[i] = lastIsBeginning===undefined ? targetLen : lastIsBeginning
+ }
+ }
+ return nextBeginningIndexes
+ },
+
+ cleanup: cleanup,
+ new: fuzzysortNew,
+ }
+ return fuzzysort
+} // fuzzysortNew
+
+// This stuff is outside fuzzysortNew, because it's shared with instances of fuzzysort.new()
+var isNode = typeof require !== 'undefined' && typeof window === 'undefined'
+// var MAX_INT = Number.MAX_SAFE_INTEGER
+// var MIN_INT = Number.MIN_VALUE
+var preparedCache = new Map()
+var preparedSearchCache = new Map()
+var noResults = []; noResults.total = 0
+var matchesSimple = []; var matchesStrict = []
+function cleanup() { preparedCache.clear(); preparedSearchCache.clear(); matchesSimple = []; matchesStrict = [] }
+function defaultScoreFn(a) {
+ var max = -9007199254740991
+ for (var i = a.length - 1; i >= 0; --i) {
+ var result = a[i]; if(result === null) continue
+ var score = result.score
+ if(score > max) max = score
+ }
+ if(max === -9007199254740991) return null
+ return max
+}
+
+// prop = 'key' 2.5ms optimized for this case, seems to be about as fast as direct obj[prop]
+// prop = 'key1.key2' 10ms
+// prop = ['key1', 'key2'] 27ms
+function getValue(obj, prop) {
+ var tmp = obj[prop]; if(tmp !== undefined) return tmp
+ var segs = prop
+ if(!Array.isArray(prop)) segs = prop.split('.')
+ var len = segs.length
+ var i = -1
+ while (obj && (++i < len)) obj = obj[segs[i]]
+ return obj
+}
+
+function isObj(x) { return typeof x === 'object' } // faster as a function
+
+// Hacked version of https://github.com/lemire/FastPriorityQueue.js
+var fastpriorityqueue=function(){var r=[],o=0,e={};function n(){for(var e=0,n=r[e],c=1;c<o;){var f=c+1;e=c,f<o&&r[f].score<r[c].score&&(e=f),r[e-1>>1]=r[e],c=1+(e<<1)}for(var a=e-1>>1;e>0&&n.score<r[a].score;a=(e=a)-1>>1)r[e]=r[a];r[e]=n}return e.add=function(e){var n=o;r[o++]=e;for(var c=n-1>>1;n>0&&e.score<r[c].score;c=(n=c)-1>>1)r[n]=r[c];r[n]=e},e.poll=function(){if(0!==o){var e=r[0];return r[0]=r[--o],n(),e}},e.peek=function(e){if(0!==o)return r[0]},e.replaceTop=function(o){r[0]=o,n()},e};
+var q = fastpriorityqueue() // reuse this, except for async, it needs to make its own
+
+return fuzzysortNew()
+}) // UMD
+
+// TODO: (performance) wasm version!?
+
+// TODO: (performance) layout memory in an optimal way to go fast by avoiding cache misses
+
+// TODO: (performance) preparedCache is a memory leak
+
+// TODO: (like sublime) backslash === forwardslash
+
+// TODO: (performance) i have no idea how well optizmied the allowing typos algorithm is
+
+}).call(this,require("timers").setImmediate)
+},{"timers":18}],9:[function(require,module,exports){
+'use strict';
+
+const instanceOfAny = (object, constructors) => constructors.some(c => object instanceof c);
+
+let idbProxyableTypes;
+let cursorAdvanceMethods;
+// This is a function to prevent it throwing up in node environments.
+function getIdbProxyableTypes() {
+ return idbProxyableTypes ||
+ (idbProxyableTypes = [IDBDatabase, IDBObjectStore, IDBIndex, IDBCursor, IDBTransaction]);
+}
+// This is a function to prevent it throwing up in node environments.
+function getCursorAdvanceMethods() {
+ return cursorAdvanceMethods || (cursorAdvanceMethods = [
+ IDBCursor.prototype.advance,
+ IDBCursor.prototype.continue,
+ IDBCursor.prototype.continuePrimaryKey,
+ ]);
+}
+const cursorRequestMap = new WeakMap();
+const transactionDoneMap = new WeakMap();
+const transactionStoreNamesMap = new WeakMap();
+const transformCache = new WeakMap();
+const reverseTransformCache = new WeakMap();
+function promisifyRequest(request) {
+ const promise = new Promise((resolve, reject) => {
+ const unlisten = () => {
+ request.removeEventListener('success', success);
+ request.removeEventListener('error', error);
+ };
+ const success = () => {
+ resolve(wrap(request.result));
+ unlisten();
+ };
+ const error = () => {
+ reject(request.error);
+ unlisten();
+ };
+ request.addEventListener('success', success);
+ request.addEventListener('error', error);
+ });
+ promise.then((value) => {
+ // Since cursoring reuses the IDBRequest (*sigh*), we cache it for later retrieval
+ // (see wrapFunction).
+ if (value instanceof IDBCursor) {
+ cursorRequestMap.set(value, request);
+ }
+ });
+ // This mapping exists in reverseTransformCache but doesn't doesn't exist in transformCache. This
+ // is because we create many promises from a single IDBRequest.
+ reverseTransformCache.set(promise, request);
+ return promise;
+}
+function cacheDonePromiseForTransaction(tx) {
+ // Early bail if we've already created a done promise for this transaction.
+ if (transactionDoneMap.has(tx))
+ return;
+ const done = new Promise((resolve, reject) => {
+ const unlisten = () => {
+ tx.removeEventListener('complete', complete);
+ tx.removeEventListener('error', error);
+ tx.removeEventListener('abort', error);
+ };
+ const complete = () => {
+ resolve();
+ unlisten();
+ };
+ const error = () => {
+ reject(tx.error);
+ unlisten();
+ };
+ tx.addEventListener('complete', complete);
+ tx.addEventListener('error', error);
+ tx.addEventListener('abort', error);
+ });
+ // Cache it for later retrieval.
+ transactionDoneMap.set(tx, done);
+}
+let idbProxyTraps = {
+ get(target, prop, receiver) {
+ if (target instanceof IDBTransaction) {
+ // Special handling for transaction.done.
+ if (prop === 'done')
+ return transactionDoneMap.get(target);
+ // Polyfill for objectStoreNames because of Edge.
+ if (prop === 'objectStoreNames') {
+ return target.objectStoreNames || transactionStoreNamesMap.get(target);
+ }
+ // Make tx.store return the only store in the transaction, or undefined if there are many.
+ if (prop === 'store') {
+ return receiver.objectStoreNames[1] ?
+ undefined : receiver.objectStore(receiver.objectStoreNames[0]);
+ }
+ }
+ // Else transform whatever we get back.
+ return wrap(target[prop]);
+ },
+ has(target, prop) {
+ if (target instanceof IDBTransaction && (prop === 'done' || prop === 'store'))
+ return true;
+ return prop in target;
+ },
+};
+function addTraps(callback) {
+ idbProxyTraps = callback(idbProxyTraps);
+}
+function wrapFunction(func) {
+ // Due to expected object equality (which is enforced by the caching in `wrap`), we
+ // only create one new func per func.
+ // Edge doesn't support objectStoreNames (booo), so we polyfill it here.
+ if (func === IDBDatabase.prototype.transaction &&
+ !('objectStoreNames' in IDBTransaction.prototype)) {
+ return function (storeNames, ...args) {
+ const tx = func.call(unwrap(this), storeNames, ...args);
+ transactionStoreNamesMap.set(tx, storeNames.sort ? storeNames.sort() : [storeNames]);
+ return wrap(tx);
+ };
+ }
+ // Cursor methods are special, as the behaviour is a little more different to standard IDB. In
+ // IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the
+ // cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense
+ // with real promises, so each advance methods returns a new promise for the cursor object, or
+ // undefined if the end of the cursor has been reached.
+ if (getCursorAdvanceMethods().includes(func)) {
+ return function (...args) {
+ // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
+ // the original object.
+ func.apply(unwrap(this), args);
+ return wrap(cursorRequestMap.get(this));
+ };
+ }
+ return function (...args) {
+ // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
+ // the original object.
+ return wrap(func.apply(unwrap(this), args));
+ };
+}
+function transformCachableValue(value) {
+ if (typeof value === 'function')
+ return wrapFunction(value);
+ // This doesn't return, it just creates a 'done' promise for the transaction,
+ // which is later returned for transaction.done (see idbObjectHandler).
+ if (value instanceof IDBTransaction)
+ cacheDonePromiseForTransaction(value);
+ if (instanceOfAny(value, getIdbProxyableTypes()))
+ return new Proxy(value, idbProxyTraps);
+ // Return the same value back if we're not going to transform it.
+ return value;
+}
+function wrap(value) {
+ // We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because
+ // IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.
+ if (value instanceof IDBRequest)
+ return promisifyRequest(value);
+ // If we've already transformed this value before, reuse the transformed value.
+ // This is faster, but it also provides object equality.
+ if (transformCache.has(value))
+ return transformCache.get(value);
+ const newValue = transformCachableValue(value);
+ // Not all types are transformed.
+ // These may be primitive types, so they can't be WeakMap keys.
+ if (newValue !== value) {
+ transformCache.set(value, newValue);
+ reverseTransformCache.set(newValue, value);
+ }
+ return newValue;
+}
+const unwrap = (value) => reverseTransformCache.get(value);
+
+exports.wrap = wrap;
+exports.addTraps = addTraps;
+exports.instanceOfAny = instanceOfAny;
+exports.reverseTransformCache = reverseTransformCache;
+exports.unwrap = unwrap;
+
+},{}],10:[function(require,module,exports){
+'use strict';
+
+Object.defineProperty(exports, '__esModule', { value: true });
+
+var __chunk_1 = require('./chunk.js');
+
+/**
+ * Open a database.
+ *
+ * @param name Name of the database.
+ * @param version Schema version.
+ * @param callbacks Additional callbacks.
+ */
+function openDB(name, version, { blocked, upgrade, blocking } = {}) {
+ const request = indexedDB.open(name, version);
+ const openPromise = __chunk_1.wrap(request);
+ if (upgrade) {
+ request.addEventListener('upgradeneeded', (event) => {
+ upgrade(__chunk_1.wrap(request.result), event.oldVersion, event.newVersion, __chunk_1.wrap(request.transaction));
+ });
+ }
+ if (blocked)
+ request.addEventListener('blocked', () => blocked());
+ if (blocking)
+ openPromise.then(db => db.addEventListener('versionchange', blocking));
+ return openPromise;
+}
+/**
+ * Delete a database.
+ *
+ * @param name Name of the database.
+ */
+function deleteDB(name, { blocked } = {}) {
+ const request = indexedDB.deleteDatabase(name);
+ if (blocked)
+ request.addEventListener('blocked', () => blocked());
+ return __chunk_1.wrap(request).then(() => undefined);
+}
+
+const readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];
+const writeMethods = ['put', 'add', 'delete', 'clear'];
+const cachedMethods = new Map();
+function getMethod(target, prop) {
+ if (!(target instanceof IDBDatabase &&
+ !(prop in target) &&
+ typeof prop === 'string'))
+ return;
+ if (cachedMethods.get(prop))
+ return cachedMethods.get(prop);
+ const targetFuncName = prop.replace(/FromIndex$/, '');
+ const useIndex = prop !== targetFuncName;
+ const isWrite = writeMethods.includes(targetFuncName);
+ if (
+ // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.
+ !(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) ||
+ !(isWrite || readMethods.includes(targetFuncName)))
+ return;
+ const method = async function (storeName, ...args) {
+ const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');
+ let target = tx.store;
+ if (useIndex)
+ target = target.index(args.shift());
+ const returnVal = target[targetFuncName](...args);
+ if (isWrite)
+ await tx.done;
+ return returnVal;
+ };
+ cachedMethods.set(prop, method);
+ return method;
+}
+__chunk_1.addTraps(oldTraps => ({
+ get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),
+ has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop),
+}));
+
+exports.unwrap = __chunk_1.unwrap;
+exports.wrap = __chunk_1.wrap;
+exports.openDB = openDB;
+exports.deleteDB = deleteDB;
+
+},{"./chunk.js":9}],11:[function(require,module,exports){
+exports.read = function (buffer, offset, isLE, mLen, nBytes) {
+ var e, m
+ var eLen = (nBytes * 8) - mLen - 1
+ var eMax = (1 << eLen) - 1
+ var eBias = eMax >> 1
+ var nBits = -7
+ var i = isLE ? (nBytes - 1) : 0
+ var d = isLE ? -1 : 1
+ var s = buffer[offset + i]
+
+ i += d
+
+ e = s & ((1 << (-nBits)) - 1)
+ s >>= (-nBits)
+ nBits += eLen
+ for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {}
+
+ m = e & ((1 << (-nBits)) - 1)
+ e >>= (-nBits)
+ nBits += mLen
+ for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {}
+
+ if (e === 0) {
+ e = 1 - eBias
+ } else if (e === eMax) {
+ return m ? NaN : ((s ? -1 : 1) * Infinity)
+ } else {
+ m = m + Math.pow(2, mLen)
+ e = e - eBias
+ }
+ return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
+}
+
+exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
+ var e, m, c
+ var eLen = (nBytes * 8) - mLen - 1
+ var eMax = (1 << eLen) - 1
+ var eBias = eMax >> 1
+ var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
+ var i = isLE ? 0 : (nBytes - 1)
+ var d = isLE ? 1 : -1
+ var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
+
+ value = Math.abs(value)
+
+ if (isNaN(value) || value === Infinity) {
+ m = isNaN(value) ? 1 : 0
+ e = eMax
+ } else {
+ e = Math.floor(Math.log(value) / Math.LN2)
+ if (value * (c = Math.pow(2, -e)) < 1) {
+ e--
+ c *= 2
+ }
+ if (e + eBias >= 1) {
+ value += rt / c
+ } else {
+ value += rt * Math.pow(2, 1 - eBias)
+ }
+ if (value * c >= 2) {
+ e++
+ c /= 2
+ }
+
+ if (e + eBias >= eMax) {
+ m = 0
+ e = eMax
+ } else if (e + eBias >= 1) {
+ m = ((value * c) - 1) * Math.pow(2, mLen)
+ e = e + eBias
+ } else {
+ m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
+ e = 0
+ }
+ }
+
+ for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
+
+ e = (e << mLen) | m
+ eLen += mLen
+ for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
+
+ buffer[offset + i - d] |= s * 128
+}
+
+},{}],12:[function(require,module,exports){
+// shim for using process in browser
+var process = module.exports = {};
+
+// cached from whatever global is present so that test runners that stub it
+// don't break things. But we need to wrap it in a try catch in case it is
+// wrapped in strict mode code which doesn't define any globals. It's inside a
+// function because try/catches deoptimize in certain engines.
+
+var cachedSetTimeout;
+var cachedClearTimeout;
+
+function defaultSetTimout() {
+ throw new Error('setTimeout has not been defined');
+}
+function defaultClearTimeout () {
+ throw new Error('clearTimeout has not been defined');
+}
+(function () {
+ try {
+ if (typeof setTimeout === 'function') {
+ cachedSetTimeout = setTimeout;
+ } else {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ } catch (e) {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ try {
+ if (typeof clearTimeout === 'function') {
+ cachedClearTimeout = clearTimeout;
+ } else {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+ } catch (e) {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+} ())
+function runTimeout(fun) {
+ if (cachedSetTimeout === setTimeout) {
+ //normal enviroments in sane situations
+ return setTimeout(fun, 0);
+ }
+ // if setTimeout wasn't available but was latter defined
+ if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
+ cachedSetTimeout = setTimeout;
+ return setTimeout(fun, 0);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedSetTimeout(fun, 0);
+ } catch(e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedSetTimeout.call(null, fun, 0);
+ } catch(e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
+ return cachedSetTimeout.call(this, fun, 0);
+ }
+ }
+
+
+}
+function runClearTimeout(marker) {
+ if (cachedClearTimeout === clearTimeout) {
+ //normal enviroments in sane situations
+ return clearTimeout(marker);
+ }
+ // if clearTimeout wasn't available but was latter defined
+ if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
+ cachedClearTimeout = clearTimeout;
+ return clearTimeout(marker);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedClearTimeout(marker);
+ } catch (e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedClearTimeout.call(null, marker);
+ } catch (e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
+ // Some versions of I.E. have different rules for clearTimeout vs setTimeout
+ return cachedClearTimeout.call(this, marker);
+ }
+ }
+
+
+
+}
+var queue = [];
+var draining = false;
+var currentQueue;
+var queueIndex = -1;
+
+function cleanUpNextTick() {
+ if (!draining || !currentQueue) {
+ return;
+ }
+ draining = false;
+ if (currentQueue.length) {
+ queue = currentQueue.concat(queue);
+ } else {
+ queueIndex = -1;
+ }
+ if (queue.length) {
+ drainQueue();
+ }
+}
+
+function drainQueue() {
+ if (draining) {
+ return;
+ }
+ var timeout = runTimeout(cleanUpNextTick);
+ draining = true;
+
+ var len = queue.length;
+ while(len) {
+ currentQueue = queue;
+ queue = [];
+ while (++queueIndex < len) {
+ if (currentQueue) {
+ currentQueue[queueIndex].run();
+ }
+ }
+ queueIndex = -1;
+ len = queue.length;
+ }
+ currentQueue = null;
+ draining = false;
+ runClearTimeout(timeout);
+}
+
+process.nextTick = function (fun) {
+ var args = new Array(arguments.length - 1);
+ if (arguments.length > 1) {
+ for (var i = 1; i < arguments.length; i++) {
+ args[i - 1] = arguments[i];
+ }
+ }
+ queue.push(new Item(fun, args));
+ if (queue.length === 1 && !draining) {
+ runTimeout(drainQueue);
+ }
+};
+
+// v8 likes predictible objects
+function Item(fun, array) {
+ this.fun = fun;
+ this.array = array;
+}
+Item.prototype.run = function () {
+ this.fun.apply(null, this.array);
+};
+process.title = 'browser';
+process.browser = true;
+process.env = {};
+process.argv = [];
+process.version = ''; // empty string to avoid regexp issues
+process.versions = {};
+
+function noop() {}
+
+process.on = noop;
+process.addListener = noop;
+process.once = noop;
+process.off = noop;
+process.removeListener = noop;
+process.removeAllListeners = noop;
+process.emit = noop;
+process.prependListener = noop;
+process.prependOnceListener = noop;
+
+process.listeners = function (name) { return [] }
+
+process.binding = function (name) {
+ throw new Error('process.binding is not supported');
+};
+
+process.cwd = function () { return '/' };
+process.chdir = function (dir) {
+ throw new Error('process.chdir is not supported');
+};
+process.umask = function() { return 0; };
+
+},{}],13:[function(require,module,exports){
+(function (global){
+/*! https://mths.be/punycode v1.4.1 by @mathias */
+;(function(root) {
+
+ /** Detect free variables */
+ var freeExports = typeof exports == 'object' && exports &&
+ !exports.nodeType && exports;
+ var freeModule = typeof module == 'object' && module &&
+ !module.nodeType && module;
+ var freeGlobal = typeof global == 'object' && global;
+ if (
+ freeGlobal.global === freeGlobal ||
+ freeGlobal.window === freeGlobal ||
+ freeGlobal.self === freeGlobal
+ ) {
+ root = freeGlobal;
+ }
+
+ /**
+ * The `punycode` object.
+ * @name punycode
+ * @type Object
+ */
+ var punycode,
+
+ /** Highest positive signed 32-bit float value */
+ maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
+
+ /** Bootstring parameters */
+ base = 36,
+ tMin = 1,
+ tMax = 26,
+ skew = 38,
+ damp = 700,
+ initialBias = 72,
+ initialN = 128, // 0x80
+ delimiter = '-', // '\x2D'
+
+ /** Regular expressions */
+ regexPunycode = /^xn--/,
+ regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
+ regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
+
+ /** Error messages */
+ errors = {
+ 'overflow': 'Overflow: input needs wider integers to process',
+ 'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
+ 'invalid-input': 'Invalid input'
+ },
+
+ /** Convenience shortcuts */
+ baseMinusTMin = base - tMin,
+ floor = Math.floor,
+ stringFromCharCode = String.fromCharCode,
+
+ /** Temporary variable */
+ key;
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * A generic error utility function.
+ * @private
+ * @param {String} type The error type.
+ * @returns {Error} Throws a `RangeError` with the applicable error message.
+ */
+ function error(type) {
+ throw new RangeError(errors[type]);
+ }
+
+ /**
+ * A generic `Array#map` utility function.
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} callback The function that gets called for every array
+ * item.
+ * @returns {Array} A new array of values returned by the callback function.
+ */
+ function map(array, fn) {
+ var length = array.length;
+ var result = [];
+ while (length--) {
+ result[length] = fn(array[length]);
+ }
+ return result;
+ }
+
+ /**
+ * A simple `Array#map`-like wrapper to work with domain name strings or email
+ * addresses.
+ * @private
+ * @param {String} domain The domain name or email address.
+ * @param {Function} callback The function that gets called for every
+ * character.
+ * @returns {Array} A new string of characters returned by the callback
+ * function.
+ */
+ function mapDomain(string, fn) {
+ var parts = string.split('@');
+ var result = '';
+ if (parts.length > 1) {
+ // In email addresses, only the domain name should be punycoded. Leave
+ // the local part (i.e. everything up to `@`) intact.
+ result = parts[0] + '@';
+ string = parts[1];
+ }
+ // Avoid `split(regex)` for IE8 compatibility. See #17.
+ string = string.replace(regexSeparators, '\x2E');
+ var labels = string.split('.');
+ var encoded = map(labels, fn).join('.');
+ return result + encoded;
+ }
+
+ /**
+ * Creates an array containing the numeric code points of each Unicode
+ * character in the string. While JavaScript uses UCS-2 internally,
+ * this function will convert a pair of surrogate halves (each of which
+ * UCS-2 exposes as separate characters) into a single code point,
+ * matching UTF-16.
+ * @see `punycode.ucs2.encode`
+ * @see <https://mathiasbynens.be/notes/javascript-encoding>
+ * @memberOf punycode.ucs2
+ * @name decode
+ * @param {String} string The Unicode input string (UCS-2).
+ * @returns {Array} The new array of code points.
+ */
+ function ucs2decode(string) {
+ var output = [],
+ counter = 0,
+ length = string.length,
+ value,
+ extra;
+ while (counter < length) {
+ value = string.charCodeAt(counter++);
+ if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
+ // high surrogate, and there is a next character
+ extra = string.charCodeAt(counter++);
+ if ((extra & 0xFC00) == 0xDC00) { // low surrogate
+ output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
+ } else {
+ // unmatched surrogate; only append this code unit, in case the next
+ // code unit is the high surrogate of a surrogate pair
+ output.push(value);
+ counter--;
+ }
+ } else {
+ output.push(value);
+ }
+ }
+ return output;
+ }
+
+ /**
+ * Creates a string based on an array of numeric code points.
+ * @see `punycode.ucs2.decode`
+ * @memberOf punycode.ucs2
+ * @name encode
+ * @param {Array} codePoints The array of numeric code points.
+ * @returns {String} The new Unicode string (UCS-2).
+ */
+ function ucs2encode(array) {
+ return map(array, function(value) {
+ var output = '';
+ if (value > 0xFFFF) {
+ value -= 0x10000;
+ output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
+ value = 0xDC00 | value & 0x3FF;
+ }
+ output += stringFromCharCode(value);
+ return output;
+ }).join('');
+ }
+
+ /**
+ * Converts a basic code point into a digit/integer.
+ * @see `digitToBasic()`
+ * @private
+ * @param {Number} codePoint The basic numeric code point value.
+ * @returns {Number} The numeric value of a basic code point (for use in
+ * representing integers) in the range `0` to `base - 1`, or `base` if
+ * the code point does not represent a value.
+ */
+ function basicToDigit(codePoint) {
+ if (codePoint - 48 < 10) {
+ return codePoint - 22;
+ }
+ if (codePoint - 65 < 26) {
+ return codePoint - 65;
+ }
+ if (codePoint - 97 < 26) {
+ return codePoint - 97;
+ }
+ return base;
+ }
+
+ /**
+ * Converts a digit/integer into a basic code point.
+ * @see `basicToDigit()`
+ * @private
+ * @param {Number} digit The numeric value of a basic code point.
+ * @returns {Number} The basic code point whose value (when used for
+ * representing integers) is `digit`, which needs to be in the range
+ * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
+ * used; else, the lowercase form is used. The behavior is undefined
+ * if `flag` is non-zero and `digit` has no uppercase form.
+ */
+ function digitToBasic(digit, flag) {
+ // 0..25 map to ASCII a..z or A..Z
+ // 26..35 map to ASCII 0..9
+ return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
+ }
+
+ /**
+ * Bias adaptation function as per section 3.4 of RFC 3492.
+ * https://tools.ietf.org/html/rfc3492#section-3.4
+ * @private
+ */
+ function adapt(delta, numPoints, firstTime) {
+ var k = 0;
+ delta = firstTime ? floor(delta / damp) : delta >> 1;
+ delta += floor(delta / numPoints);
+ for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
+ delta = floor(delta / baseMinusTMin);
+ }
+ return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
+ }
+
+ /**
+ * Converts a Punycode string of ASCII-only symbols to a string of Unicode
+ * symbols.
+ * @memberOf punycode
+ * @param {String} input The Punycode string of ASCII-only symbols.
+ * @returns {String} The resulting string of Unicode symbols.
+ */
+ function decode(input) {
+ // Don't use UCS-2
+ var output = [],
+ inputLength = input.length,
+ out,
+ i = 0,
+ n = initialN,
+ bias = initialBias,
+ basic,
+ j,
+ index,
+ oldi,
+ w,
+ k,
+ digit,
+ t,
+ /** Cached calculation results */
+ baseMinusT;
+
+ // Handle the basic code points: let `basic` be the number of input code
+ // points before the last delimiter, or `0` if there is none, then copy
+ // the first basic code points to the output.
+
+ basic = input.lastIndexOf(delimiter);
+ if (basic < 0) {
+ basic = 0;
+ }
+
+ for (j = 0; j < basic; ++j) {
+ // if it's not a basic code point
+ if (input.charCodeAt(j) >= 0x80) {
+ error('not-basic');
+ }
+ output.push(input.charCodeAt(j));
+ }
+
+ // Main decoding loop: start just after the last delimiter if any basic code
+ // points were copied; start at the beginning otherwise.
+
+ for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
+
+ // `index` is the index of the next character to be consumed.
+ // Decode a generalized variable-length integer into `delta`,
+ // which gets added to `i`. The overflow checking is easier
+ // if we increase `i` as we go, then subtract off its starting
+ // value at the end to obtain `delta`.
+ for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
+
+ if (index >= inputLength) {
+ error('invalid-input');
+ }
+
+ digit = basicToDigit(input.charCodeAt(index++));
+
+ if (digit >= base || digit > floor((maxInt - i) / w)) {
+ error('overflow');
+ }
+
+ i += digit * w;
+ t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+
+ if (digit < t) {
+ break;
+ }
+
+ baseMinusT = base - t;
+ if (w > floor(maxInt / baseMinusT)) {
+ error('overflow');
+ }
+
+ w *= baseMinusT;
+
+ }
+
+ out = output.length + 1;
+ bias = adapt(i - oldi, out, oldi == 0);
+
+ // `i` was supposed to wrap around from `out` to `0`,
+ // incrementing `n` each time, so we'll fix that now:
+ if (floor(i / out) > maxInt - n) {
+ error('overflow');
+ }
+
+ n += floor(i / out);
+ i %= out;
+
+ // Insert `n` at position `i` of the output
+ output.splice(i++, 0, n);
+
+ }
+
+ return ucs2encode(output);
+ }
+
+ /**
+ * Converts a string of Unicode symbols (e.g. a domain name label) to a
+ * Punycode string of ASCII-only symbols.
+ * @memberOf punycode
+ * @param {String} input The string of Unicode symbols.
+ * @returns {String} The resulting Punycode string of ASCII-only symbols.
+ */
+ function encode(input) {
+ var n,
+ delta,
+ handledCPCount,
+ basicLength,
+ bias,
+ j,
+ m,
+ q,
+ k,
+ t,
+ currentValue,
+ output = [],
+ /** `inputLength` will hold the number of code points in `input`. */
+ inputLength,
+ /** Cached calculation results */
+ handledCPCountPlusOne,
+ baseMinusT,
+ qMinusT;
+
+ // Convert the input in UCS-2 to Unicode
+ input = ucs2decode(input);
+
+ // Cache the length
+ inputLength = input.length;
+
+ // Initialize the state
+ n = initialN;
+ delta = 0;
+ bias = initialBias;
+
+ // Handle the basic code points
+ for (j = 0; j < inputLength; ++j) {
+ currentValue = input[j];
+ if (currentValue < 0x80) {
+ output.push(stringFromCharCode(currentValue));
+ }
+ }
+
+ handledCPCount = basicLength = output.length;
+
+ // `handledCPCount` is the number of code points that have been handled;
+ // `basicLength` is the number of basic code points.
+
+ // Finish the basic string - if it is not empty - with a delimiter
+ if (basicLength) {
+ output.push(delimiter);
+ }
+
+ // Main encoding loop:
+ while (handledCPCount < inputLength) {
+
+ // All non-basic code points < n have been handled already. Find the next
+ // larger one:
+ for (m = maxInt, j = 0; j < inputLength; ++j) {
+ currentValue = input[j];
+ if (currentValue >= n && currentValue < m) {
+ m = currentValue;
+ }
+ }
+
+ // Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
+ // but guard against overflow
+ handledCPCountPlusOne = handledCPCount + 1;
+ if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
+ error('overflow');
+ }
+
+ delta += (m - n) * handledCPCountPlusOne;
+ n = m;
+
+ for (j = 0; j < inputLength; ++j) {
+ currentValue = input[j];
+
+ if (currentValue < n && ++delta > maxInt) {
+ error('overflow');
+ }
+
+ if (currentValue == n) {
+ // Represent delta as a generalized variable-length integer
+ for (q = delta, k = base; /* no condition */; k += base) {
+ t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+ if (q < t) {
+ break;
+ }
+ qMinusT = q - t;
+ baseMinusT = base - t;
+ output.push(
+ stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
+ );
+ q = floor(qMinusT / baseMinusT);
+ }
+
+ output.push(stringFromCharCode(digitToBasic(q, 0)));
+ bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
+ delta = 0;
+ ++handledCPCount;
+ }
+ }
+
+ ++delta;
+ ++n;
+
+ }
+ return output.join('');
+ }
+
+ /**
+ * Converts a Punycode string representing a domain name or an email address
+ * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
+ * it doesn't matter if you call it on a string that has already been
+ * converted to Unicode.
+ * @memberOf punycode
+ * @param {String} input The Punycoded domain name or email address to
+ * convert to Unicode.
+ * @returns {String} The Unicode representation of the given Punycode
+ * string.
+ */
+ function toUnicode(input) {
+ return mapDomain(input, function(string) {
+ return regexPunycode.test(string)
+ ? decode(string.slice(4).toLowerCase())
+ : string;
+ });
+ }
+
+ /**
+ * Converts a Unicode string representing a domain name or an email address to
+ * Punycode. Only the non-ASCII parts of the domain name will be converted,
+ * i.e. it doesn't matter if you call it with a domain that's already in
+ * ASCII.
+ * @memberOf punycode
+ * @param {String} input The domain name or email address to convert, as a
+ * Unicode string.
+ * @returns {String} The Punycode representation of the given domain name or
+ * email address.
+ */
+ function toASCII(input) {
+ return mapDomain(input, function(string) {
+ return regexNonASCII.test(string)
+ ? 'xn--' + encode(string)
+ : string;
+ });
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /** Define the public API */
+ punycode = {
+ /**
+ * A string representing the current Punycode.js version number.
+ * @memberOf punycode
+ * @type String
+ */
+ 'version': '1.4.1',
+ /**
+ * An object of methods to convert from JavaScript's internal character
+ * representation (UCS-2) to Unicode code points, and back.
+ * @see <https://mathiasbynens.be/notes/javascript-encoding>
+ * @memberOf punycode
+ * @type Object
+ */
+ 'ucs2': {
+ 'decode': ucs2decode,
+ 'encode': ucs2encode
+ },
+ 'decode': decode,
+ 'encode': encode,
+ 'toASCII': toASCII,
+ 'toUnicode': toUnicode
+ };
+
+ /** Expose `punycode` */
+ // Some AMD build optimizers, like r.js, check for specific condition patterns
+ // like the following:
+ if (
+ typeof define == 'function' &&
+ typeof define.amd == 'object' &&
+ define.amd
+ ) {
+ define('punycode', function() {
+ return punycode;
+ });
+ } else if (freeExports && freeModule) {
+ if (module.exports == freeExports) {
+ // in Node.js, io.js, or RingoJS v0.8.0+
+ freeModule.exports = punycode;
+ } else {
+ // in Narwhal or RingoJS v0.7.0-
+ for (key in punycode) {
+ punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
+ }
+ }
+ } else {
+ // in Rhino or a web browser
+ root.punycode = punycode;
+ }
+
+}(this));
+
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{}],14:[function(require,module,exports){
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+'use strict';
+
+// If obj.hasOwnProperty has been overridden, then calling
+// obj.hasOwnProperty(prop) will break.
+// See: https://github.com/joyent/node/issues/1707
+function hasOwnProperty(obj, prop) {
+ return Object.prototype.hasOwnProperty.call(obj, prop);
+}
+
+module.exports = function(qs, sep, eq, options) {
+ sep = sep || '&';
+ eq = eq || '=';
+ var obj = {};
+
+ if (typeof qs !== 'string' || qs.length === 0) {
+ return obj;
+ }
+
+ var regexp = /\+/g;
+ qs = qs.split(sep);
+
+ var maxKeys = 1000;
+ if (options && typeof options.maxKeys === 'number') {
+ maxKeys = options.maxKeys;
+ }
+
+ var len = qs.length;
+ // maxKeys <= 0 means that we should not limit keys count
+ if (maxKeys > 0 && len > maxKeys) {
+ len = maxKeys;
+ }
+
+ for (var i = 0; i < len; ++i) {
+ var x = qs[i].replace(regexp, '%20'),
+ idx = x.indexOf(eq),
+ kstr, vstr, k, v;
+
+ if (idx >= 0) {
+ kstr = x.substr(0, idx);
+ vstr = x.substr(idx + 1);
+ } else {
+ kstr = x;
+ vstr = '';
+ }
+
+ k = decodeURIComponent(kstr);
+ v = decodeURIComponent(vstr);
+
+ if (!hasOwnProperty(obj, k)) {
+ obj[k] = v;
+ } else if (isArray(obj[k])) {
+ obj[k].push(v);
+ } else {
+ obj[k] = [obj[k], v];
+ }
+ }
+
+ return obj;
+};
+
+var isArray = Array.isArray || function (xs) {
+ return Object.prototype.toString.call(xs) === '[object Array]';
+};
+
+},{}],15:[function(require,module,exports){
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+'use strict';
+
+var stringifyPrimitive = function(v) {
+ switch (typeof v) {
+ case 'string':
+ return v;
+
+ case 'boolean':
+ return v ? 'true' : 'false';
+
+ case 'number':
+ return isFinite(v) ? v : '';
+
+ default:
+ return '';
+ }
+};
+
+module.exports = function(obj, sep, eq, name) {
+ sep = sep || '&';
+ eq = eq || '=';
+ if (obj === null) {
+ obj = undefined;
+ }
+
+ if (typeof obj === 'object') {
+ return map(objectKeys(obj), function(k) {
+ var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
+ if (isArray(obj[k])) {
+ return map(obj[k], function(v) {
+ return ks + encodeURIComponent(stringifyPrimitive(v));
+ }).join(sep);
+ } else {
+ return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
+ }
+ }).join(sep);
+
+ }
+
+ if (!name) return '';
+ return encodeURIComponent(stringifyPrimitive(name)) + eq +
+ encodeURIComponent(stringifyPrimitive(obj));
+};
+
+var isArray = Array.isArray || function (xs) {
+ return Object.prototype.toString.call(xs) === '[object Array]';
+};
+
+function map (xs, f) {
+ if (xs.map) return xs.map(f);
+ var res = [];
+ for (var i = 0; i < xs.length; i++) {
+ res.push(f(xs[i], i));
+ }
+ return res;
+}
+
+var objectKeys = Object.keys || function (obj) {
+ var res = [];
+ for (var key in obj) {
+ if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key);
+ }
+ return res;
+};
+
+},{}],16:[function(require,module,exports){
+'use strict';
+
+exports.decode = exports.parse = require('./decode');
+exports.encode = exports.stringify = require('./encode');
+
+},{"./decode":14,"./encode":15}],17:[function(require,module,exports){
+(function (Buffer){
+(function() {
+ var crypt = require('crypt'),
+ utf8 = require('charenc').utf8,
+ bin = require('charenc').bin,
+
+ // The core
+ sha1 = function (message) {
+ // Convert to byte array
+ if (message.constructor == String)
+ message = utf8.stringToBytes(message);
+ else if (typeof Buffer !== 'undefined' && typeof Buffer.isBuffer == 'function' && Buffer.isBuffer(message))
+ message = Array.prototype.slice.call(message, 0);
+ else if (!Array.isArray(message))
+ message = message.toString();
+
+ // otherwise assume byte array
+
+ var m = crypt.bytesToWords(message),
+ l = message.length * 8,
+ w = [],
+ H0 = 1732584193,
+ H1 = -271733879,
+ H2 = -1732584194,
+ H3 = 271733878,
+ H4 = -1009589776;
+
+ // Padding
+ m[l >> 5] |= 0x80 << (24 - l % 32);
+ m[((l + 64 >>> 9) << 4) + 15] = l;
+
+ for (var i = 0; i < m.length; i += 16) {
+ var a = H0,
+ b = H1,
+ c = H2,
+ d = H3,
+ e = H4;
+
+ for (var j = 0; j < 80; j++) {
+
+ if (j < 16)
+ w[j] = m[i + j];
+ else {
+ var n = w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16];
+ w[j] = (n << 1) | (n >>> 31);
+ }
+
+ var t = ((H0 << 5) | (H0 >>> 27)) + H4 + (w[j] >>> 0) + (
+ j < 20 ? (H1 & H2 | ~H1 & H3) + 1518500249 :
+ j < 40 ? (H1 ^ H2 ^ H3) + 1859775393 :
+ j < 60 ? (H1 & H2 | H1 & H3 | H2 & H3) - 1894007588 :
+ (H1 ^ H2 ^ H3) - 899497514);
+
+ H4 = H3;
+ H3 = H2;
+ H2 = (H1 << 30) | (H1 >>> 2);
+ H1 = H0;
+ H0 = t;
+ }
+
+ H0 += a;
+ H1 += b;
+ H2 += c;
+ H3 += d;
+ H4 += e;
+ }
+
+ return [H0, H1, H2, H3, H4];
+ },
+
+ // Public API
+ api = function (message, options) {
+ var digestbytes = crypt.wordsToBytes(sha1(message));
+ return options && options.asBytes ? digestbytes :
+ options && options.asString ? bin.bytesToString(digestbytes) :
+ crypt.bytesToHex(digestbytes);
+ };
+
+ api._blocksize = 16;
+ api._digestsize = 20;
+
+ module.exports = api;
+})();
+
+}).call(this,require("buffer").Buffer)
+},{"buffer":4,"charenc":5,"crypt":7}],18:[function(require,module,exports){
+(function (setImmediate,clearImmediate){
+var nextTick = require('process/browser.js').nextTick;
+var apply = Function.prototype.apply;
+var slice = Array.prototype.slice;
+var immediateIds = {};
+var nextImmediateId = 0;
+
+// DOM APIs, for completeness
+
+exports.setTimeout = function() {
+ return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout);
+};
+exports.setInterval = function() {
+ return new Timeout(apply.call(setInterval, window, arguments), clearInterval);
+};
+exports.clearTimeout =
+exports.clearInterval = function(timeout) { timeout.close(); };
+
+function Timeout(id, clearFn) {
+ this._id = id;
+ this._clearFn = clearFn;
+}
+Timeout.prototype.unref = Timeout.prototype.ref = function() {};
+Timeout.prototype.close = function() {
+ this._clearFn.call(window, this._id);
+};
+
+// Does not start the time, just sets up the members needed.
+exports.enroll = function(item, msecs) {
+ clearTimeout(item._idleTimeoutId);
+ item._idleTimeout = msecs;
+};
+
+exports.unenroll = function(item) {
+ clearTimeout(item._idleTimeoutId);
+ item._idleTimeout = -1;
+};
+
+exports._unrefActive = exports.active = function(item) {
+ clearTimeout(item._idleTimeoutId);
+
+ var msecs = item._idleTimeout;
+ if (msecs >= 0) {
+ item._idleTimeoutId = setTimeout(function onTimeout() {
+ if (item._onTimeout)
+ item._onTimeout();
+ }, msecs);
+ }
+};
+
+// That's not how node.js implements it but the exposed api is the same.
+exports.setImmediate = typeof setImmediate === "function" ? setImmediate : function(fn) {
+ var id = nextImmediateId++;
+ var args = arguments.length < 2 ? false : slice.call(arguments, 1);
+
+ immediateIds[id] = true;
+
+ nextTick(function onNextTick() {
+ if (immediateIds[id]) {
+ // fn.call() is faster so we optimize for the common use-case
+ // @see http://jsperf.com/call-apply-segu
+ if (args) {
+ fn.apply(null, args);
+ } else {
+ fn.call(null);
+ }
+ // Prevent ids from leaking
+ exports.clearImmediate(id);
+ }
+ });
+
+ return id;
+};
+
+exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate : function(id) {
+ delete immediateIds[id];
+};
+}).call(this,require("timers").setImmediate,require("timers").clearImmediate)
+},{"process/browser.js":12,"timers":18}],19:[function(require,module,exports){
+'use strict';
+
+
+// Load rules
+var Trie = require('./lib/suffix-trie.js');
+var allRules = Trie.fromJson(require('./rules.json'));
+
+// Internals
+var extractHostname = require('./lib/clean-host.js');
+var getDomain = require('./lib/domain.js');
+var getPublicSuffix = require('./lib/public-suffix.js');
+var getSubdomain = require('./lib/subdomain.js');
+var isValid = require('./lib/is-valid.js');
+var isIp = require('./lib/is-ip.js');
+var tldExists = require('./lib/tld-exists.js');
+
+
+// Flags representing steps in the `parse` function. They are used to implement
+// a early stop mechanism (simulating some form of laziness) to avoid doing more
+// work than necessary to perform a given action (e.g.: we don't need to extract
+// the domain and subdomain if we are only interested in public suffix).
+var TLD_EXISTS = 1;
+var PUBLIC_SUFFIX = 2;
+var DOMAIN = 3;
+var SUB_DOMAIN = 4;
+var ALL = 5;
+
+
+/**
+ * Creates a new instance of tldjs
+ * @param {Object.<rules,validHosts>} options [description]
+ * @return {tldjs|Object} [description]
+ */
+function factory(options) {
+ var rules = options.rules || allRules || {};
+ var validHosts = options.validHosts || [];
+ var _extractHostname = options.extractHostname || extractHostname;
+
+ /**
+ * Process a given url and extract all information. This is a higher level API
+ * around private functions of `tld.js`. It allows to remove duplication (only
+ * extract hostname from url once for all operations) and implement some early
+ * termination mechanism to not pay the price of what we don't need (this
+ * simulates laziness at a lower cost).
+ *
+ * @param {string} url
+ * @param {number|undefined} _step - where should we stop processing
+ * @return {object}
+ */
+ function parse(url, _step) {
+ var step = _step || ALL;
+ var result = {
+ hostname: _extractHostname(url),
+ isValid: null,
+ isIp: null,
+ tldExists: false,
+ publicSuffix: null,
+ domain: null,
+ subdomain: null,
+ };
+
+ if (result.hostname === null) {
+ result.isIp = false;
+ result.isValid = false;
+ return result;
+ }
+
+ // Check if `hostname` is a valid ip address
+ result.isIp = isIp(result.hostname);
+ if (result.isIp) {
+ result.isValid = true;
+ return result;
+ }
+
+ // Check if `hostname` is valid
+ result.isValid = isValid(result.hostname);
+ if (result.isValid === false) return result;
+
+ // Check if tld exists
+ if (step === ALL || step === TLD_EXISTS) {
+ result.tldExists = tldExists(rules, result.hostname);
+ }
+ if (step === TLD_EXISTS) return result;
+
+ // Extract public suffix
+ result.publicSuffix = getPublicSuffix(rules, result.hostname);
+ if (step === PUBLIC_SUFFIX) return result;
+
+ // Extract domain
+ result.domain = getDomain(validHosts, result.publicSuffix, result.hostname);
+ if (step === DOMAIN) return result;
+
+ // Extract subdomain
+ result.subdomain = getSubdomain(result.hostname, result.domain);
+
+ return result;
+ }
+
+
+ return {
+ extractHostname: _extractHostname,
+ isValid: isValid,
+ parse: parse,
+ tldExists: function (url) {
+ return parse(url, TLD_EXISTS).tldExists;
+ },
+ getPublicSuffix: function (url) {
+ return parse(url, PUBLIC_SUFFIX).publicSuffix;
+ },
+ getDomain: function (url) {
+ return parse(url, DOMAIN).domain;
+ },
+ getSubdomain: function (url) {
+ return parse(url, SUB_DOMAIN).subdomain;
+ },
+ fromUserSettings: factory
+ };
+}
+
+
+module.exports = factory({});
+
+},{"./lib/clean-host.js":20,"./lib/domain.js":21,"./lib/is-ip.js":23,"./lib/is-valid.js":24,"./lib/public-suffix.js":25,"./lib/subdomain.js":26,"./lib/suffix-trie.js":27,"./lib/tld-exists.js":28,"./rules.json":29}],20:[function(require,module,exports){
+
+var URL = require('url');
+var isValid = require('./is-valid.js');
+
+
+/**
+ * Utility to cleanup the base host value. Also removes url fragments.
+ *
+ * Works for:
+ * - hostname
+ * - //hostname
+ * - scheme://hostname
+ * - scheme+scheme://hostname
+ *
+ * @param {string} value
+ * @return {String}
+ */
+
+// scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+var hasPrefixRE = /^(([a-z][a-z0-9+.-]*)?:)?\/\//;
+
+
+/**
+ * @see https://github.com/oncletom/tld.js/issues/95
+ *
+ * @param {string} value
+ */
+function trimTrailingDots(value) {
+ if (value[value.length - 1] === '.') {
+ return value.substr(0, value.length - 1);
+ }
+ return value;
+}
+
+
+/**
+ * Fast check to avoid calling `trim` when not needed.
+ *
+ * @param {string} value
+ */
+function checkTrimmingNeeded(value) {
+ return (
+ value.length > 0 && (
+ value.charCodeAt(0) <= 32 ||
+ value.charCodeAt(value.length - 1) <= 32
+ )
+ );
+}
+
+
+/**
+ * Fast check to avoid calling `toLowerCase` when not needed.
+ *
+ * @param {string} value
+ */
+function checkLowerCaseNeeded(value) {
+ for (var i = 0; i < value.length; i += 1) {
+ var code = value.charCodeAt(i);
+ if (code >= 65 && code <= 90) { // [A-Z]
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+module.exports = function extractHostname(value) {
+ // First check if `value` is already a valid hostname.
+ if (isValid(value)) {
+ return trimTrailingDots(value);
+ }
+
+ var url = value;
+
+ if (typeof url !== 'string') {
+ url = '' + url;
+ }
+
+ var needsTrimming = checkTrimmingNeeded(url);
+ if (needsTrimming) {
+ url = url.trim();
+ }
+
+ var needsLowerCase = checkLowerCaseNeeded(url);
+ if (needsLowerCase) {
+ url = url.toLowerCase();
+ }
+
+ // Try again after `url` has been transformed to lowercase and trimmed.
+ if ((needsLowerCase || needsTrimming) && isValid(url)) {
+ return trimTrailingDots(url);
+ }
+
+ // Proceed with heavier url parsing to extract the hostname.
+ if (!hasPrefixRE.test(url)) {
+ url = '//' + url;
+ }
+
+ var parts = URL.parse(url, null, true);
+
+ if (parts.hostname) {
+ return trimTrailingDots(parts.hostname);
+ }
+
+ return null;
+};
+
+},{"./is-valid.js":24,"url":30}],21:[function(require,module,exports){
+'use strict';
+
+
+/**
+ * Polyfill for `endsWith`
+ *
+ * @param {string} str
+ * @param {string} pattern
+ * @return {boolean}
+ */
+function endsWith(str, pattern) {
+ return (
+ str.lastIndexOf(pattern) === (str.length - pattern.length)
+ );
+}
+
+
+/**
+ * Check if `vhost` is a valid suffix of `hostname` (top-domain)
+ *
+ * It means that `vhost` needs to be a suffix of `hostname` and we then need to
+ * make sure that: either they are equal, or the character preceding `vhost` in
+ * `hostname` is a '.' (it should not be a partial label).
+ *
+ * * hostname = 'not.evil.com' and vhost = 'vil.com' => not ok
+ * * hostname = 'not.evil.com' and vhost = 'evil.com' => ok
+ * * hostname = 'not.evil.com' and vhost = 'not.evil.com' => ok
+ *
+ * @param {string} hostname
+ * @param {string} vhost
+ * @return {boolean}
+ */
+function shareSameDomainSuffix(hostname, vhost) {
+ if (endsWith(hostname, vhost)) {
+ return (
+ hostname.length === vhost.length ||
+ hostname[hostname.length - vhost.length - 1] === '.'
+ );
+ }
+
+ return false;
+}
+
+
+/**
+ * Given a hostname and its public suffix, extract the general domain.
+ *
+ * @param {string} hostname
+ * @param {string} publicSuffix
+ * @return {string}
+ */
+function extractDomainWithSuffix(hostname, publicSuffix) {
+ // Locate the index of the last '.' in the part of the `hostname` preceding
+ // the public suffix.
+ //
+ // examples:
+ // 1. not.evil.co.uk => evil.co.uk
+ // ^ ^
+ // | | start of public suffix
+ // | index of the last dot
+ //
+ // 2. example.co.uk => example.co.uk
+ // ^ ^
+ // | | start of public suffix
+ // |
+ // | (-1) no dot found before the public suffix
+ var publicSuffixIndex = hostname.length - publicSuffix.length - 2;
+ var lastDotBeforeSuffixIndex = hostname.lastIndexOf('.', publicSuffixIndex);
+
+ // No '.' found, then `hostname` is the general domain (no sub-domain)
+ if (lastDotBeforeSuffixIndex === -1) {
+ return hostname;
+ }
+
+ // Extract the part between the last '.'
+ return hostname.substr(lastDotBeforeSuffixIndex + 1);
+}
+
+
+/**
+ * Detects the domain based on rules and upon and a host string
+ *
+ * @api
+ * @param {string} host
+ * @return {String}
+ */
+module.exports = function getDomain(validHosts, suffix, hostname) {
+ // Check if `hostname` ends with a member of `validHosts`.
+ for (var i = 0; i < validHosts.length; i += 1) {
+ var vhost = validHosts[i];
+ if (shareSameDomainSuffix(hostname, vhost)) {
+ return vhost;
+ }
+ }
+
+ // If there is no suffix, there is no hostname
+ if (suffix === null) {
+ return null;
+ }
+
+ // If `hostname` is a valid public suffix, then there is no domain to return.
+ // Since we already know that `getPublicSuffix` returns a suffix of `hostname`
+ // there is no need to perform a string comparison and we only compare the
+ // size.
+ if (suffix.length === hostname.length) {
+ return null;
+ }
+
+ // To extract the general domain, we start by identifying the public suffix
+ // (if any), then consider the domain to be the public suffix with one added
+ // level of depth. (e.g.: if hostname is `not.evil.co.uk` and public suffix:
+ // `co.uk`, then we take one more level: `evil`, giving the final result:
+ // `evil.co.uk`).
+ return extractDomainWithSuffix(hostname, suffix);
+};
+
+},{}],22:[function(require,module,exports){
+"use strict";
+
+/**
+ * Utility to extract the TLD from a hostname string
+ *
+ * @param {string} host
+ * @return {String}
+ */
+module.exports = function extractTldFromHost(hostname) {
+ var lastDotIndex = hostname.lastIndexOf('.');
+ if (lastDotIndex === -1) {
+ return null;
+ }
+
+ return hostname.substr(lastDotIndex + 1);
+};
+
+},{}],23:[function(require,module,exports){
+'use strict';
+
+
+/**
+ * Check if a hostname is an IP. You should be aware that this only works
+ * because `hostname` is already garanteed to be a valid hostname!
+ *
+ * @param {string} hostname
+ * @return {boolean}
+ */
+function isProbablyIpv4(hostname) {
+ var numberOfDots = 0;
+
+ for (var i = 0; i < hostname.length; i += 1) {
+ var code = hostname.charCodeAt(i);
+
+ if (code === 46) { // '.'
+ numberOfDots += 1;
+ } else if (code < 48 || code > 57) {
+ // 48 => '0'
+ // 57 => '9'
+ return false;
+ }
+ }
+
+ return (
+ numberOfDots === 3 &&
+ hostname[0] !== '.' &&
+ hostname[hostname.length - 1] !== '.'
+ );
+}
+
+
+/**
+ * Similar to isProbablyIpv4.
+ *
+ * @param {string} hostname
+ * @return {boolean}
+ */
+function isProbablyIpv6(hostname) {
+ var hasColon = false;
+
+ for (var i = 0; i < hostname.length; i += 1) {
+ var code = hostname.charCodeAt(i);
+
+ if (code === 58) { // ':'
+ hasColon = true;
+ } else if (!(
+ (code >= 48 && code <= 57) || // 0-9
+ (code >= 97 && code <= 102) // a-f
+ )) {
+ return false;
+ }
+ }
+
+ return hasColon;
+}
+
+
+/**
+ * Check if `hostname` is *probably* a valid ip addr (either ipv6 or ipv4).
+ * This *will not* work on any string. We need `hostname` to be a valid
+ * hostname.
+ *
+ * @param {string} hostname
+ * @return {boolean}
+ */
+module.exports = function isIp(hostname) {
+ if (typeof hostname !== 'string') {
+ return false;
+ }
+
+ if (hostname.length === 0) {
+ return false;
+ }
+
+ return (isProbablyIpv6(hostname) || isProbablyIpv4(hostname));
+};
+
+},{}],24:[function(require,module,exports){
+"use strict";
+
+
+/**
+ * Check if the code point is a digit [0-9]
+ *
+ * @param {number} code
+ * @return boolean
+ */
+function isDigit(code) {
+ // 48 == '0'
+ // 57 == '9'
+ return code >= 48 && code <= 57;
+}
+
+
+/**
+ * Check if the code point is a letter [a-zA-Z]
+ *
+ * @param {number} code
+ * @return boolean
+ */
+function isAlpha(code) {
+ // 97 === 'a'
+ // 122 == 'z'
+ return code >= 97 && code <= 122;
+}
+
+
+/**
+ * Check if a hostname string is valid (according to RFC). It's usually a
+ * preliminary check before trying to use getDomain or anything else.
+ *
+ * Beware: it does not check if the TLD exists.
+ *
+ * @api
+ * @param {string} hostname
+ * @return {boolean}
+ */
+module.exports = function isValid(hostname) {
+ if (typeof hostname !== 'string') {
+ return false;
+ }
+
+ if (hostname.length > 255) {
+ return false;
+ }
+
+ if (hostname.length === 0) {
+ return false;
+ }
+
+ // Check first character: [a-zA-Z0-9]
+ var firstCharCode = hostname.charCodeAt(0);
+ if (!(isAlpha(firstCharCode) || isDigit(firstCharCode))) {
+ return false;
+ }
+
+ // Validate hostname according to RFC
+ var lastDotIndex = -1;
+ var lastCharCode;
+ var code;
+ var len = hostname.length;
+
+ for (var i = 0; i < len; i += 1) {
+ code = hostname.charCodeAt(i);
+
+ if (code === 46) { // '.'
+ if (
+ // Check that previous label is < 63 bytes long (64 = 63 + '.')
+ (i - lastDotIndex) > 64 ||
+ // Check that previous character was not already a '.'
+ lastCharCode === 46 ||
+ // Check that the previous label does not end with a '-'
+ lastCharCode === 45
+ ) {
+ return false;
+ }
+
+ lastDotIndex = i;
+ } else if (!(isAlpha(code) || isDigit(code) || code === 45)) {
+ // Check if there is a forbidden character in the label: [^a-zA-Z0-9-]
+ return false;
+ }
+
+ lastCharCode = code;
+ }
+
+ return (
+ // Check that last label is shorter than 63 chars
+ (len - lastDotIndex - 1) <= 63 &&
+ // Check that the last character is an allowed trailing label character.
+ // Since we already checked that the char is a valid hostname character,
+ // we only need to check that it's different from '-'.
+ lastCharCode !== 45
+ );
+};
+
+},{}],25:[function(require,module,exports){
+'use strict';
+
+
+var extractTldFromHost = require('./from-host.js');
+
+
+/**
+ * Returns the public suffix (including exact matches)
+ *
+ * @api
+ * @since 1.5
+ * @param {string} hostname
+ * @return {string}
+ */
+module.exports = function getPublicSuffix(rules, hostname) {
+ // First check if `hostname` is already a valid top-level Domain.
+ if (rules.hasTld(hostname)) {
+ return hostname;
+ }
+
+ var candidate = rules.suffixLookup(hostname);
+ if (candidate === null) {
+ // Prevailing rule is '*' so we consider the top-level domain to be the
+ // public suffix of `hostname` (e.g.: 'example.org' => 'org').
+ return extractTldFromHost(hostname);
+ }
+
+ return candidate;
+};
+
+},{"./from-host.js":22}],26:[function(require,module,exports){
+'use strict';
+
+
+/**
+ * Returns the subdomain of a hostname string
+ *
+ * @api
+ * @param {string} hostname
+ * @param {string} domain - the root domain of the hostname
+ * @return {string|null} a subdomain string if any, blank string if subdomain
+ * is empty, otherwise null.
+ */
+module.exports = function getSubdomain(hostname, domain) {
+ // No domain found? Just abort, abort!
+ if (domain === null) {
+ return null;
+ }
+
+ return hostname.substr(0, hostname.length - domain.length - 1);
+};
+
+},{}],27:[function(require,module,exports){
+"use strict";
+
+var VALID_HOSTNAME_VALUE = 0;
+
+
+/**
+ * Return min(a, b), handling possible `null` values.
+ *
+ * @param {number|null} a
+ * @param {number|null} b
+ * @return {number|null}
+ */
+function minIndex(a, b) {
+ if (a === null) {
+ return b;
+ } else if (b === null) {
+ return a;
+ }
+
+ return a < b ? a : b;
+}
+
+
+/**
+ * Insert a public suffix rule in the `trie`.
+ *
+ * @param {object} rule
+ * @param {object} trie
+ * @return {object} trie (updated)
+ */
+function insertInTrie(rule, trie) {
+ var parts = rule.parts;
+ var node = trie;
+
+ for (var i = 0; i < parts.length; i += 1) {
+ var part = parts[i];
+ var nextNode = node[part];
+ if (nextNode === undefined) {
+ nextNode = Object.create(null);
+ node[part] = nextNode;
+ }
+
+ node = nextNode;
+ }
+
+ node.$ = VALID_HOSTNAME_VALUE;
+
+ return trie;
+}
+
+
+/**
+ * Recursive lookup of `parts` (starting at `index`) in the tree.
+ *
+ * @param {array} parts
+ * @param {object} trie
+ * @param {number} index - when to start in `parts` (initially: length - 1)
+ * @return {number} size of the suffix found (in number of parts matched)
+ */
+function lookupInTrie(parts, trie, index) {
+ var part;
+ var nextNode;
+ var publicSuffixIndex = null;
+
+ // We have a match!
+ if (trie.$ !== undefined) {
+ publicSuffixIndex = index + 1;
+ }
+
+ // No more `parts` to look for
+ if (index === -1) {
+ return publicSuffixIndex;
+ }
+
+ part = parts[index];
+
+ // Check branch corresponding to next part of hostname
+ nextNode = trie[part];
+ if (nextNode !== undefined) {
+ publicSuffixIndex = minIndex(
+ publicSuffixIndex,
+ lookupInTrie(parts, nextNode, index - 1)
+ );
+ }
+
+ // Check wildcard branch
+ nextNode = trie['*'];
+ if (nextNode !== undefined) {
+ publicSuffixIndex = minIndex(
+ publicSuffixIndex,
+ lookupInTrie(parts, nextNode, index - 1)
+ );
+ }
+
+ return publicSuffixIndex;
+}
+
+
+/**
+ * Contains the public suffix ruleset as a Trie for efficient look-up.
+ *
+ * @constructor
+ */
+function SuffixTrie(rules) {
+ this.exceptions = Object.create(null);
+ this.rules = Object.create(null);
+
+ if (rules) {
+ for (var i = 0; i < rules.length; i += 1) {
+ var rule = rules[i];
+ if (rule.exception) {
+ insertInTrie(rule, this.exceptions);
+ } else {
+ insertInTrie(rule, this.rules);
+ }
+ }
+ }
+}
+
+
+/**
+ * Load the trie from JSON (as serialized by JSON.stringify).
+ */
+SuffixTrie.fromJson = function (json) {
+ var trie = new SuffixTrie();
+
+ trie.exceptions = json.exceptions;
+ trie.rules = json.rules;
+
+ return trie;
+};
+
+
+/**
+ * Check if `value` is a valid TLD.
+ */
+SuffixTrie.prototype.hasTld = function (value) {
+ // All TLDs are at the root of the Trie.
+ return this.rules[value] !== undefined;
+};
+
+
+/**
+ * Check if `hostname` has a valid public suffix in `trie`.
+ *
+ * @param {string} hostname
+ * @return {string|null} public suffix
+ */
+SuffixTrie.prototype.suffixLookup = function (hostname) {
+ var parts = hostname.split('.');
+
+ // Look for a match in rules
+ var publicSuffixIndex = lookupInTrie(
+ parts,
+ this.rules,
+ parts.length - 1
+ );
+
+ if (publicSuffixIndex === null) {
+ return null;
+ }
+
+ // Look for exceptions
+ var exceptionIndex = lookupInTrie(
+ parts,
+ this.exceptions,
+ parts.length - 1
+ );
+
+ if (exceptionIndex !== null) {
+ return parts.slice(exceptionIndex + 1).join('.');
+ }
+
+ return parts.slice(publicSuffixIndex).join('.');
+};
+
+
+module.exports = SuffixTrie;
+
+},{}],28:[function(require,module,exports){
+'use strict';
+
+
+var extractTldFromHost = require('./from-host.js');
+
+
+/**
+ * Checks if the TLD exists for a given hostname
+ *
+ * @api
+ * @param {string} rules
+ * @param {string} hostname
+ * @return {boolean}
+ */
+module.exports = function tldExists(rules, hostname) {
+ // Easy case, it's a TLD
+ if (rules.hasTld(hostname)) {
+ return true;
+ }
+
+ // Popping only the TLD of the hostname
+ var hostTld = extractTldFromHost(hostname);
+ if (hostTld === null) {
+ return false;
+ }
+
+ return rules.hasTld(hostTld);
+};
+
+},{"./from-host.js":22}],29:[function(require,module,exports){
+module.exports={"exceptions":{"ck":{"www":{"$":0}},"jp":{"kawasaki":{"city":{"$":0}},"kitakyushu":{"city":{"$":0}},"kobe":{"city":{"$":0}},"nagoya":{"city":{"$":0}},"sapporo":{"city":{"$":0}},"sendai":{"city":{"$":0}},"yokohama":{"city":{"$":0}}}},"rules":{"ac":{"$":0,"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"net":{"$":0},"mil":{"$":0},"org":{"$":0}},"ad":{"$":0,"nom":{"$":0}},"ae":{"$":0,"co":{"$":0},"net":{"$":0},"org":{"$":0},"sch":{"$":0},"ac":{"$":0},"gov":{"$":0},"mil":{"$":0},"blogspot":{"$":0},"nom":{"$":0}},"aero":{"$":0,"accident-investigation":{"$":0},"accident-prevention":{"$":0},"aerobatic":{"$":0},"aeroclub":{"$":0},"aerodrome":{"$":0},"agents":{"$":0},"aircraft":{"$":0},"airline":{"$":0},"airport":{"$":0},"air-surveillance":{"$":0},"airtraffic":{"$":0},"air-traffic-control":{"$":0},"ambulance":{"$":0},"amusement":{"$":0},"association":{"$":0},"author":{"$":0},"ballooning":{"$":0},"broker":{"$":0},"caa":{"$":0},"cargo":{"$":0},"catering":{"$":0},"certification":{"$":0},"championship":{"$":0},"charter":{"$":0},"civilaviation":{"$":0},"club":{"$":0},"conference":{"$":0},"consultant":{"$":0},"consulting":{"$":0},"control":{"$":0},"council":{"$":0},"crew":{"$":0},"design":{"$":0},"dgca":{"$":0},"educator":{"$":0},"emergency":{"$":0},"engine":{"$":0},"engineer":{"$":0},"entertainment":{"$":0},"equipment":{"$":0},"exchange":{"$":0},"express":{"$":0},"federation":{"$":0},"flight":{"$":0},"freight":{"$":0},"fuel":{"$":0},"gliding":{"$":0},"government":{"$":0},"groundhandling":{"$":0},"group":{"$":0},"hanggliding":{"$":0},"homebuilt":{"$":0},"insurance":{"$":0},"journal":{"$":0},"journalist":{"$":0},"leasing":{"$":0},"logistics":{"$":0},"magazine":{"$":0},"maintenance":{"$":0},"media":{"$":0},"microlight":{"$":0},"modelling":{"$":0},"navigation":{"$":0},"parachuting":{"$":0},"paragliding":{"$":0},"passenger-association":{"$":0},"pilot":{"$":0},"press":{"$":0},"production":{"$":0},"recreation":{"$":0},"repbody":{"$":0},"res":{"$":0},"research":{"$":0},"rotorcraft":{"$":0},"safety":{"$":0},"scientist":{"$":0},"services":{"$":0},"show":{"$":0},"skydiving":{"$":0},"software":{"$":0},"student":{"$":0},"trader":{"$":0},"trading":{"$":0},"trainer":{"$":0},"union":{"$":0},"workinggroup":{"$":0},"works":{"$":0}},"af":{"$":0,"gov":{"$":0},"com":{"$":0},"org":{"$":0},"net":{"$":0},"edu":{"$":0}},"ag":{"$":0,"com":{"$":0},"org":{"$":0},"net":{"$":0},"co":{"$":0},"nom":{"$":0}},"ai":{"$":0,"off":{"$":0},"com":{"$":0},"net":{"$":0},"org":{"$":0},"nom":{"$":0}},"al":{"$":0,"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"mil":{"$":0},"net":{"$":0},"org":{"$":0},"blogspot":{"$":0},"nom":{"$":0}},"am":{"$":0,"blogspot":{"$":0}},"ao":{"$":0,"ed":{"$":0},"gv":{"$":0},"og":{"$":0},"co":{"$":0},"pb":{"$":0},"it":{"$":0}},"aq":{"$":0},"ar":{"$":0,"com":{"$":0,"blogspot":{"$":0}},"edu":{"$":0},"gob":{"$":0},"gov":{"$":0},"int":{"$":0},"mil":{"$":0},"musica":{"$":0},"net":{"$":0},"org":{"$":0},"tur":{"$":0}},"arpa":{"$":0,"e164":{"$":0},"in-addr":{"$":0},"ip6":{"$":0},"iris":{"$":0},"uri":{"$":0},"urn":{"$":0}},"as":{"$":0,"gov":{"$":0}},"asia":{"$":0,"cloudns":{"$":0}},"at":{"$":0,"ac":{"$":0},"co":{"$":0,"blogspot":{"$":0}},"gv":{"$":0},"or":{"$":0},"futurecms":{"*":{"$":0}},"futurehosting":{"$":0},"futuremailing":{"$":0},"ortsinfo":{"ex":{"*":{"$":0}},"kunden":{"*":{"$":0}}},"biz":{"$":0},"info":{"$":0},"priv":{"$":0},"12hp":{"$":0},"2ix":{"$":0},"4lima":{"$":0},"lima-city":{"$":0}},"au":{"$":0,"com":{"$":0,"blogspot":{"$":0}},"net":{"$":0},"org":{"$":0},"edu":{"$":0,"act":{"$":0},"nsw":{"$":0},"nt":{"$":0},"qld":{"$":0},"sa":{"$":0},"tas":{"$":0},"vic":{"$":0},"wa":{"$":0}},"gov":{"$":0,"qld":{"$":0},"sa":{"$":0},"tas":{"$":0},"vic":{"$":0},"wa":{"$":0}},"asn":{"$":0},"id":{"$":0},"info":{"$":0},"conf":{"$":0},"oz":{"$":0},"act":{"$":0},"nsw":{"$":0},"nt":{"$":0},"qld":{"$":0},"sa":{"$":0},"tas":{"$":0},"vic":{"$":0},"wa":{"$":0}},"aw":{"$":0,"com":{"$":0}},"ax":{"$":0},"az":{"$":0,"com":{"$":0},"net":{"$":0},"int":{"$":0},"gov":{"$":0},"org":{"$":0},"edu":{"$":0},"info":{"$":0},"pp":{"$":0},"mil":{"$":0},"name":{"$":0},"pro":{"$":0},"biz":{"$":0}},"ba":{"$":0,"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"mil":{"$":0},"net":{"$":0},"org":{"$":0},"blogspot":{"$":0}},"bb":{"$":0,"biz":{"$":0},"co":{"$":0},"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"info":{"$":0},"net":{"$":0},"org":{"$":0},"store":{"$":0},"tv":{"$":0}},"bd":{"*":{"$":0}},"be":{"$":0,"ac":{"$":0},"webhosting":{"$":0},"blogspot":{"$":0},"transurl":{"*":{"$":0}}},"bf":{"$":0,"gov":{"$":0}},"bg":{"0":{"$":0},"1":{"$":0},"2":{"$":0},"3":{"$":0},"4":{"$":0},"5":{"$":0},"6":{"$":0},"7":{"$":0},"8":{"$":0},"9":{"$":0},"$":0,"a":{"$":0},"b":{"$":0},"c":{"$":0},"d":{"$":0},"e":{"$":0},"f":{"$":0},"g":{"$":0},"h":{"$":0},"i":{"$":0},"j":{"$":0},"k":{"$":0},"l":{"$":0},"m":{"$":0},"n":{"$":0},"o":{"$":0},"p":{"$":0},"q":{"$":0},"r":{"$":0},"s":{"$":0},"t":{"$":0},"u":{"$":0},"v":{"$":0},"w":{"$":0},"x":{"$":0},"y":{"$":0},"z":{"$":0},"blogspot":{"$":0},"barsy":{"$":0}},"bh":{"$":0,"com":{"$":0},"edu":{"$":0},"net":{"$":0},"org":{"$":0},"gov":{"$":0}},"bi":{"$":0,"co":{"$":0},"com":{"$":0},"edu":{"$":0},"or":{"$":0},"org":{"$":0}},"biz":{"$":0,"cloudns":{"$":0},"dyndns":{"$":0},"for-better":{"$":0},"for-more":{"$":0},"for-some":{"$":0},"for-the":{"$":0},"selfip":{"$":0},"webhop":{"$":0},"mmafan":{"$":0},"myftp":{"$":0},"no-ip":{"$":0},"dscloud":{"$":0}},"bj":{"$":0,"asso":{"$":0},"barreau":{"$":0},"gouv":{"$":0},"blogspot":{"$":0}},"bm":{"$":0,"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"net":{"$":0},"org":{"$":0}},"bn":{"*":{"$":0}},"bo":{"$":0,"com":{"$":0},"edu":{"$":0},"gob":{"$":0},"int":{"$":0},"org":{"$":0},"net":{"$":0},"mil":{"$":0},"tv":{"$":0},"web":{"$":0},"academia":{"$":0},"agro":{"$":0},"arte":{"$":0},"blog":{"$":0},"bolivia":{"$":0},"ciencia":{"$":0},"cooperativa":{"$":0},"democracia":{"$":0},"deporte":{"$":0},"ecologia":{"$":0},"economia":{"$":0},"empresa":{"$":0},"indigena":{"$":0},"industria":{"$":0},"info":{"$":0},"medicina":{"$":0},"movimiento":{"$":0},"musica":{"$":0},"natural":{"$":0},"nombre":{"$":0},"noticias":{"$":0},"patria":{"$":0},"politica":{"$":0},"profesional":{"$":0},"plurinacional":{"$":0},"pueblo":{"$":0},"revista":{"$":0},"salud":{"$":0},"tecnologia":{"$":0},"tksat":{"$":0},"transporte":{"$":0},"wiki":{"$":0}},"br":{"$":0,"9guacu":{"$":0},"abc":{"$":0},"adm":{"$":0},"adv":{"$":0},"agr":{"$":0},"aju":{"$":0},"am":{"$":0},"anani":{"$":0},"aparecida":{"$":0},"arq":{"$":0},"art":{"$":0},"ato":{"$":0},"b":{"$":0},"belem":{"$":0},"bhz":{"$":0},"bio":{"$":0},"blog":{"$":0},"bmd":{"$":0},"boavista":{"$":0},"bsb":{"$":0},"campinagrande":{"$":0},"campinas":{"$":0},"caxias":{"$":0},"cim":{"$":0},"cng":{"$":0},"cnt":{"$":0},"com":{"$":0,"blogspot":{"$":0}},"contagem":{"$":0},"coop":{"$":0},"cri":{"$":0},"cuiaba":{"$":0},"curitiba":{"$":0},"def":{"$":0},"ecn":{"$":0},"eco":{"$":0},"edu":{"$":0},"emp":{"$":0},"eng":{"$":0},"esp":{"$":0},"etc":{"$":0},"eti":{"$":0},"far":{"$":0},"feira":{"$":0},"flog":{"$":0},"floripa":{"$":0},"fm":{"$":0},"fnd":{"$":0},"fortal":{"$":0},"fot":{"$":0},"foz":{"$":0},"fst":{"$":0},"g12":{"$":0},"ggf":{"$":0},"goiania":{"$":0},"gov":{"$":0,"ac":{"$":0},"al":{"$":0},"am":{"$":0},"ap":{"$":0},"ba":{"$":0},"ce":{"$":0},"df":{"$":0},"es":{"$":0},"go":{"$":0},"ma":{"$":0},"mg":{"$":0},"ms":{"$":0},"mt":{"$":0},"pa":{"$":0},"pb":{"$":0},"pe":{"$":0},"pi":{"$":0},"pr":{"$":0},"rj":{"$":0},"rn":{"$":0},"ro":{"$":0},"rr":{"$":0},"rs":{"$":0},"sc":{"$":0},"se":{"$":0},"sp":{"$":0},"to":{"$":0}},"gru":{"$":0},"imb":{"$":0},"ind":{"$":0},"inf":{"$":0},"jab":{"$":0},"jampa":{"$":0},"jdf":{"$":0},"joinville":{"$":0},"jor":{"$":0},"jus":{"$":0},"leg":{"$":0,"ac":{"$":0},"al":{"$":0},"am":{"$":0},"ap":{"$":0},"ba":{"$":0},"ce":{"$":0},"df":{"$":0},"es":{"$":0},"go":{"$":0},"ma":{"$":0},"mg":{"$":0},"ms":{"$":0},"mt":{"$":0},"pa":{"$":0},"pb":{"$":0},"pe":{"$":0},"pi":{"$":0},"pr":{"$":0},"rj":{"$":0},"rn":{"$":0},"ro":{"$":0},"rr":{"$":0},"rs":{"$":0},"sc":{"$":0},"se":{"$":0},"sp":{"$":0},"to":{"$":0}},"lel":{"$":0},"londrina":{"$":0},"macapa":{"$":0},"maceio":{"$":0},"manaus":{"$":0},"maringa":{"$":0},"mat":{"$":0},"med":{"$":0},"mil":{"$":0},"morena":{"$":0},"mp":{"$":0},"mus":{"$":0},"natal":{"$":0},"net":{"$":0},"niteroi":{"$":0},"nom":{"*":{"$":0}},"not":{"$":0},"ntr":{"$":0},"odo":{"$":0},"org":{"$":0},"osasco":{"$":0},"palmas":{"$":0},"poa":{"$":0},"ppg":{"$":0},"pro":{"$":0},"psc":{"$":0},"psi":{"$":0},"pvh":{"$":0},"qsl":{"$":0},"radio":{"$":0},"rec":{"$":0},"recife":{"$":0},"ribeirao":{"$":0},"rio":{"$":0},"riobranco":{"$":0},"riopreto":{"$":0},"salvador":{"$":0},"sampa":{"$":0},"santamaria":{"$":0},"santoandre":{"$":0},"saobernardo":{"$":0},"saogonca":{"$":0},"sjc":{"$":0},"slg":{"$":0},"slz":{"$":0},"sorocaba":{"$":0},"srv":{"$":0},"taxi":{"$":0},"teo":{"$":0},"the":{"$":0},"tmp":{"$":0},"trd":{"$":0},"tur":{"$":0},"tv":{"$":0},"udi":{"$":0},"vet":{"$":0},"vix":{"$":0},"vlog":{"$":0},"wiki":{"$":0},"zlg":{"$":0}},"bs":{"$":0,"com":{"$":0},"net":{"$":0},"org":{"$":0},"edu":{"$":0},"gov":{"$":0},"we":{"$":0}},"bt":{"$":0,"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"net":{"$":0},"org":{"$":0}},"bv":{"$":0},"bw":{"$":0,"co":{"$":0},"org":{"$":0}},"by":{"$":0,"gov":{"$":0},"mil":{"$":0},"com":{"$":0,"blogspot":{"$":0}},"of":{"$":0},"nym":{"$":0}},"bz":{"$":0,"com":{"$":0},"net":{"$":0},"org":{"$":0},"edu":{"$":0},"gov":{"$":0},"za":{"$":0},"nym":{"$":0}},"ca":{"$":0,"ab":{"$":0},"bc":{"$":0},"mb":{"$":0},"nb":{"$":0},"nf":{"$":0},"nl":{"$":0},"ns":{"$":0},"nt":{"$":0},"nu":{"$":0},"on":{"$":0},"pe":{"$":0},"qc":{"$":0},"sk":{"$":0},"yk":{"$":0},"gc":{"$":0},"1password":{"$":0},"awdev":{"*":{"$":0}},"co":{"$":0},"blogspot":{"$":0},"no-ip":{"$":0}},"cat":{"$":0},"cc":{"$":0,"cloudns":{"$":0},"ftpaccess":{"$":0},"game-server":{"$":0},"myphotos":{"$":0},"scrapping":{"$":0},"twmail":{"$":0},"fantasyleague":{"$":0}},"cd":{"$":0,"gov":{"$":0}},"cf":{"$":0,"blogspot":{"$":0}},"cg":{"$":0},"ch":{"$":0,"square7":{"$":0},"blogspot":{"$":0},"gotdns":{"$":0},"12hp":{"$":0},"2ix":{"$":0},"4lima":{"$":0},"lima-city":{"$":0}},"ci":{"$":0,"org":{"$":0},"or":{"$":0},"com":{"$":0},"co":{"$":0},"edu":{"$":0},"ed":{"$":0},"ac":{"$":0},"net":{"$":0},"go":{"$":0},"asso":{"$":0},"xn--aroport-bya":{"$":0},"int":{"$":0},"presse":{"$":0},"md":{"$":0},"gouv":{"$":0}},"ck":{"*":{"$":0}},"cl":{"$":0,"gov":{"$":0},"gob":{"$":0},"co":{"$":0},"mil":{"$":0},"blogspot":{"$":0},"nom":{"$":0}},"cm":{"$":0,"co":{"$":0},"com":{"$":0},"gov":{"$":0},"net":{"$":0}},"cn":{"$":0,"ac":{"$":0},"com":{"$":0,"amazonaws":{"compute":{"*":{"$":0}},"eb":{"cn-north-1":{"$":0}},"elb":{"*":{"$":0}},"cn-north-1":{"s3":{"$":0}}}},"edu":{"$":0},"gov":{"$":0},"net":{"$":0},"org":{"$":0},"mil":{"$":0},"xn--55qx5d":{"$":0},"xn--io0a7i":{"$":0},"xn--od0alg":{"$":0},"ah":{"$":0},"bj":{"$":0},"cq":{"$":0},"fj":{"$":0},"gd":{"$":0},"gs":{"$":0},"gz":{"$":0},"gx":{"$":0},"ha":{"$":0},"hb":{"$":0},"he":{"$":0},"hi":{"$":0},"hl":{"$":0},"hn":{"$":0},"jl":{"$":0},"js":{"$":0},"jx":{"$":0},"ln":{"$":0},"nm":{"$":0},"nx":{"$":0},"qh":{"$":0},"sc":{"$":0},"sd":{"$":0},"sh":{"$":0},"sn":{"$":0},"sx":{"$":0},"tj":{"$":0},"xj":{"$":0},"xz":{"$":0},"yn":{"$":0},"zj":{"$":0},"hk":{"$":0},"mo":{"$":0},"tw":{"$":0}},"co":{"$":0,"arts":{"$":0},"com":{"$":0,"blogspot":{"$":0}},"edu":{"$":0},"firm":{"$":0},"gov":{"$":0},"info":{"$":0},"int":{"$":0},"mil":{"$":0},"net":{"$":0},"nom":{"$":0},"org":{"$":0},"rec":{"$":0},"web":{"$":0},"nodum":{"$":0}},"com":{"$":0,"1password":{"$":0},"amazonaws":{"compute":{"*":{"$":0}},"compute-1":{"*":{"$":0}},"us-east-1":{"$":0,"dualstack":{"s3":{"$":0}}},"elb":{"*":{"$":0}},"s3":{"$":0},"s3-ap-northeast-1":{"$":0},"s3-ap-northeast-2":{"$":0},"s3-ap-south-1":{"$":0},"s3-ap-southeast-1":{"$":0},"s3-ap-southeast-2":{"$":0},"s3-ca-central-1":{"$":0},"s3-eu-central-1":{"$":0},"s3-eu-west-1":{"$":0},"s3-eu-west-2":{"$":0},"s3-eu-west-3":{"$":0},"s3-external-1":{"$":0},"s3-fips-us-gov-west-1":{"$":0},"s3-sa-east-1":{"$":0},"s3-us-gov-west-1":{"$":0},"s3-us-east-2":{"$":0},"s3-us-west-1":{"$":0},"s3-us-west-2":{"$":0},"ap-northeast-2":{"s3":{"$":0},"dualstack":{"s3":{"$":0}},"s3-website":{"$":0}},"ap-south-1":{"s3":{"$":0},"dualstack":{"s3":{"$":0}},"s3-website":{"$":0}},"ca-central-1":{"s3":{"$":0},"dualstack":{"s3":{"$":0}},"s3-website":{"$":0}},"eu-central-1":{"s3":{"$":0},"dualstack":{"s3":{"$":0}},"s3-website":{"$":0}},"eu-west-2":{"s3":{"$":0},"dualstack":{"s3":{"$":0}},"s3-website":{"$":0}},"eu-west-3":{"s3":{"$":0},"dualstack":{"s3":{"$":0}},"s3-website":{"$":0}},"us-east-2":{"s3":{"$":0},"dualstack":{"s3":{"$":0}},"s3-website":{"$":0}},"ap-northeast-1":{"dualstack":{"s3":{"$":0}}},"ap-southeast-1":{"dualstack":{"s3":{"$":0}}},"ap-southeast-2":{"dualstack":{"s3":{"$":0}}},"eu-west-1":{"dualstack":{"s3":{"$":0}}},"sa-east-1":{"dualstack":{"s3":{"$":0}}},"s3-website-us-east-1":{"$":0},"s3-website-us-west-1":{"$":0},"s3-website-us-west-2":{"$":0},"s3-website-ap-northeast-1":{"$":0},"s3-website-ap-southeast-1":{"$":0},"s3-website-ap-southeast-2":{"$":0},"s3-website-eu-west-1":{"$":0},"s3-website-sa-east-1":{"$":0}},"elasticbeanstalk":{"$":0,"ap-northeast-1":{"$":0},"ap-northeast-2":{"$":0},"ap-south-1":{"$":0},"ap-southeast-1":{"$":0},"ap-southeast-2":{"$":0},"ca-central-1":{"$":0},"eu-central-1":{"$":0},"eu-west-1":{"$":0},"eu-west-2":{"$":0},"eu-west-3":{"$":0},"sa-east-1":{"$":0},"us-east-1":{"$":0},"us-east-2":{"$":0},"us-gov-west-1":{"$":0},"us-west-1":{"$":0},"us-west-2":{"$":0}},"on-aptible":{"$":0},"myasustor":{"$":0},"betainabox":{"$":0},"bplaced":{"$":0},"ar":{"$":0},"br":{"$":0},"cn":{"$":0},"de":{"$":0},"eu":{"$":0},"gb":{"$":0},"hu":{"$":0},"jpn":{"$":0},"kr":{"$":0},"mex":{"$":0},"no":{"$":0},"qc":{"$":0},"ru":{"$":0},"sa":{"$":0},"se":{"$":0},"uk":{"$":0},"us":{"$":0},"uy":{"$":0},"za":{"$":0},"africa":{"$":0},"gr":{"$":0},"co":{"$":0},"xenapponazure":{"$":0},"jdevcloud":{"$":0},"wpdevcloud":{"$":0},"cloudcontrolled":{"$":0},"cloudcontrolapp":{"$":0},"drayddns":{"$":0},"dreamhosters":{"$":0},"mydrobo":{"$":0},"dyndns-at-home":{"$":0},"dyndns-at-work":{"$":0},"dyndns-blog":{"$":0},"dyndns-free":{"$":0},"dyndns-home":{"$":0},"dyndns-ip":{"$":0},"dyndns-mail":{"$":0},"dyndns-office":{"$":0},"dyndns-pics":{"$":0},"dyndns-remote":{"$":0},"dyndns-server":{"$":0},"dyndns-web":{"$":0},"dyndns-wiki":{"$":0},"dyndns-work":{"$":0},"blogdns":{"$":0},"cechire":{"$":0},"dnsalias":{"$":0},"dnsdojo":{"$":0},"doesntexist":{"$":0},"dontexist":{"$":0},"doomdns":{"$":0},"dyn-o-saur":{"$":0},"dynalias":{"$":0},"est-a-la-maison":{"$":0},"est-a-la-masion":{"$":0},"est-le-patron":{"$":0},"est-mon-blogueur":{"$":0},"from-ak":{"$":0},"from-al":{"$":0},"from-ar":{"$":0},"from-ca":{"$":0},"from-ct":{"$":0},"from-dc":{"$":0},"from-de":{"$":0},"from-fl":{"$":0},"from-ga":{"$":0},"from-hi":{"$":0},"from-ia":{"$":0},"from-id":{"$":0},"from-il":{"$":0},"from-in":{"$":0},"from-ks":{"$":0},"from-ky":{"$":0},"from-ma":{"$":0},"from-md":{"$":0},"from-mi":{"$":0},"from-mn":{"$":0},"from-mo":{"$":0},"from-ms":{"$":0},"from-mt":{"$":0},"from-nc":{"$":0},"from-nd":{"$":0},"from-ne":{"$":0},"from-nh":{"$":0},"from-nj":{"$":0},"from-nm":{"$":0},"from-nv":{"$":0},"from-oh":{"$":0},"from-ok":{"$":0},"from-or":{"$":0},"from-pa":{"$":0},"from-pr":{"$":0},"from-ri":{"$":0},"from-sc":{"$":0},"from-sd":{"$":0},"from-tn":{"$":0},"from-tx":{"$":0},"from-ut":{"$":0},"from-va":{"$":0},"from-vt":{"$":0},"from-wa":{"$":0},"from-wi":{"$":0},"from-wv":{"$":0},"from-wy":{"$":0},"getmyip":{"$":0},"gotdns":{"$":0},"hobby-site":{"$":0},"homelinux":{"$":0},"homeunix":{"$":0},"iamallama":{"$":0},"is-a-anarchist":{"$":0},"is-a-blogger":{"$":0},"is-a-bookkeeper":{"$":0},"is-a-bulls-fan":{"$":0},"is-a-caterer":{"$":0},"is-a-chef":{"$":0},"is-a-conservative":{"$":0},"is-a-cpa":{"$":0},"is-a-cubicle-slave":{"$":0},"is-a-democrat":{"$":0},"is-a-designer":{"$":0},"is-a-doctor":{"$":0},"is-a-financialadvisor":{"$":0},"is-a-geek":{"$":0},"is-a-green":{"$":0},"is-a-guru":{"$":0},"is-a-hard-worker":{"$":0},"is-a-hunter":{"$":0},"is-a-landscaper":{"$":0},"is-a-lawyer":{"$":0},"is-a-liberal":{"$":0},"is-a-libertarian":{"$":0},"is-a-llama":{"$":0},"is-a-musician":{"$":0},"is-a-nascarfan":{"$":0},"is-a-nurse":{"$":0},"is-a-painter":{"$":0},"is-a-personaltrainer":{"$":0},"is-a-photographer":{"$":0},"is-a-player":{"$":0},"is-a-republican":{"$":0},"is-a-rockstar":{"$":0},"is-a-socialist":{"$":0},"is-a-student":{"$":0},"is-a-teacher":{"$":0},"is-a-techie":{"$":0},"is-a-therapist":{"$":0},"is-an-accountant":{"$":0},"is-an-actor":{"$":0},"is-an-actress":{"$":0},"is-an-anarchist":{"$":0},"is-an-artist":{"$":0},"is-an-engineer":{"$":0},"is-an-entertainer":{"$":0},"is-certified":{"$":0},"is-gone":{"$":0},"is-into-anime":{"$":0},"is-into-cars":{"$":0},"is-into-cartoons":{"$":0},"is-into-games":{"$":0},"is-leet":{"$":0},"is-not-certified":{"$":0},"is-slick":{"$":0},"is-uberleet":{"$":0},"is-with-theband":{"$":0},"isa-geek":{"$":0},"isa-hockeynut":{"$":0},"issmarterthanyou":{"$":0},"likes-pie":{"$":0},"likescandy":{"$":0},"neat-url":{"$":0},"saves-the-whales":{"$":0},"selfip":{"$":0},"sells-for-less":{"$":0},"sells-for-u":{"$":0},"servebbs":{"$":0},"simple-url":{"$":0},"space-to-rent":{"$":0},"teaches-yoga":{"$":0},"writesthisblog":{"$":0},"ddnsfree":{"$":0},"ddnsgeek":{"$":0},"giize":{"$":0},"gleeze":{"$":0},"kozow":{"$":0},"loseyourip":{"$":0},"ooguy":{"$":0},"theworkpc":{"$":0},"mytuleap":{"$":0},"evennode":{"eu-1":{"$":0},"eu-2":{"$":0},"eu-3":{"$":0},"eu-4":{"$":0},"us-1":{"$":0},"us-2":{"$":0},"us-3":{"$":0},"us-4":{"$":0}},"fbsbx":{"apps":{"$":0}},"firebaseapp":{"$":0},"flynnhub":{"$":0},"freebox-os":{"$":0},"freeboxos":{"$":0},"githubusercontent":{"$":0},"0emm":{"*":{"$":0}},"appspot":{"$":0},"blogspot":{"$":0},"codespot":{"$":0},"googleapis":{"$":0},"googlecode":{"$":0},"pagespeedmobilizer":{"$":0},"publishproxy":{"$":0},"withgoogle":{"$":0},"withyoutube":{"$":0},"herokuapp":{"$":0},"herokussl":{"$":0},"pixolino":{"$":0},"joyent":{"cns":{"*":{"$":0}}},"barsyonline":{"$":0},"meteorapp":{"$":0,"eu":{"$":0}},"bitballoon":{"$":0},"netlify":{"$":0},"4u":{"$":0},"nfshost":{"$":0},"blogsyte":{"$":0},"ciscofreak":{"$":0},"damnserver":{"$":0},"ditchyourip":{"$":0},"dnsiskinky":{"$":0},"dynns":{"$":0},"geekgalaxy":{"$":0},"health-carereform":{"$":0},"homesecuritymac":{"$":0},"homesecuritypc":{"$":0},"myactivedirectory":{"$":0},"mysecuritycamera":{"$":0},"net-freaks":{"$":0},"onthewifi":{"$":0},"point2this":{"$":0},"quicksytes":{"$":0},"securitytactics":{"$":0},"serveexchange":{"$":0},"servehumour":{"$":0},"servep2p":{"$":0},"servesarcasm":{"$":0},"stufftoread":{"$":0},"unusualperson":{"$":0},"workisboring":{"$":0},"3utilities":{"$":0},"ddnsking":{"$":0},"myvnc":{"$":0},"servebeer":{"$":0},"servecounterstrike":{"$":0},"serveftp":{"$":0},"servegame":{"$":0},"servehalflife":{"$":0},"servehttp":{"$":0},"serveirc":{"$":0},"servemp3":{"$":0},"servepics":{"$":0},"servequake":{"$":0},"operaunite":{"$":0},"outsystemscloud":{"$":0},"ownprovider":{"$":0},"pgfog":{"$":0},"pagefrontapp":{"$":0},"gotpantheon":{"$":0},"prgmr":{"xen":{"$":0}},"qa2":{"$":0},"dev-myqnapcloud":{"$":0},"alpha-myqnapcloud":{"$":0},"myqnapcloud":{"$":0},"quipelements":{"*":{"$":0}},"rackmaze":{"$":0},"rhcloud":{"$":0},"logoip":{"$":0},"scrysec":{"$":0},"firewall-gateway":{"$":0},"myshopblocks":{"$":0},"1kapp":{"$":0},"appchizi":{"$":0},"applinzi":{"$":0},"sinaapp":{"$":0},"vipsinaapp":{"$":0},"bounty-full":{"$":0,"alpha":{"$":0},"beta":{"$":0}},"temp-dns":{"$":0},"dsmynas":{"$":0},"familyds":{"$":0},"bloxcms":{"$":0},"townnews-staging":{"$":0},"hk":{"$":0},"remotewd":{"$":0},"yolasite":{"$":0}},"coop":{"$":0},"cr":{"$":0,"ac":{"$":0},"co":{"$":0},"ed":{"$":0},"fi":{"$":0},"go":{"$":0},"or":{"$":0},"sa":{"$":0}},"cu":{"$":0,"com":{"$":0},"edu":{"$":0},"org":{"$":0},"net":{"$":0},"gov":{"$":0},"inf":{"$":0}},"cv":{"$":0,"blogspot":{"$":0}},"cw":{"$":0,"com":{"$":0},"edu":{"$":0},"net":{"$":0},"org":{"$":0}},"cx":{"$":0,"gov":{"$":0},"ath":{"$":0},"info":{"$":0}},"cy":{"$":0,"ac":{"$":0},"biz":{"$":0},"com":{"$":0,"blogspot":{"$":0}},"ekloges":{"$":0},"gov":{"$":0},"ltd":{"$":0},"name":{"$":0},"net":{"$":0},"org":{"$":0},"parliament":{"$":0},"press":{"$":0},"pro":{"$":0},"tm":{"$":0}},"cz":{"$":0,"co":{"$":0},"realm":{"$":0},"e4":{"$":0},"blogspot":{"$":0},"metacentrum":{"cloud":{"$":0},"custom":{"$":0}}},"de":{"$":0,"bplaced":{"$":0},"square7":{"$":0},"com":{"$":0},"cosidns":{"dyn":{"$":0}},"dynamisches-dns":{"$":0},"dnsupdater":{"$":0},"internet-dns":{"$":0},"l-o-g-i-n":{"$":0},"dnshome":{"$":0},"fuettertdasnetz":{"$":0},"isteingeek":{"$":0},"istmein":{"$":0},"lebtimnetz":{"$":0},"leitungsen":{"$":0},"traeumtgerade":{"$":0},"ddnss":{"$":0,"dyn":{"$":0},"dyndns":{"$":0}},"dyndns1":{"$":0},"dyn-ip24":{"$":0},"home-webserver":{"$":0,"dyn":{"$":0}},"myhome-server":{"$":0},"goip":{"$":0},"blogspot":{"$":0},"keymachine":{"$":0},"git-repos":{"$":0},"lcube-server":{"$":0},"svn-repos":{"$":0},"barsy":{"$":0},"logoip":{"$":0},"firewall-gateway":{"$":0},"my-gateway":{"$":0},"my-router":{"$":0},"spdns":{"$":0},"taifun-dns":{"$":0},"12hp":{"$":0},"2ix":{"$":0},"4lima":{"$":0},"lima-city":{"$":0},"dd-dns":{"$":0},"dray-dns":{"$":0},"draydns":{"$":0},"dyn-vpn":{"$":0},"dynvpn":{"$":0},"mein-vigor":{"$":0},"my-vigor":{"$":0},"my-wan":{"$":0},"syno-ds":{"$":0},"synology-diskstation":{"$":0},"synology-ds":{"$":0}},"dj":{"$":0},"dk":{"$":0,"biz":{"$":0},"co":{"$":0},"firm":{"$":0},"reg":{"$":0},"store":{"$":0},"blogspot":{"$":0}},"dm":{"$":0,"com":{"$":0},"net":{"$":0},"org":{"$":0},"edu":{"$":0},"gov":{"$":0}},"do":{"$":0,"art":{"$":0},"com":{"$":0},"edu":{"$":0},"gob":{"$":0},"gov":{"$":0},"mil":{"$":0},"net":{"$":0},"org":{"$":0},"sld":{"$":0},"web":{"$":0}},"dz":{"$":0,"com":{"$":0},"org":{"$":0},"net":{"$":0},"gov":{"$":0},"edu":{"$":0},"asso":{"$":0},"pol":{"$":0},"art":{"$":0}},"ec":{"$":0,"com":{"$":0},"info":{"$":0},"net":{"$":0},"fin":{"$":0},"k12":{"$":0},"med":{"$":0},"pro":{"$":0},"org":{"$":0},"edu":{"$":0},"gov":{"$":0},"gob":{"$":0},"mil":{"$":0}},"edu":{"$":0},"ee":{"$":0,"edu":{"$":0},"gov":{"$":0},"riik":{"$":0},"lib":{"$":0},"med":{"$":0},"com":{"$":0,"blogspot":{"$":0}},"pri":{"$":0},"aip":{"$":0},"org":{"$":0},"fie":{"$":0}},"eg":{"$":0,"com":{"$":0,"blogspot":{"$":0}},"edu":{"$":0},"eun":{"$":0},"gov":{"$":0},"mil":{"$":0},"name":{"$":0},"net":{"$":0},"org":{"$":0},"sci":{"$":0}},"er":{"*":{"$":0}},"es":{"$":0,"com":{"$":0,"blogspot":{"$":0}},"nom":{"$":0},"org":{"$":0},"gob":{"$":0},"edu":{"$":0}},"et":{"$":0,"com":{"$":0},"gov":{"$":0},"org":{"$":0},"edu":{"$":0},"biz":{"$":0},"name":{"$":0},"info":{"$":0},"net":{"$":0}},"eu":{"$":0,"1password":{"$":0},"mycd":{"$":0},"cloudns":{"$":0},"barsy":{"$":0},"wellbeingzone":{"$":0},"spdns":{"$":0},"transurl":{"*":{"$":0}},"diskstation":{"$":0}},"fi":{"$":0,"aland":{"$":0},"dy":{"$":0},"blogspot":{"$":0},"iki":{"$":0}},"fj":{"*":{"$":0}},"fk":{"*":{"$":0}},"fm":{"$":0},"fo":{"$":0},"fr":{"$":0,"com":{"$":0},"asso":{"$":0},"nom":{"$":0},"prd":{"$":0},"presse":{"$":0},"tm":{"$":0},"aeroport":{"$":0},"assedic":{"$":0},"avocat":{"$":0},"avoues":{"$":0},"cci":{"$":0},"chambagri":{"$":0},"chirurgiens-dentistes":{"$":0},"experts-comptables":{"$":0},"geometre-expert":{"$":0},"gouv":{"$":0},"greta":{"$":0},"huissier-justice":{"$":0},"medecin":{"$":0},"notaires":{"$":0},"pharmacien":{"$":0},"port":{"$":0},"veterinaire":{"$":0},"fbx-os":{"$":0},"fbxos":{"$":0},"freebox-os":{"$":0},"freeboxos":{"$":0},"blogspot":{"$":0},"on-web":{"$":0},"chirurgiens-dentistes-en-france":{"$":0}},"ga":{"$":0},"gb":{"$":0},"gd":{"$":0,"nom":{"$":0}},"ge":{"$":0,"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"org":{"$":0},"mil":{"$":0},"net":{"$":0},"pvt":{"$":0}},"gf":{"$":0},"gg":{"$":0,"co":{"$":0},"net":{"$":0},"org":{"$":0},"cya":{"$":0}},"gh":{"$":0,"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"org":{"$":0},"mil":{"$":0}},"gi":{"$":0,"com":{"$":0},"ltd":{"$":0},"gov":{"$":0},"mod":{"$":0},"edu":{"$":0},"org":{"$":0}},"gl":{"$":0,"co":{"$":0},"com":{"$":0},"edu":{"$":0},"net":{"$":0},"org":{"$":0},"nom":{"$":0}},"gm":{"$":0},"gn":{"$":0,"ac":{"$":0},"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"org":{"$":0},"net":{"$":0}},"gov":{"$":0},"gp":{"$":0,"com":{"$":0},"net":{"$":0},"mobi":{"$":0},"edu":{"$":0},"org":{"$":0},"asso":{"$":0}},"gq":{"$":0},"gr":{"$":0,"com":{"$":0},"edu":{"$":0},"net":{"$":0},"org":{"$":0},"gov":{"$":0},"blogspot":{"$":0},"nym":{"$":0}},"gs":{"$":0},"gt":{"$":0,"com":{"$":0},"edu":{"$":0},"gob":{"$":0},"ind":{"$":0},"mil":{"$":0},"net":{"$":0},"org":{"$":0},"nom":{"$":0}},"gu":{"*":{"$":0}},"gw":{"$":0},"gy":{"$":0,"co":{"$":0},"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"net":{"$":0},"org":{"$":0}},"hk":{"$":0,"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"idv":{"$":0},"net":{"$":0},"org":{"$":0},"xn--55qx5d":{"$":0},"xn--wcvs22d":{"$":0},"xn--lcvr32d":{"$":0},"xn--mxtq1m":{"$":0},"xn--gmqw5a":{"$":0},"xn--ciqpn":{"$":0},"xn--gmq050i":{"$":0},"xn--zf0avx":{"$":0},"xn--io0a7i":{"$":0},"xn--mk0axi":{"$":0},"xn--od0alg":{"$":0},"xn--od0aq3b":{"$":0},"xn--tn0ag":{"$":0},"xn--uc0atv":{"$":0},"xn--uc0ay4a":{"$":0},"blogspot":{"$":0},"ltd":{"$":0},"inc":{"$":0}},"hm":{"$":0},"hn":{"$":0,"com":{"$":0},"edu":{"$":0},"org":{"$":0},"net":{"$":0},"mil":{"$":0},"gob":{"$":0},"nom":{"$":0}},"hr":{"$":0,"iz":{"$":0},"from":{"$":0},"name":{"$":0},"com":{"$":0},"blogspot":{"$":0}},"ht":{"$":0,"com":{"$":0},"shop":{"$":0},"firm":{"$":0},"info":{"$":0},"adult":{"$":0},"net":{"$":0},"pro":{"$":0},"org":{"$":0},"med":{"$":0},"art":{"$":0},"coop":{"$":0},"pol":{"$":0},"asso":{"$":0},"edu":{"$":0},"rel":{"$":0},"gouv":{"$":0},"perso":{"$":0}},"hu":{"2000":{"$":0},"$":0,"co":{"$":0},"info":{"$":0},"org":{"$":0},"priv":{"$":0},"sport":{"$":0},"tm":{"$":0},"agrar":{"$":0},"bolt":{"$":0},"casino":{"$":0},"city":{"$":0},"erotica":{"$":0},"erotika":{"$":0},"film":{"$":0},"forum":{"$":0},"games":{"$":0},"hotel":{"$":0},"ingatlan":{"$":0},"jogasz":{"$":0},"konyvelo":{"$":0},"lakas":{"$":0},"media":{"$":0},"news":{"$":0},"reklam":{"$":0},"sex":{"$":0},"shop":{"$":0},"suli":{"$":0},"szex":{"$":0},"tozsde":{"$":0},"utazas":{"$":0},"video":{"$":0},"blogspot":{"$":0}},"id":{"$":0,"ac":{"$":0},"biz":{"$":0},"co":{"$":0,"blogspot":{"$":0}},"desa":{"$":0},"go":{"$":0},"mil":{"$":0},"my":{"$":0},"net":{"$":0},"or":{"$":0},"sch":{"$":0},"web":{"$":0}},"ie":{"$":0,"gov":{"$":0},"blogspot":{"$":0}},"il":{"$":0,"ac":{"$":0},"co":{"$":0,"blogspot":{"$":0}},"gov":{"$":0},"idf":{"$":0},"k12":{"$":0},"muni":{"$":0},"net":{"$":0},"org":{"$":0}},"im":{"$":0,"ac":{"$":0},"co":{"$":0,"ltd":{"$":0},"plc":{"$":0}},"com":{"$":0},"net":{"$":0},"org":{"$":0},"tt":{"$":0},"tv":{"$":0},"ro":{"$":0},"nom":{"$":0}},"in":{"$":0,"co":{"$":0},"firm":{"$":0},"net":{"$":0},"org":{"$":0},"gen":{"$":0},"ind":{"$":0},"nic":{"$":0},"ac":{"$":0},"edu":{"$":0},"res":{"$":0},"gov":{"$":0},"mil":{"$":0},"cloudns":{"$":0},"blogspot":{"$":0},"barsy":{"$":0}},"info":{"$":0,"cloudns":{"$":0},"dynamic-dns":{"$":0},"dyndns":{"$":0},"barrel-of-knowledge":{"$":0},"barrell-of-knowledge":{"$":0},"for-our":{"$":0},"groks-the":{"$":0},"groks-this":{"$":0},"here-for-more":{"$":0},"knowsitall":{"$":0},"selfip":{"$":0},"webhop":{"$":0},"nsupdate":{"$":0},"dvrcam":{"$":0},"ilovecollege":{"$":0},"no-ip":{"$":0},"v-info":{"$":0}},"int":{"$":0,"eu":{"$":0}},"io":{"$":0,"com":{"$":0},"backplaneapp":{"$":0},"boxfuse":{"$":0},"browsersafetymark":{"$":0},"dedyn":{"$":0},"drud":{"$":0},"definima":{"$":0},"enonic":{"$":0,"customer":{"$":0}},"github":{"$":0},"gitlab":{"$":0},"hasura-app":{"$":0},"ngrok":{"$":0},"nodeart":{"stage":{"$":0}},"nodum":{"$":0},"nid":{"$":0},"pantheonsite":{"$":0},"protonet":{"$":0},"vaporcloud":{"$":0},"resindevice":{"$":0},"resinstaging":{"devices":{"$":0}},"hzc":{"$":0},"sandcats":{"$":0},"s5y":{"*":{"$":0}},"shiftedit":{"$":0},"lair":{"apps":{"$":0}},"stolos":{"*":{"$":0}},"spacekit":{"$":0},"thingdust":{"dev":{"cust":{"$":0}},"disrec":{"cust":{"$":0}},"prod":{"cust":{"$":0}},"testing":{"cust":{"$":0}}},"wedeploy":{"$":0}},"iq":{"$":0,"gov":{"$":0},"edu":{"$":0},"mil":{"$":0},"com":{"$":0},"org":{"$":0},"net":{"$":0}},"ir":{"$":0,"ac":{"$":0},"co":{"$":0},"gov":{"$":0},"id":{"$":0},"net":{"$":0},"org":{"$":0},"sch":{"$":0},"xn--mgba3a4f16a":{"$":0},"xn--mgba3a4fra":{"$":0}},"is":{"$":0,"net":{"$":0},"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"org":{"$":0},"int":{"$":0},"cupcake":{"$":0},"blogspot":{"$":0}},"it":{"$":0,"gov":{"$":0},"edu":{"$":0},"abr":{"$":0},"abruzzo":{"$":0},"aosta-valley":{"$":0},"aostavalley":{"$":0},"bas":{"$":0},"basilicata":{"$":0},"cal":{"$":0},"calabria":{"$":0},"cam":{"$":0},"campania":{"$":0},"emilia-romagna":{"$":0},"emiliaromagna":{"$":0},"emr":{"$":0},"friuli-v-giulia":{"$":0},"friuli-ve-giulia":{"$":0},"friuli-vegiulia":{"$":0},"friuli-venezia-giulia":{"$":0},"friuli-veneziagiulia":{"$":0},"friuli-vgiulia":{"$":0},"friuliv-giulia":{"$":0},"friulive-giulia":{"$":0},"friulivegiulia":{"$":0},"friulivenezia-giulia":{"$":0},"friuliveneziagiulia":{"$":0},"friulivgiulia":{"$":0},"fvg":{"$":0},"laz":{"$":0},"lazio":{"$":0},"lig":{"$":0},"liguria":{"$":0},"lom":{"$":0},"lombardia":{"$":0},"lombardy":{"$":0},"lucania":{"$":0},"mar":{"$":0},"marche":{"$":0},"mol":{"$":0},"molise":{"$":0},"piedmont":{"$":0},"piemonte":{"$":0},"pmn":{"$":0},"pug":{"$":0},"puglia":{"$":0},"sar":{"$":0},"sardegna":{"$":0},"sardinia":{"$":0},"sic":{"$":0},"sicilia":{"$":0},"sicily":{"$":0},"taa":{"$":0},"tos":{"$":0},"toscana":{"$":0},"trentino-a-adige":{"$":0},"trentino-aadige":{"$":0},"trentino-alto-adige":{"$":0},"trentino-altoadige":{"$":0},"trentino-s-tirol":{"$":0},"trentino-stirol":{"$":0},"trentino-sud-tirol":{"$":0},"trentino-sudtirol":{"$":0},"trentino-sued-tirol":{"$":0},"trentino-suedtirol":{"$":0},"trentinoa-adige":{"$":0},"trentinoaadige":{"$":0},"trentinoalto-adige":{"$":0},"trentinoaltoadige":{"$":0},"trentinos-tirol":{"$":0},"trentinostirol":{"$":0},"trentinosud-tirol":{"$":0},"trentinosudtirol":{"$":0},"trentinosued-tirol":{"$":0},"trentinosuedtirol":{"$":0},"tuscany":{"$":0},"umb":{"$":0},"umbria":{"$":0},"val-d-aosta":{"$":0},"val-daosta":{"$":0},"vald-aosta":{"$":0},"valdaosta":{"$":0},"valle-aosta":{"$":0},"valle-d-aosta":{"$":0},"valle-daosta":{"$":0},"valleaosta":{"$":0},"valled-aosta":{"$":0},"valledaosta":{"$":0},"vallee-aoste":{"$":0},"valleeaoste":{"$":0},"vao":{"$":0},"vda":{"$":0},"ven":{"$":0},"veneto":{"$":0},"ag":{"$":0},"agrigento":{"$":0},"al":{"$":0},"alessandria":{"$":0},"alto-adige":{"$":0},"altoadige":{"$":0},"an":{"$":0},"ancona":{"$":0},"andria-barletta-trani":{"$":0},"andria-trani-barletta":{"$":0},"andriabarlettatrani":{"$":0},"andriatranibarletta":{"$":0},"ao":{"$":0},"aosta":{"$":0},"aoste":{"$":0},"ap":{"$":0},"aq":{"$":0},"aquila":{"$":0},"ar":{"$":0},"arezzo":{"$":0},"ascoli-piceno":{"$":0},"ascolipiceno":{"$":0},"asti":{"$":0},"at":{"$":0},"av":{"$":0},"avellino":{"$":0},"ba":{"$":0},"balsan":{"$":0},"bari":{"$":0},"barletta-trani-andria":{"$":0},"barlettatraniandria":{"$":0},"belluno":{"$":0},"benevento":{"$":0},"bergamo":{"$":0},"bg":{"$":0},"bi":{"$":0},"biella":{"$":0},"bl":{"$":0},"bn":{"$":0},"bo":{"$":0},"bologna":{"$":0},"bolzano":{"$":0},"bozen":{"$":0},"br":{"$":0},"brescia":{"$":0},"brindisi":{"$":0},"bs":{"$":0},"bt":{"$":0},"bz":{"$":0},"ca":{"$":0},"cagliari":{"$":0},"caltanissetta":{"$":0},"campidano-medio":{"$":0},"campidanomedio":{"$":0},"campobasso":{"$":0},"carbonia-iglesias":{"$":0},"carboniaiglesias":{"$":0},"carrara-massa":{"$":0},"carraramassa":{"$":0},"caserta":{"$":0},"catania":{"$":0},"catanzaro":{"$":0},"cb":{"$":0},"ce":{"$":0},"cesena-forli":{"$":0},"cesenaforli":{"$":0},"ch":{"$":0},"chieti":{"$":0},"ci":{"$":0},"cl":{"$":0},"cn":{"$":0},"co":{"$":0},"como":{"$":0},"cosenza":{"$":0},"cr":{"$":0},"cremona":{"$":0},"crotone":{"$":0},"cs":{"$":0},"ct":{"$":0},"cuneo":{"$":0},"cz":{"$":0},"dell-ogliastra":{"$":0},"dellogliastra":{"$":0},"en":{"$":0},"enna":{"$":0},"fc":{"$":0},"fe":{"$":0},"fermo":{"$":0},"ferrara":{"$":0},"fg":{"$":0},"fi":{"$":0},"firenze":{"$":0},"florence":{"$":0},"fm":{"$":0},"foggia":{"$":0},"forli-cesena":{"$":0},"forlicesena":{"$":0},"fr":{"$":0},"frosinone":{"$":0},"ge":{"$":0},"genoa":{"$":0},"genova":{"$":0},"go":{"$":0},"gorizia":{"$":0},"gr":{"$":0},"grosseto":{"$":0},"iglesias-carbonia":{"$":0},"iglesiascarbonia":{"$":0},"im":{"$":0},"imperia":{"$":0},"is":{"$":0},"isernia":{"$":0},"kr":{"$":0},"la-spezia":{"$":0},"laquila":{"$":0},"laspezia":{"$":0},"latina":{"$":0},"lc":{"$":0},"le":{"$":0},"lecce":{"$":0},"lecco":{"$":0},"li":{"$":0},"livorno":{"$":0},"lo":{"$":0},"lodi":{"$":0},"lt":{"$":0},"lu":{"$":0},"lucca":{"$":0},"macerata":{"$":0},"mantova":{"$":0},"massa-carrara":{"$":0},"massacarrara":{"$":0},"matera":{"$":0},"mb":{"$":0},"mc":{"$":0},"me":{"$":0},"medio-campidano":{"$":0},"mediocampidano":{"$":0},"messina":{"$":0},"mi":{"$":0},"milan":{"$":0},"milano":{"$":0},"mn":{"$":0},"mo":{"$":0},"modena":{"$":0},"monza-brianza":{"$":0},"monza-e-della-brianza":{"$":0},"monza":{"$":0},"monzabrianza":{"$":0},"monzaebrianza":{"$":0},"monzaedellabrianza":{"$":0},"ms":{"$":0},"mt":{"$":0},"na":{"$":0},"naples":{"$":0},"napoli":{"$":0},"no":{"$":0},"novara":{"$":0},"nu":{"$":0},"nuoro":{"$":0},"og":{"$":0},"ogliastra":{"$":0},"olbia-tempio":{"$":0},"olbiatempio":{"$":0},"or":{"$":0},"oristano":{"$":0},"ot":{"$":0},"pa":{"$":0},"padova":{"$":0},"padua":{"$":0},"palermo":{"$":0},"parma":{"$":0},"pavia":{"$":0},"pc":{"$":0},"pd":{"$":0},"pe":{"$":0},"perugia":{"$":0},"pesaro-urbino":{"$":0},"pesarourbino":{"$":0},"pescara":{"$":0},"pg":{"$":0},"pi":{"$":0},"piacenza":{"$":0},"pisa":{"$":0},"pistoia":{"$":0},"pn":{"$":0},"po":{"$":0},"pordenone":{"$":0},"potenza":{"$":0},"pr":{"$":0},"prato":{"$":0},"pt":{"$":0},"pu":{"$":0},"pv":{"$":0},"pz":{"$":0},"ra":{"$":0},"ragusa":{"$":0},"ravenna":{"$":0},"rc":{"$":0},"re":{"$":0},"reggio-calabria":{"$":0},"reggio-emilia":{"$":0},"reggiocalabria":{"$":0},"reggioemilia":{"$":0},"rg":{"$":0},"ri":{"$":0},"rieti":{"$":0},"rimini":{"$":0},"rm":{"$":0},"rn":{"$":0},"ro":{"$":0},"roma":{"$":0},"rome":{"$":0},"rovigo":{"$":0},"sa":{"$":0},"salerno":{"$":0},"sassari":{"$":0},"savona":{"$":0},"si":{"$":0},"siena":{"$":0},"siracusa":{"$":0},"so":{"$":0},"sondrio":{"$":0},"sp":{"$":0},"sr":{"$":0},"ss":{"$":0},"suedtirol":{"$":0},"sv":{"$":0},"ta":{"$":0},"taranto":{"$":0},"te":{"$":0},"tempio-olbia":{"$":0},"tempioolbia":{"$":0},"teramo":{"$":0},"terni":{"$":0},"tn":{"$":0},"to":{"$":0},"torino":{"$":0},"tp":{"$":0},"tr":{"$":0},"trani-andria-barletta":{"$":0},"trani-barletta-andria":{"$":0},"traniandriabarletta":{"$":0},"tranibarlettaandria":{"$":0},"trapani":{"$":0},"trentino":{"$":0},"trento":{"$":0},"treviso":{"$":0},"trieste":{"$":0},"ts":{"$":0},"turin":{"$":0},"tv":{"$":0},"ud":{"$":0},"udine":{"$":0},"urbino-pesaro":{"$":0},"urbinopesaro":{"$":0},"va":{"$":0},"varese":{"$":0},"vb":{"$":0},"vc":{"$":0},"ve":{"$":0},"venezia":{"$":0},"venice":{"$":0},"verbania":{"$":0},"vercelli":{"$":0},"verona":{"$":0},"vi":{"$":0},"vibo-valentia":{"$":0},"vibovalentia":{"$":0},"vicenza":{"$":0},"viterbo":{"$":0},"vr":{"$":0},"vs":{"$":0},"vt":{"$":0},"vv":{"$":0},"blogspot":{"$":0}},"je":{"$":0,"co":{"$":0},"net":{"$":0},"org":{"$":0}},"jm":{"*":{"$":0}},"jo":{"$":0,"com":{"$":0},"org":{"$":0},"net":{"$":0},"edu":{"$":0},"sch":{"$":0},"gov":{"$":0},"mil":{"$":0},"name":{"$":0}},"jobs":{"$":0},"jp":{"$":0,"ac":{"$":0},"ad":{"$":0},"co":{"$":0},"ed":{"$":0},"go":{"$":0},"gr":{"$":0},"lg":{"$":0},"ne":{"$":0},"or":{"$":0},"aichi":{"$":0,"aisai":{"$":0},"ama":{"$":0},"anjo":{"$":0},"asuke":{"$":0},"chiryu":{"$":0},"chita":{"$":0},"fuso":{"$":0},"gamagori":{"$":0},"handa":{"$":0},"hazu":{"$":0},"hekinan":{"$":0},"higashiura":{"$":0},"ichinomiya":{"$":0},"inazawa":{"$":0},"inuyama":{"$":0},"isshiki":{"$":0},"iwakura":{"$":0},"kanie":{"$":0},"kariya":{"$":0},"kasugai":{"$":0},"kira":{"$":0},"kiyosu":{"$":0},"komaki":{"$":0},"konan":{"$":0},"kota":{"$":0},"mihama":{"$":0},"miyoshi":{"$":0},"nishio":{"$":0},"nisshin":{"$":0},"obu":{"$":0},"oguchi":{"$":0},"oharu":{"$":0},"okazaki":{"$":0},"owariasahi":{"$":0},"seto":{"$":0},"shikatsu":{"$":0},"shinshiro":{"$":0},"shitara":{"$":0},"tahara":{"$":0},"takahama":{"$":0},"tobishima":{"$":0},"toei":{"$":0},"togo":{"$":0},"tokai":{"$":0},"tokoname":{"$":0},"toyoake":{"$":0},"toyohashi":{"$":0},"toyokawa":{"$":0},"toyone":{"$":0},"toyota":{"$":0},"tsushima":{"$":0},"yatomi":{"$":0}},"akita":{"$":0,"akita":{"$":0},"daisen":{"$":0},"fujisato":{"$":0},"gojome":{"$":0},"hachirogata":{"$":0},"happou":{"$":0},"higashinaruse":{"$":0},"honjo":{"$":0},"honjyo":{"$":0},"ikawa":{"$":0},"kamikoani":{"$":0},"kamioka":{"$":0},"katagami":{"$":0},"kazuno":{"$":0},"kitaakita":{"$":0},"kosaka":{"$":0},"kyowa":{"$":0},"misato":{"$":0},"mitane":{"$":0},"moriyoshi":{"$":0},"nikaho":{"$":0},"noshiro":{"$":0},"odate":{"$":0},"oga":{"$":0},"ogata":{"$":0},"semboku":{"$":0},"yokote":{"$":0},"yurihonjo":{"$":0}},"aomori":{"$":0,"aomori":{"$":0},"gonohe":{"$":0},"hachinohe":{"$":0},"hashikami":{"$":0},"hiranai":{"$":0},"hirosaki":{"$":0},"itayanagi":{"$":0},"kuroishi":{"$":0},"misawa":{"$":0},"mutsu":{"$":0},"nakadomari":{"$":0},"noheji":{"$":0},"oirase":{"$":0},"owani":{"$":0},"rokunohe":{"$":0},"sannohe":{"$":0},"shichinohe":{"$":0},"shingo":{"$":0},"takko":{"$":0},"towada":{"$":0},"tsugaru":{"$":0},"tsuruta":{"$":0}},"chiba":{"$":0,"abiko":{"$":0},"asahi":{"$":0},"chonan":{"$":0},"chosei":{"$":0},"choshi":{"$":0},"chuo":{"$":0},"funabashi":{"$":0},"futtsu":{"$":0},"hanamigawa":{"$":0},"ichihara":{"$":0},"ichikawa":{"$":0},"ichinomiya":{"$":0},"inzai":{"$":0},"isumi":{"$":0},"kamagaya":{"$":0},"kamogawa":{"$":0},"kashiwa":{"$":0},"katori":{"$":0},"katsuura":{"$":0},"kimitsu":{"$":0},"kisarazu":{"$":0},"kozaki":{"$":0},"kujukuri":{"$":0},"kyonan":{"$":0},"matsudo":{"$":0},"midori":{"$":0},"mihama":{"$":0},"minamiboso":{"$":0},"mobara":{"$":0},"mutsuzawa":{"$":0},"nagara":{"$":0},"nagareyama":{"$":0},"narashino":{"$":0},"narita":{"$":0},"noda":{"$":0},"oamishirasato":{"$":0},"omigawa":{"$":0},"onjuku":{"$":0},"otaki":{"$":0},"sakae":{"$":0},"sakura":{"$":0},"shimofusa":{"$":0},"shirako":{"$":0},"shiroi":{"$":0},"shisui":{"$":0},"sodegaura":{"$":0},"sosa":{"$":0},"tako":{"$":0},"tateyama":{"$":0},"togane":{"$":0},"tohnosho":{"$":0},"tomisato":{"$":0},"urayasu":{"$":0},"yachimata":{"$":0},"yachiyo":{"$":0},"yokaichiba":{"$":0},"yokoshibahikari":{"$":0},"yotsukaido":{"$":0}},"ehime":{"$":0,"ainan":{"$":0},"honai":{"$":0},"ikata":{"$":0},"imabari":{"$":0},"iyo":{"$":0},"kamijima":{"$":0},"kihoku":{"$":0},"kumakogen":{"$":0},"masaki":{"$":0},"matsuno":{"$":0},"matsuyama":{"$":0},"namikata":{"$":0},"niihama":{"$":0},"ozu":{"$":0},"saijo":{"$":0},"seiyo":{"$":0},"shikokuchuo":{"$":0},"tobe":{"$":0},"toon":{"$":0},"uchiko":{"$":0},"uwajima":{"$":0},"yawatahama":{"$":0}},"fukui":{"$":0,"echizen":{"$":0},"eiheiji":{"$":0},"fukui":{"$":0},"ikeda":{"$":0},"katsuyama":{"$":0},"mihama":{"$":0},"minamiechizen":{"$":0},"obama":{"$":0},"ohi":{"$":0},"ono":{"$":0},"sabae":{"$":0},"sakai":{"$":0},"takahama":{"$":0},"tsuruga":{"$":0},"wakasa":{"$":0}},"fukuoka":{"$":0,"ashiya":{"$":0},"buzen":{"$":0},"chikugo":{"$":0},"chikuho":{"$":0},"chikujo":{"$":0},"chikushino":{"$":0},"chikuzen":{"$":0},"chuo":{"$":0},"dazaifu":{"$":0},"fukuchi":{"$":0},"hakata":{"$":0},"higashi":{"$":0},"hirokawa":{"$":0},"hisayama":{"$":0},"iizuka":{"$":0},"inatsuki":{"$":0},"kaho":{"$":0},"kasuga":{"$":0},"kasuya":{"$":0},"kawara":{"$":0},"keisen":{"$":0},"koga":{"$":0},"kurate":{"$":0},"kurogi":{"$":0},"kurume":{"$":0},"minami":{"$":0},"miyako":{"$":0},"miyama":{"$":0},"miyawaka":{"$":0},"mizumaki":{"$":0},"munakata":{"$":0},"nakagawa":{"$":0},"nakama":{"$":0},"nishi":{"$":0},"nogata":{"$":0},"ogori":{"$":0},"okagaki":{"$":0},"okawa":{"$":0},"oki":{"$":0},"omuta":{"$":0},"onga":{"$":0},"onojo":{"$":0},"oto":{"$":0},"saigawa":{"$":0},"sasaguri":{"$":0},"shingu":{"$":0},"shinyoshitomi":{"$":0},"shonai":{"$":0},"soeda":{"$":0},"sue":{"$":0},"tachiarai":{"$":0},"tagawa":{"$":0},"takata":{"$":0},"toho":{"$":0},"toyotsu":{"$":0},"tsuiki":{"$":0},"ukiha":{"$":0},"umi":{"$":0},"usui":{"$":0},"yamada":{"$":0},"yame":{"$":0},"yanagawa":{"$":0},"yukuhashi":{"$":0}},"fukushima":{"$":0,"aizubange":{"$":0},"aizumisato":{"$":0},"aizuwakamatsu":{"$":0},"asakawa":{"$":0},"bandai":{"$":0},"date":{"$":0},"fukushima":{"$":0},"furudono":{"$":0},"futaba":{"$":0},"hanawa":{"$":0},"higashi":{"$":0},"hirata":{"$":0},"hirono":{"$":0},"iitate":{"$":0},"inawashiro":{"$":0},"ishikawa":{"$":0},"iwaki":{"$":0},"izumizaki":{"$":0},"kagamiishi":{"$":0},"kaneyama":{"$":0},"kawamata":{"$":0},"kitakata":{"$":0},"kitashiobara":{"$":0},"koori":{"$":0},"koriyama":{"$":0},"kunimi":{"$":0},"miharu":{"$":0},"mishima":{"$":0},"namie":{"$":0},"nango":{"$":0},"nishiaizu":{"$":0},"nishigo":{"$":0},"okuma":{"$":0},"omotego":{"$":0},"ono":{"$":0},"otama":{"$":0},"samegawa":{"$":0},"shimogo":{"$":0},"shirakawa":{"$":0},"showa":{"$":0},"soma":{"$":0},"sukagawa":{"$":0},"taishin":{"$":0},"tamakawa":{"$":0},"tanagura":{"$":0},"tenei":{"$":0},"yabuki":{"$":0},"yamato":{"$":0},"yamatsuri":{"$":0},"yanaizu":{"$":0},"yugawa":{"$":0}},"gifu":{"$":0,"anpachi":{"$":0},"ena":{"$":0},"gifu":{"$":0},"ginan":{"$":0},"godo":{"$":0},"gujo":{"$":0},"hashima":{"$":0},"hichiso":{"$":0},"hida":{"$":0},"higashishirakawa":{"$":0},"ibigawa":{"$":0},"ikeda":{"$":0},"kakamigahara":{"$":0},"kani":{"$":0},"kasahara":{"$":0},"kasamatsu":{"$":0},"kawaue":{"$":0},"kitagata":{"$":0},"mino":{"$":0},"minokamo":{"$":0},"mitake":{"$":0},"mizunami":{"$":0},"motosu":{"$":0},"nakatsugawa":{"$":0},"ogaki":{"$":0},"sakahogi":{"$":0},"seki":{"$":0},"sekigahara":{"$":0},"shirakawa":{"$":0},"tajimi":{"$":0},"takayama":{"$":0},"tarui":{"$":0},"toki":{"$":0},"tomika":{"$":0},"wanouchi":{"$":0},"yamagata":{"$":0},"yaotsu":{"$":0},"yoro":{"$":0}},"gunma":{"$":0,"annaka":{"$":0},"chiyoda":{"$":0},"fujioka":{"$":0},"higashiagatsuma":{"$":0},"isesaki":{"$":0},"itakura":{"$":0},"kanna":{"$":0},"kanra":{"$":0},"katashina":{"$":0},"kawaba":{"$":0},"kiryu":{"$":0},"kusatsu":{"$":0},"maebashi":{"$":0},"meiwa":{"$":0},"midori":{"$":0},"minakami":{"$":0},"naganohara":{"$":0},"nakanojo":{"$":0},"nanmoku":{"$":0},"numata":{"$":0},"oizumi":{"$":0},"ora":{"$":0},"ota":{"$":0},"shibukawa":{"$":0},"shimonita":{"$":0},"shinto":{"$":0},"showa":{"$":0},"takasaki":{"$":0},"takayama":{"$":0},"tamamura":{"$":0},"tatebayashi":{"$":0},"tomioka":{"$":0},"tsukiyono":{"$":0},"tsumagoi":{"$":0},"ueno":{"$":0},"yoshioka":{"$":0}},"hiroshima":{"$":0,"asaminami":{"$":0},"daiwa":{"$":0},"etajima":{"$":0},"fuchu":{"$":0},"fukuyama":{"$":0},"hatsukaichi":{"$":0},"higashihiroshima":{"$":0},"hongo":{"$":0},"jinsekikogen":{"$":0},"kaita":{"$":0},"kui":{"$":0},"kumano":{"$":0},"kure":{"$":0},"mihara":{"$":0},"miyoshi":{"$":0},"naka":{"$":0},"onomichi":{"$":0},"osakikamijima":{"$":0},"otake":{"$":0},"saka":{"$":0},"sera":{"$":0},"seranishi":{"$":0},"shinichi":{"$":0},"shobara":{"$":0},"takehara":{"$":0}},"hokkaido":{"$":0,"abashiri":{"$":0},"abira":{"$":0},"aibetsu":{"$":0},"akabira":{"$":0},"akkeshi":{"$":0},"asahikawa":{"$":0},"ashibetsu":{"$":0},"ashoro":{"$":0},"assabu":{"$":0},"atsuma":{"$":0},"bibai":{"$":0},"biei":{"$":0},"bifuka":{"$":0},"bihoro":{"$":0},"biratori":{"$":0},"chippubetsu":{"$":0},"chitose":{"$":0},"date":{"$":0},"ebetsu":{"$":0},"embetsu":{"$":0},"eniwa":{"$":0},"erimo":{"$":0},"esan":{"$":0},"esashi":{"$":0},"fukagawa":{"$":0},"fukushima":{"$":0},"furano":{"$":0},"furubira":{"$":0},"haboro":{"$":0},"hakodate":{"$":0},"hamatonbetsu":{"$":0},"hidaka":{"$":0},"higashikagura":{"$":0},"higashikawa":{"$":0},"hiroo":{"$":0},"hokuryu":{"$":0},"hokuto":{"$":0},"honbetsu":{"$":0},"horokanai":{"$":0},"horonobe":{"$":0},"ikeda":{"$":0},"imakane":{"$":0},"ishikari":{"$":0},"iwamizawa":{"$":0},"iwanai":{"$":0},"kamifurano":{"$":0},"kamikawa":{"$":0},"kamishihoro":{"$":0},"kamisunagawa":{"$":0},"kamoenai":{"$":0},"kayabe":{"$":0},"kembuchi":{"$":0},"kikonai":{"$":0},"kimobetsu":{"$":0},"kitahiroshima":{"$":0},"kitami":{"$":0},"kiyosato":{"$":0},"koshimizu":{"$":0},"kunneppu":{"$":0},"kuriyama":{"$":0},"kuromatsunai":{"$":0},"kushiro":{"$":0},"kutchan":{"$":0},"kyowa":{"$":0},"mashike":{"$":0},"matsumae":{"$":0},"mikasa":{"$":0},"minamifurano":{"$":0},"mombetsu":{"$":0},"moseushi":{"$":0},"mukawa":{"$":0},"muroran":{"$":0},"naie":{"$":0},"nakagawa":{"$":0},"nakasatsunai":{"$":0},"nakatombetsu":{"$":0},"nanae":{"$":0},"nanporo":{"$":0},"nayoro":{"$":0},"nemuro":{"$":0},"niikappu":{"$":0},"niki":{"$":0},"nishiokoppe":{"$":0},"noboribetsu":{"$":0},"numata":{"$":0},"obihiro":{"$":0},"obira":{"$":0},"oketo":{"$":0},"okoppe":{"$":0},"otaru":{"$":0},"otobe":{"$":0},"otofuke":{"$":0},"otoineppu":{"$":0},"oumu":{"$":0},"ozora":{"$":0},"pippu":{"$":0},"rankoshi":{"$":0},"rebun":{"$":0},"rikubetsu":{"$":0},"rishiri":{"$":0},"rishirifuji":{"$":0},"saroma":{"$":0},"sarufutsu":{"$":0},"shakotan":{"$":0},"shari":{"$":0},"shibecha":{"$":0},"shibetsu":{"$":0},"shikabe":{"$":0},"shikaoi":{"$":0},"shimamaki":{"$":0},"shimizu":{"$":0},"shimokawa":{"$":0},"shinshinotsu":{"$":0},"shintoku":{"$":0},"shiranuka":{"$":0},"shiraoi":{"$":0},"shiriuchi":{"$":0},"sobetsu":{"$":0},"sunagawa":{"$":0},"taiki":{"$":0},"takasu":{"$":0},"takikawa":{"$":0},"takinoue":{"$":0},"teshikaga":{"$":0},"tobetsu":{"$":0},"tohma":{"$":0},"tomakomai":{"$":0},"tomari":{"$":0},"toya":{"$":0},"toyako":{"$":0},"toyotomi":{"$":0},"toyoura":{"$":0},"tsubetsu":{"$":0},"tsukigata":{"$":0},"urakawa":{"$":0},"urausu":{"$":0},"uryu":{"$":0},"utashinai":{"$":0},"wakkanai":{"$":0},"wassamu":{"$":0},"yakumo":{"$":0},"yoichi":{"$":0}},"hyogo":{"$":0,"aioi":{"$":0},"akashi":{"$":0},"ako":{"$":0},"amagasaki":{"$":0},"aogaki":{"$":0},"asago":{"$":0},"ashiya":{"$":0},"awaji":{"$":0},"fukusaki":{"$":0},"goshiki":{"$":0},"harima":{"$":0},"himeji":{"$":0},"ichikawa":{"$":0},"inagawa":{"$":0},"itami":{"$":0},"kakogawa":{"$":0},"kamigori":{"$":0},"kamikawa":{"$":0},"kasai":{"$":0},"kasuga":{"$":0},"kawanishi":{"$":0},"miki":{"$":0},"minamiawaji":{"$":0},"nishinomiya":{"$":0},"nishiwaki":{"$":0},"ono":{"$":0},"sanda":{"$":0},"sannan":{"$":0},"sasayama":{"$":0},"sayo":{"$":0},"shingu":{"$":0},"shinonsen":{"$":0},"shiso":{"$":0},"sumoto":{"$":0},"taishi":{"$":0},"taka":{"$":0},"takarazuka":{"$":0},"takasago":{"$":0},"takino":{"$":0},"tamba":{"$":0},"tatsuno":{"$":0},"toyooka":{"$":0},"yabu":{"$":0},"yashiro":{"$":0},"yoka":{"$":0},"yokawa":{"$":0}},"ibaraki":{"$":0,"ami":{"$":0},"asahi":{"$":0},"bando":{"$":0},"chikusei":{"$":0},"daigo":{"$":0},"fujishiro":{"$":0},"hitachi":{"$":0},"hitachinaka":{"$":0},"hitachiomiya":{"$":0},"hitachiota":{"$":0},"ibaraki":{"$":0},"ina":{"$":0},"inashiki":{"$":0},"itako":{"$":0},"iwama":{"$":0},"joso":{"$":0},"kamisu":{"$":0},"kasama":{"$":0},"kashima":{"$":0},"kasumigaura":{"$":0},"koga":{"$":0},"miho":{"$":0},"mito":{"$":0},"moriya":{"$":0},"naka":{"$":0},"namegata":{"$":0},"oarai":{"$":0},"ogawa":{"$":0},"omitama":{"$":0},"ryugasaki":{"$":0},"sakai":{"$":0},"sakuragawa":{"$":0},"shimodate":{"$":0},"shimotsuma":{"$":0},"shirosato":{"$":0},"sowa":{"$":0},"suifu":{"$":0},"takahagi":{"$":0},"tamatsukuri":{"$":0},"tokai":{"$":0},"tomobe":{"$":0},"tone":{"$":0},"toride":{"$":0},"tsuchiura":{"$":0},"tsukuba":{"$":0},"uchihara":{"$":0},"ushiku":{"$":0},"yachiyo":{"$":0},"yamagata":{"$":0},"yawara":{"$":0},"yuki":{"$":0}},"ishikawa":{"$":0,"anamizu":{"$":0},"hakui":{"$":0},"hakusan":{"$":0},"kaga":{"$":0},"kahoku":{"$":0},"kanazawa":{"$":0},"kawakita":{"$":0},"komatsu":{"$":0},"nakanoto":{"$":0},"nanao":{"$":0},"nomi":{"$":0},"nonoichi":{"$":0},"noto":{"$":0},"shika":{"$":0},"suzu":{"$":0},"tsubata":{"$":0},"tsurugi":{"$":0},"uchinada":{"$":0},"wajima":{"$":0}},"iwate":{"$":0,"fudai":{"$":0},"fujisawa":{"$":0},"hanamaki":{"$":0},"hiraizumi":{"$":0},"hirono":{"$":0},"ichinohe":{"$":0},"ichinoseki":{"$":0},"iwaizumi":{"$":0},"iwate":{"$":0},"joboji":{"$":0},"kamaishi":{"$":0},"kanegasaki":{"$":0},"karumai":{"$":0},"kawai":{"$":0},"kitakami":{"$":0},"kuji":{"$":0},"kunohe":{"$":0},"kuzumaki":{"$":0},"miyako":{"$":0},"mizusawa":{"$":0},"morioka":{"$":0},"ninohe":{"$":0},"noda":{"$":0},"ofunato":{"$":0},"oshu":{"$":0},"otsuchi":{"$":0},"rikuzentakata":{"$":0},"shiwa":{"$":0},"shizukuishi":{"$":0},"sumita":{"$":0},"tanohata":{"$":0},"tono":{"$":0},"yahaba":{"$":0},"yamada":{"$":0}},"kagawa":{"$":0,"ayagawa":{"$":0},"higashikagawa":{"$":0},"kanonji":{"$":0},"kotohira":{"$":0},"manno":{"$":0},"marugame":{"$":0},"mitoyo":{"$":0},"naoshima":{"$":0},"sanuki":{"$":0},"tadotsu":{"$":0},"takamatsu":{"$":0},"tonosho":{"$":0},"uchinomi":{"$":0},"utazu":{"$":0},"zentsuji":{"$":0}},"kagoshima":{"$":0,"akune":{"$":0},"amami":{"$":0},"hioki":{"$":0},"isa":{"$":0},"isen":{"$":0},"izumi":{"$":0},"kagoshima":{"$":0},"kanoya":{"$":0},"kawanabe":{"$":0},"kinko":{"$":0},"kouyama":{"$":0},"makurazaki":{"$":0},"matsumoto":{"$":0},"minamitane":{"$":0},"nakatane":{"$":0},"nishinoomote":{"$":0},"satsumasendai":{"$":0},"soo":{"$":0},"tarumizu":{"$":0},"yusui":{"$":0}},"kanagawa":{"$":0,"aikawa":{"$":0},"atsugi":{"$":0},"ayase":{"$":0},"chigasaki":{"$":0},"ebina":{"$":0},"fujisawa":{"$":0},"hadano":{"$":0},"hakone":{"$":0},"hiratsuka":{"$":0},"isehara":{"$":0},"kaisei":{"$":0},"kamakura":{"$":0},"kiyokawa":{"$":0},"matsuda":{"$":0},"minamiashigara":{"$":0},"miura":{"$":0},"nakai":{"$":0},"ninomiya":{"$":0},"odawara":{"$":0},"oi":{"$":0},"oiso":{"$":0},"sagamihara":{"$":0},"samukawa":{"$":0},"tsukui":{"$":0},"yamakita":{"$":0},"yamato":{"$":0},"yokosuka":{"$":0},"yugawara":{"$":0},"zama":{"$":0},"zushi":{"$":0}},"kochi":{"$":0,"aki":{"$":0},"geisei":{"$":0},"hidaka":{"$":0},"higashitsuno":{"$":0},"ino":{"$":0},"kagami":{"$":0},"kami":{"$":0},"kitagawa":{"$":0},"kochi":{"$":0},"mihara":{"$":0},"motoyama":{"$":0},"muroto":{"$":0},"nahari":{"$":0},"nakamura":{"$":0},"nankoku":{"$":0},"nishitosa":{"$":0},"niyodogawa":{"$":0},"ochi":{"$":0},"okawa":{"$":0},"otoyo":{"$":0},"otsuki":{"$":0},"sakawa":{"$":0},"sukumo":{"$":0},"susaki":{"$":0},"tosa":{"$":0},"tosashimizu":{"$":0},"toyo":{"$":0},"tsuno":{"$":0},"umaji":{"$":0},"yasuda":{"$":0},"yusuhara":{"$":0}},"kumamoto":{"$":0,"amakusa":{"$":0},"arao":{"$":0},"aso":{"$":0},"choyo":{"$":0},"gyokuto":{"$":0},"kamiamakusa":{"$":0},"kikuchi":{"$":0},"kumamoto":{"$":0},"mashiki":{"$":0},"mifune":{"$":0},"minamata":{"$":0},"minamioguni":{"$":0},"nagasu":{"$":0},"nishihara":{"$":0},"oguni":{"$":0},"ozu":{"$":0},"sumoto":{"$":0},"takamori":{"$":0},"uki":{"$":0},"uto":{"$":0},"yamaga":{"$":0},"yamato":{"$":0},"yatsushiro":{"$":0}},"kyoto":{"$":0,"ayabe":{"$":0},"fukuchiyama":{"$":0},"higashiyama":{"$":0},"ide":{"$":0},"ine":{"$":0},"joyo":{"$":0},"kameoka":{"$":0},"kamo":{"$":0},"kita":{"$":0},"kizu":{"$":0},"kumiyama":{"$":0},"kyotamba":{"$":0},"kyotanabe":{"$":0},"kyotango":{"$":0},"maizuru":{"$":0},"minami":{"$":0},"minamiyamashiro":{"$":0},"miyazu":{"$":0},"muko":{"$":0},"nagaokakyo":{"$":0},"nakagyo":{"$":0},"nantan":{"$":0},"oyamazaki":{"$":0},"sakyo":{"$":0},"seika":{"$":0},"tanabe":{"$":0},"uji":{"$":0},"ujitawara":{"$":0},"wazuka":{"$":0},"yamashina":{"$":0},"yawata":{"$":0}},"mie":{"$":0,"asahi":{"$":0},"inabe":{"$":0},"ise":{"$":0},"kameyama":{"$":0},"kawagoe":{"$":0},"kiho":{"$":0},"kisosaki":{"$":0},"kiwa":{"$":0},"komono":{"$":0},"kumano":{"$":0},"kuwana":{"$":0},"matsusaka":{"$":0},"meiwa":{"$":0},"mihama":{"$":0},"minamiise":{"$":0},"misugi":{"$":0},"miyama":{"$":0},"nabari":{"$":0},"shima":{"$":0},"suzuka":{"$":0},"tado":{"$":0},"taiki":{"$":0},"taki":{"$":0},"tamaki":{"$":0},"toba":{"$":0},"tsu":{"$":0},"udono":{"$":0},"ureshino":{"$":0},"watarai":{"$":0},"yokkaichi":{"$":0}},"miyagi":{"$":0,"furukawa":{"$":0},"higashimatsushima":{"$":0},"ishinomaki":{"$":0},"iwanuma":{"$":0},"kakuda":{"$":0},"kami":{"$":0},"kawasaki":{"$":0},"marumori":{"$":0},"matsushima":{"$":0},"minamisanriku":{"$":0},"misato":{"$":0},"murata":{"$":0},"natori":{"$":0},"ogawara":{"$":0},"ohira":{"$":0},"onagawa":{"$":0},"osaki":{"$":0},"rifu":{"$":0},"semine":{"$":0},"shibata":{"$":0},"shichikashuku":{"$":0},"shikama":{"$":0},"shiogama":{"$":0},"shiroishi":{"$":0},"tagajo":{"$":0},"taiwa":{"$":0},"tome":{"$":0},"tomiya":{"$":0},"wakuya":{"$":0},"watari":{"$":0},"yamamoto":{"$":0},"zao":{"$":0}},"miyazaki":{"$":0,"aya":{"$":0},"ebino":{"$":0},"gokase":{"$":0},"hyuga":{"$":0},"kadogawa":{"$":0},"kawaminami":{"$":0},"kijo":{"$":0},"kitagawa":{"$":0},"kitakata":{"$":0},"kitaura":{"$":0},"kobayashi":{"$":0},"kunitomi":{"$":0},"kushima":{"$":0},"mimata":{"$":0},"miyakonojo":{"$":0},"miyazaki":{"$":0},"morotsuka":{"$":0},"nichinan":{"$":0},"nishimera":{"$":0},"nobeoka":{"$":0},"saito":{"$":0},"shiiba":{"$":0},"shintomi":{"$":0},"takaharu":{"$":0},"takanabe":{"$":0},"takazaki":{"$":0},"tsuno":{"$":0}},"nagano":{"$":0,"achi":{"$":0},"agematsu":{"$":0},"anan":{"$":0},"aoki":{"$":0},"asahi":{"$":0},"azumino":{"$":0},"chikuhoku":{"$":0},"chikuma":{"$":0},"chino":{"$":0},"fujimi":{"$":0},"hakuba":{"$":0},"hara":{"$":0},"hiraya":{"$":0},"iida":{"$":0},"iijima":{"$":0},"iiyama":{"$":0},"iizuna":{"$":0},"ikeda":{"$":0},"ikusaka":{"$":0},"ina":{"$":0},"karuizawa":{"$":0},"kawakami":{"$":0},"kiso":{"$":0},"kisofukushima":{"$":0},"kitaaiki":{"$":0},"komagane":{"$":0},"komoro":{"$":0},"matsukawa":{"$":0},"matsumoto":{"$":0},"miasa":{"$":0},"minamiaiki":{"$":0},"minamimaki":{"$":0},"minamiminowa":{"$":0},"minowa":{"$":0},"miyada":{"$":0},"miyota":{"$":0},"mochizuki":{"$":0},"nagano":{"$":0},"nagawa":{"$":0},"nagiso":{"$":0},"nakagawa":{"$":0},"nakano":{"$":0},"nozawaonsen":{"$":0},"obuse":{"$":0},"ogawa":{"$":0},"okaya":{"$":0},"omachi":{"$":0},"omi":{"$":0},"ookuwa":{"$":0},"ooshika":{"$":0},"otaki":{"$":0},"otari":{"$":0},"sakae":{"$":0},"sakaki":{"$":0},"saku":{"$":0},"sakuho":{"$":0},"shimosuwa":{"$":0},"shinanomachi":{"$":0},"shiojiri":{"$":0},"suwa":{"$":0},"suzaka":{"$":0},"takagi":{"$":0},"takamori":{"$":0},"takayama":{"$":0},"tateshina":{"$":0},"tatsuno":{"$":0},"togakushi":{"$":0},"togura":{"$":0},"tomi":{"$":0},"ueda":{"$":0},"wada":{"$":0},"yamagata":{"$":0},"yamanouchi":{"$":0},"yasaka":{"$":0},"yasuoka":{"$":0}},"nagasaki":{"$":0,"chijiwa":{"$":0},"futsu":{"$":0},"goto":{"$":0},"hasami":{"$":0},"hirado":{"$":0},"iki":{"$":0},"isahaya":{"$":0},"kawatana":{"$":0},"kuchinotsu":{"$":0},"matsuura":{"$":0},"nagasaki":{"$":0},"obama":{"$":0},"omura":{"$":0},"oseto":{"$":0},"saikai":{"$":0},"sasebo":{"$":0},"seihi":{"$":0},"shimabara":{"$":0},"shinkamigoto":{"$":0},"togitsu":{"$":0},"tsushima":{"$":0},"unzen":{"$":0}},"nara":{"$":0,"ando":{"$":0},"gose":{"$":0},"heguri":{"$":0},"higashiyoshino":{"$":0},"ikaruga":{"$":0},"ikoma":{"$":0},"kamikitayama":{"$":0},"kanmaki":{"$":0},"kashiba":{"$":0},"kashihara":{"$":0},"katsuragi":{"$":0},"kawai":{"$":0},"kawakami":{"$":0},"kawanishi":{"$":0},"koryo":{"$":0},"kurotaki":{"$":0},"mitsue":{"$":0},"miyake":{"$":0},"nara":{"$":0},"nosegawa":{"$":0},"oji":{"$":0},"ouda":{"$":0},"oyodo":{"$":0},"sakurai":{"$":0},"sango":{"$":0},"shimoichi":{"$":0},"shimokitayama":{"$":0},"shinjo":{"$":0},"soni":{"$":0},"takatori":{"$":0},"tawaramoto":{"$":0},"tenkawa":{"$":0},"tenri":{"$":0},"uda":{"$":0},"yamatokoriyama":{"$":0},"yamatotakada":{"$":0},"yamazoe":{"$":0},"yoshino":{"$":0}},"niigata":{"$":0,"aga":{"$":0},"agano":{"$":0},"gosen":{"$":0},"itoigawa":{"$":0},"izumozaki":{"$":0},"joetsu":{"$":0},"kamo":{"$":0},"kariwa":{"$":0},"kashiwazaki":{"$":0},"minamiuonuma":{"$":0},"mitsuke":{"$":0},"muika":{"$":0},"murakami":{"$":0},"myoko":{"$":0},"nagaoka":{"$":0},"niigata":{"$":0},"ojiya":{"$":0},"omi":{"$":0},"sado":{"$":0},"sanjo":{"$":0},"seiro":{"$":0},"seirou":{"$":0},"sekikawa":{"$":0},"shibata":{"$":0},"tagami":{"$":0},"tainai":{"$":0},"tochio":{"$":0},"tokamachi":{"$":0},"tsubame":{"$":0},"tsunan":{"$":0},"uonuma":{"$":0},"yahiko":{"$":0},"yoita":{"$":0},"yuzawa":{"$":0}},"oita":{"$":0,"beppu":{"$":0},"bungoono":{"$":0},"bungotakada":{"$":0},"hasama":{"$":0},"hiji":{"$":0},"himeshima":{"$":0},"hita":{"$":0},"kamitsue":{"$":0},"kokonoe":{"$":0},"kuju":{"$":0},"kunisaki":{"$":0},"kusu":{"$":0},"oita":{"$":0},"saiki":{"$":0},"taketa":{"$":0},"tsukumi":{"$":0},"usa":{"$":0},"usuki":{"$":0},"yufu":{"$":0}},"okayama":{"$":0,"akaiwa":{"$":0},"asakuchi":{"$":0},"bizen":{"$":0},"hayashima":{"$":0},"ibara":{"$":0},"kagamino":{"$":0},"kasaoka":{"$":0},"kibichuo":{"$":0},"kumenan":{"$":0},"kurashiki":{"$":0},"maniwa":{"$":0},"misaki":{"$":0},"nagi":{"$":0},"niimi":{"$":0},"nishiawakura":{"$":0},"okayama":{"$":0},"satosho":{"$":0},"setouchi":{"$":0},"shinjo":{"$":0},"shoo":{"$":0},"soja":{"$":0},"takahashi":{"$":0},"tamano":{"$":0},"tsuyama":{"$":0},"wake":{"$":0},"yakage":{"$":0}},"okinawa":{"$":0,"aguni":{"$":0},"ginowan":{"$":0},"ginoza":{"$":0},"gushikami":{"$":0},"haebaru":{"$":0},"higashi":{"$":0},"hirara":{"$":0},"iheya":{"$":0},"ishigaki":{"$":0},"ishikawa":{"$":0},"itoman":{"$":0},"izena":{"$":0},"kadena":{"$":0},"kin":{"$":0},"kitadaito":{"$":0},"kitanakagusuku":{"$":0},"kumejima":{"$":0},"kunigami":{"$":0},"minamidaito":{"$":0},"motobu":{"$":0},"nago":{"$":0},"naha":{"$":0},"nakagusuku":{"$":0},"nakijin":{"$":0},"nanjo":{"$":0},"nishihara":{"$":0},"ogimi":{"$":0},"okinawa":{"$":0},"onna":{"$":0},"shimoji":{"$":0},"taketomi":{"$":0},"tarama":{"$":0},"tokashiki":{"$":0},"tomigusuku":{"$":0},"tonaki":{"$":0},"urasoe":{"$":0},"uruma":{"$":0},"yaese":{"$":0},"yomitan":{"$":0},"yonabaru":{"$":0},"yonaguni":{"$":0},"zamami":{"$":0}},"osaka":{"$":0,"abeno":{"$":0},"chihayaakasaka":{"$":0},"chuo":{"$":0},"daito":{"$":0},"fujiidera":{"$":0},"habikino":{"$":0},"hannan":{"$":0},"higashiosaka":{"$":0},"higashisumiyoshi":{"$":0},"higashiyodogawa":{"$":0},"hirakata":{"$":0},"ibaraki":{"$":0},"ikeda":{"$":0},"izumi":{"$":0},"izumiotsu":{"$":0},"izumisano":{"$":0},"kadoma":{"$":0},"kaizuka":{"$":0},"kanan":{"$":0},"kashiwara":{"$":0},"katano":{"$":0},"kawachinagano":{"$":0},"kishiwada":{"$":0},"kita":{"$":0},"kumatori":{"$":0},"matsubara":{"$":0},"minato":{"$":0},"minoh":{"$":0},"misaki":{"$":0},"moriguchi":{"$":0},"neyagawa":{"$":0},"nishi":{"$":0},"nose":{"$":0},"osakasayama":{"$":0},"sakai":{"$":0},"sayama":{"$":0},"sennan":{"$":0},"settsu":{"$":0},"shijonawate":{"$":0},"shimamoto":{"$":0},"suita":{"$":0},"tadaoka":{"$":0},"taishi":{"$":0},"tajiri":{"$":0},"takaishi":{"$":0},"takatsuki":{"$":0},"tondabayashi":{"$":0},"toyonaka":{"$":0},"toyono":{"$":0},"yao":{"$":0}},"saga":{"$":0,"ariake":{"$":0},"arita":{"$":0},"fukudomi":{"$":0},"genkai":{"$":0},"hamatama":{"$":0},"hizen":{"$":0},"imari":{"$":0},"kamimine":{"$":0},"kanzaki":{"$":0},"karatsu":{"$":0},"kashima":{"$":0},"kitagata":{"$":0},"kitahata":{"$":0},"kiyama":{"$":0},"kouhoku":{"$":0},"kyuragi":{"$":0},"nishiarita":{"$":0},"ogi":{"$":0},"omachi":{"$":0},"ouchi":{"$":0},"saga":{"$":0},"shiroishi":{"$":0},"taku":{"$":0},"tara":{"$":0},"tosu":{"$":0},"yoshinogari":{"$":0}},"saitama":{"$":0,"arakawa":{"$":0},"asaka":{"$":0},"chichibu":{"$":0},"fujimi":{"$":0},"fujimino":{"$":0},"fukaya":{"$":0},"hanno":{"$":0},"hanyu":{"$":0},"hasuda":{"$":0},"hatogaya":{"$":0},"hatoyama":{"$":0},"hidaka":{"$":0},"higashichichibu":{"$":0},"higashimatsuyama":{"$":0},"honjo":{"$":0},"ina":{"$":0},"iruma":{"$":0},"iwatsuki":{"$":0},"kamiizumi":{"$":0},"kamikawa":{"$":0},"kamisato":{"$":0},"kasukabe":{"$":0},"kawagoe":{"$":0},"kawaguchi":{"$":0},"kawajima":{"$":0},"kazo":{"$":0},"kitamoto":{"$":0},"koshigaya":{"$":0},"kounosu":{"$":0},"kuki":{"$":0},"kumagaya":{"$":0},"matsubushi":{"$":0},"minano":{"$":0},"misato":{"$":0},"miyashiro":{"$":0},"miyoshi":{"$":0},"moroyama":{"$":0},"nagatoro":{"$":0},"namegawa":{"$":0},"niiza":{"$":0},"ogano":{"$":0},"ogawa":{"$":0},"ogose":{"$":0},"okegawa":{"$":0},"omiya":{"$":0},"otaki":{"$":0},"ranzan":{"$":0},"ryokami":{"$":0},"saitama":{"$":0},"sakado":{"$":0},"satte":{"$":0},"sayama":{"$":0},"shiki":{"$":0},"shiraoka":{"$":0},"soka":{"$":0},"sugito":{"$":0},"toda":{"$":0},"tokigawa":{"$":0},"tokorozawa":{"$":0},"tsurugashima":{"$":0},"urawa":{"$":0},"warabi":{"$":0},"yashio":{"$":0},"yokoze":{"$":0},"yono":{"$":0},"yorii":{"$":0},"yoshida":{"$":0},"yoshikawa":{"$":0},"yoshimi":{"$":0}},"shiga":{"$":0,"aisho":{"$":0},"gamo":{"$":0},"higashiomi":{"$":0},"hikone":{"$":0},"koka":{"$":0},"konan":{"$":0},"kosei":{"$":0},"koto":{"$":0},"kusatsu":{"$":0},"maibara":{"$":0},"moriyama":{"$":0},"nagahama":{"$":0},"nishiazai":{"$":0},"notogawa":{"$":0},"omihachiman":{"$":0},"otsu":{"$":0},"ritto":{"$":0},"ryuoh":{"$":0},"takashima":{"$":0},"takatsuki":{"$":0},"torahime":{"$":0},"toyosato":{"$":0},"yasu":{"$":0}},"shimane":{"$":0,"akagi":{"$":0},"ama":{"$":0},"gotsu":{"$":0},"hamada":{"$":0},"higashiizumo":{"$":0},"hikawa":{"$":0},"hikimi":{"$":0},"izumo":{"$":0},"kakinoki":{"$":0},"masuda":{"$":0},"matsue":{"$":0},"misato":{"$":0},"nishinoshima":{"$":0},"ohda":{"$":0},"okinoshima":{"$":0},"okuizumo":{"$":0},"shimane":{"$":0},"tamayu":{"$":0},"tsuwano":{"$":0},"unnan":{"$":0},"yakumo":{"$":0},"yasugi":{"$":0},"yatsuka":{"$":0}},"shizuoka":{"$":0,"arai":{"$":0},"atami":{"$":0},"fuji":{"$":0},"fujieda":{"$":0},"fujikawa":{"$":0},"fujinomiya":{"$":0},"fukuroi":{"$":0},"gotemba":{"$":0},"haibara":{"$":0},"hamamatsu":{"$":0},"higashiizu":{"$":0},"ito":{"$":0},"iwata":{"$":0},"izu":{"$":0},"izunokuni":{"$":0},"kakegawa":{"$":0},"kannami":{"$":0},"kawanehon":{"$":0},"kawazu":{"$":0},"kikugawa":{"$":0},"kosai":{"$":0},"makinohara":{"$":0},"matsuzaki":{"$":0},"minamiizu":{"$":0},"mishima":{"$":0},"morimachi":{"$":0},"nishiizu":{"$":0},"numazu":{"$":0},"omaezaki":{"$":0},"shimada":{"$":0},"shimizu":{"$":0},"shimoda":{"$":0},"shizuoka":{"$":0},"susono":{"$":0},"yaizu":{"$":0},"yoshida":{"$":0}},"tochigi":{"$":0,"ashikaga":{"$":0},"bato":{"$":0},"haga":{"$":0},"ichikai":{"$":0},"iwafune":{"$":0},"kaminokawa":{"$":0},"kanuma":{"$":0},"karasuyama":{"$":0},"kuroiso":{"$":0},"mashiko":{"$":0},"mibu":{"$":0},"moka":{"$":0},"motegi":{"$":0},"nasu":{"$":0},"nasushiobara":{"$":0},"nikko":{"$":0},"nishikata":{"$":0},"nogi":{"$":0},"ohira":{"$":0},"ohtawara":{"$":0},"oyama":{"$":0},"sakura":{"$":0},"sano":{"$":0},"shimotsuke":{"$":0},"shioya":{"$":0},"takanezawa":{"$":0},"tochigi":{"$":0},"tsuga":{"$":0},"ujiie":{"$":0},"utsunomiya":{"$":0},"yaita":{"$":0}},"tokushima":{"$":0,"aizumi":{"$":0},"anan":{"$":0},"ichiba":{"$":0},"itano":{"$":0},"kainan":{"$":0},"komatsushima":{"$":0},"matsushige":{"$":0},"mima":{"$":0},"minami":{"$":0},"miyoshi":{"$":0},"mugi":{"$":0},"nakagawa":{"$":0},"naruto":{"$":0},"sanagochi":{"$":0},"shishikui":{"$":0},"tokushima":{"$":0},"wajiki":{"$":0}},"tokyo":{"$":0,"adachi":{"$":0},"akiruno":{"$":0},"akishima":{"$":0},"aogashima":{"$":0},"arakawa":{"$":0},"bunkyo":{"$":0},"chiyoda":{"$":0},"chofu":{"$":0},"chuo":{"$":0},"edogawa":{"$":0},"fuchu":{"$":0},"fussa":{"$":0},"hachijo":{"$":0},"hachioji":{"$":0},"hamura":{"$":0},"higashikurume":{"$":0},"higashimurayama":{"$":0},"higashiyamato":{"$":0},"hino":{"$":0},"hinode":{"$":0},"hinohara":{"$":0},"inagi":{"$":0},"itabashi":{"$":0},"katsushika":{"$":0},"kita":{"$":0},"kiyose":{"$":0},"kodaira":{"$":0},"koganei":{"$":0},"kokubunji":{"$":0},"komae":{"$":0},"koto":{"$":0},"kouzushima":{"$":0},"kunitachi":{"$":0},"machida":{"$":0},"meguro":{"$":0},"minato":{"$":0},"mitaka":{"$":0},"mizuho":{"$":0},"musashimurayama":{"$":0},"musashino":{"$":0},"nakano":{"$":0},"nerima":{"$":0},"ogasawara":{"$":0},"okutama":{"$":0},"ome":{"$":0},"oshima":{"$":0},"ota":{"$":0},"setagaya":{"$":0},"shibuya":{"$":0},"shinagawa":{"$":0},"shinjuku":{"$":0},"suginami":{"$":0},"sumida":{"$":0},"tachikawa":{"$":0},"taito":{"$":0},"tama":{"$":0},"toshima":{"$":0}},"tottori":{"$":0,"chizu":{"$":0},"hino":{"$":0},"kawahara":{"$":0},"koge":{"$":0},"kotoura":{"$":0},"misasa":{"$":0},"nanbu":{"$":0},"nichinan":{"$":0},"sakaiminato":{"$":0},"tottori":{"$":0},"wakasa":{"$":0},"yazu":{"$":0},"yonago":{"$":0}},"toyama":{"$":0,"asahi":{"$":0},"fuchu":{"$":0},"fukumitsu":{"$":0},"funahashi":{"$":0},"himi":{"$":0},"imizu":{"$":0},"inami":{"$":0},"johana":{"$":0},"kamiichi":{"$":0},"kurobe":{"$":0},"nakaniikawa":{"$":0},"namerikawa":{"$":0},"nanto":{"$":0},"nyuzen":{"$":0},"oyabe":{"$":0},"taira":{"$":0},"takaoka":{"$":0},"tateyama":{"$":0},"toga":{"$":0},"tonami":{"$":0},"toyama":{"$":0},"unazuki":{"$":0},"uozu":{"$":0},"yamada":{"$":0}},"wakayama":{"$":0,"arida":{"$":0},"aridagawa":{"$":0},"gobo":{"$":0},"hashimoto":{"$":0},"hidaka":{"$":0},"hirogawa":{"$":0},"inami":{"$":0},"iwade":{"$":0},"kainan":{"$":0},"kamitonda":{"$":0},"katsuragi":{"$":0},"kimino":{"$":0},"kinokawa":{"$":0},"kitayama":{"$":0},"koya":{"$":0},"koza":{"$":0},"kozagawa":{"$":0},"kudoyama":{"$":0},"kushimoto":{"$":0},"mihama":{"$":0},"misato":{"$":0},"nachikatsuura":{"$":0},"shingu":{"$":0},"shirahama":{"$":0},"taiji":{"$":0},"tanabe":{"$":0},"wakayama":{"$":0},"yuasa":{"$":0},"yura":{"$":0}},"yamagata":{"$":0,"asahi":{"$":0},"funagata":{"$":0},"higashine":{"$":0},"iide":{"$":0},"kahoku":{"$":0},"kaminoyama":{"$":0},"kaneyama":{"$":0},"kawanishi":{"$":0},"mamurogawa":{"$":0},"mikawa":{"$":0},"murayama":{"$":0},"nagai":{"$":0},"nakayama":{"$":0},"nanyo":{"$":0},"nishikawa":{"$":0},"obanazawa":{"$":0},"oe":{"$":0},"oguni":{"$":0},"ohkura":{"$":0},"oishida":{"$":0},"sagae":{"$":0},"sakata":{"$":0},"sakegawa":{"$":0},"shinjo":{"$":0},"shirataka":{"$":0},"shonai":{"$":0},"takahata":{"$":0},"tendo":{"$":0},"tozawa":{"$":0},"tsuruoka":{"$":0},"yamagata":{"$":0},"yamanobe":{"$":0},"yonezawa":{"$":0},"yuza":{"$":0}},"yamaguchi":{"$":0,"abu":{"$":0},"hagi":{"$":0},"hikari":{"$":0},"hofu":{"$":0},"iwakuni":{"$":0},"kudamatsu":{"$":0},"mitou":{"$":0},"nagato":{"$":0},"oshima":{"$":0},"shimonoseki":{"$":0},"shunan":{"$":0},"tabuse":{"$":0},"tokuyama":{"$":0},"toyota":{"$":0},"ube":{"$":0},"yuu":{"$":0}},"yamanashi":{"$":0,"chuo":{"$":0},"doshi":{"$":0},"fuefuki":{"$":0},"fujikawa":{"$":0},"fujikawaguchiko":{"$":0},"fujiyoshida":{"$":0},"hayakawa":{"$":0},"hokuto":{"$":0},"ichikawamisato":{"$":0},"kai":{"$":0},"kofu":{"$":0},"koshu":{"$":0},"kosuge":{"$":0},"minami-alps":{"$":0},"minobu":{"$":0},"nakamichi":{"$":0},"nanbu":{"$":0},"narusawa":{"$":0},"nirasaki":{"$":0},"nishikatsura":{"$":0},"oshino":{"$":0},"otsuki":{"$":0},"showa":{"$":0},"tabayama":{"$":0},"tsuru":{"$":0},"uenohara":{"$":0},"yamanakako":{"$":0},"yamanashi":{"$":0}},"xn--4pvxs":{"$":0},"xn--vgu402c":{"$":0},"xn--c3s14m":{"$":0},"xn--f6qx53a":{"$":0},"xn--8pvr4u":{"$":0},"xn--uist22h":{"$":0},"xn--djrs72d6uy":{"$":0},"xn--mkru45i":{"$":0},"xn--0trq7p7nn":{"$":0},"xn--8ltr62k":{"$":0},"xn--2m4a15e":{"$":0},"xn--efvn9s":{"$":0},"xn--32vp30h":{"$":0},"xn--4it797k":{"$":0},"xn--1lqs71d":{"$":0},"xn--5rtp49c":{"$":0},"xn--5js045d":{"$":0},"xn--ehqz56n":{"$":0},"xn--1lqs03n":{"$":0},"xn--qqqt11m":{"$":0},"xn--kbrq7o":{"$":0},"xn--pssu33l":{"$":0},"xn--ntsq17g":{"$":0},"xn--uisz3g":{"$":0},"xn--6btw5a":{"$":0},"xn--1ctwo":{"$":0},"xn--6orx2r":{"$":0},"xn--rht61e":{"$":0},"xn--rht27z":{"$":0},"xn--djty4k":{"$":0},"xn--nit225k":{"$":0},"xn--rht3d":{"$":0},"xn--klty5x":{"$":0},"xn--kltx9a":{"$":0},"xn--kltp7d":{"$":0},"xn--uuwu58a":{"$":0},"xn--zbx025d":{"$":0},"xn--ntso0iqx3a":{"$":0},"xn--elqq16h":{"$":0},"xn--4it168d":{"$":0},"xn--klt787d":{"$":0},"xn--rny31h":{"$":0},"xn--7t0a264c":{"$":0},"xn--5rtq34k":{"$":0},"xn--k7yn95e":{"$":0},"xn--tor131o":{"$":0},"xn--d5qv7z876c":{"$":0},"kawasaki":{"*":{"$":0}},"kitakyushu":{"*":{"$":0}},"kobe":{"*":{"$":0}},"nagoya":{"*":{"$":0}},"sapporo":{"*":{"$":0}},"sendai":{"*":{"$":0}},"yokohama":{"*":{"$":0}},"blogspot":{"$":0}},"ke":{"$":0,"ac":{"$":0},"co":{"$":0,"blogspot":{"$":0}},"go":{"$":0},"info":{"$":0},"me":{"$":0},"mobi":{"$":0},"ne":{"$":0},"or":{"$":0},"sc":{"$":0}},"kg":{"$":0,"org":{"$":0},"net":{"$":0},"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"mil":{"$":0}},"kh":{"*":{"$":0}},"ki":{"$":0,"edu":{"$":0},"biz":{"$":0},"net":{"$":0},"org":{"$":0},"gov":{"$":0},"info":{"$":0},"com":{"$":0}},"km":{"$":0,"org":{"$":0},"nom":{"$":0},"gov":{"$":0},"prd":{"$":0},"tm":{"$":0},"edu":{"$":0},"mil":{"$":0},"ass":{"$":0},"com":{"$":0},"coop":{"$":0},"asso":{"$":0},"presse":{"$":0},"medecin":{"$":0},"notaires":{"$":0},"pharmaciens":{"$":0},"veterinaire":{"$":0},"gouv":{"$":0}},"kn":{"$":0,"net":{"$":0},"org":{"$":0},"edu":{"$":0},"gov":{"$":0}},"kp":{"$":0,"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"org":{"$":0},"rep":{"$":0},"tra":{"$":0}},"kr":{"$":0,"ac":{"$":0},"co":{"$":0},"es":{"$":0},"go":{"$":0},"hs":{"$":0},"kg":{"$":0},"mil":{"$":0},"ms":{"$":0},"ne":{"$":0},"or":{"$":0},"pe":{"$":0},"re":{"$":0},"sc":{"$":0},"busan":{"$":0},"chungbuk":{"$":0},"chungnam":{"$":0},"daegu":{"$":0},"daejeon":{"$":0},"gangwon":{"$":0},"gwangju":{"$":0},"gyeongbuk":{"$":0},"gyeonggi":{"$":0},"gyeongnam":{"$":0},"incheon":{"$":0},"jeju":{"$":0},"jeonbuk":{"$":0},"jeonnam":{"$":0},"seoul":{"$":0},"ulsan":{"$":0},"blogspot":{"$":0}},"kw":{"*":{"$":0}},"ky":{"$":0,"edu":{"$":0},"gov":{"$":0},"com":{"$":0},"org":{"$":0},"net":{"$":0}},"kz":{"$":0,"org":{"$":0},"edu":{"$":0},"net":{"$":0},"gov":{"$":0},"mil":{"$":0},"com":{"$":0},"nym":{"$":0}},"la":{"$":0,"int":{"$":0},"net":{"$":0},"info":{"$":0},"edu":{"$":0},"gov":{"$":0},"per":{"$":0},"com":{"$":0},"org":{"$":0},"bnr":{"$":0},"c":{"$":0},"nym":{"$":0}},"lb":{"$":0,"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"net":{"$":0},"org":{"$":0}},"lc":{"$":0,"com":{"$":0},"net":{"$":0},"co":{"$":0},"org":{"$":0},"edu":{"$":0},"gov":{"$":0},"oy":{"$":0}},"li":{"$":0,"blogspot":{"$":0},"nom":{"$":0},"nym":{"$":0}},"lk":{"$":0,"gov":{"$":0},"sch":{"$":0},"net":{"$":0},"int":{"$":0},"com":{"$":0},"org":{"$":0},"edu":{"$":0},"ngo":{"$":0},"soc":{"$":0},"web":{"$":0},"ltd":{"$":0},"assn":{"$":0},"grp":{"$":0},"hotel":{"$":0},"ac":{"$":0}},"lr":{"$":0,"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"org":{"$":0},"net":{"$":0}},"ls":{"$":0,"co":{"$":0},"org":{"$":0}},"lt":{"$":0,"gov":{"$":0},"blogspot":{"$":0},"nym":{"$":0}},"lu":{"$":0,"blogspot":{"$":0},"nym":{"$":0}},"lv":{"$":0,"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"org":{"$":0},"mil":{"$":0},"id":{"$":0},"net":{"$":0},"asn":{"$":0},"conf":{"$":0}},"ly":{"$":0,"com":{"$":0},"net":{"$":0},"gov":{"$":0},"plc":{"$":0},"edu":{"$":0},"sch":{"$":0},"med":{"$":0},"org":{"$":0},"id":{"$":0}},"ma":{"$":0,"co":{"$":0},"net":{"$":0},"gov":{"$":0},"org":{"$":0},"ac":{"$":0},"press":{"$":0}},"mc":{"$":0,"tm":{"$":0},"asso":{"$":0}},"md":{"$":0,"blogspot":{"$":0}},"me":{"$":0,"co":{"$":0},"net":{"$":0},"org":{"$":0},"edu":{"$":0},"ac":{"$":0},"gov":{"$":0},"its":{"$":0},"priv":{"$":0},"c66":{"$":0},"daplie":{"$":0,"localhost":{"$":0}},"filegear":{"$":0},"brasilia":{"$":0},"ddns":{"$":0},"dnsfor":{"$":0},"hopto":{"$":0},"loginto":{"$":0},"noip":{"$":0},"webhop":{"$":0},"nym":{"$":0},"diskstation":{"$":0},"dscloud":{"$":0},"i234":{"$":0},"myds":{"$":0},"synology":{"$":0},"wedeploy":{"$":0},"yombo":{"$":0}},"mg":{"$":0,"org":{"$":0},"nom":{"$":0},"gov":{"$":0},"prd":{"$":0},"tm":{"$":0},"edu":{"$":0},"mil":{"$":0},"com":{"$":0},"co":{"$":0}},"mh":{"$":0},"mil":{"$":0},"mk":{"$":0,"com":{"$":0},"org":{"$":0},"net":{"$":0},"edu":{"$":0},"gov":{"$":0},"inf":{"$":0},"name":{"$":0},"blogspot":{"$":0},"nom":{"$":0}},"ml":{"$":0,"com":{"$":0},"edu":{"$":0},"gouv":{"$":0},"gov":{"$":0},"net":{"$":0},"org":{"$":0},"presse":{"$":0}},"mm":{"*":{"$":0}},"mn":{"$":0,"gov":{"$":0},"edu":{"$":0},"org":{"$":0},"nyc":{"$":0}},"mo":{"$":0,"com":{"$":0},"net":{"$":0},"org":{"$":0},"edu":{"$":0},"gov":{"$":0}},"mobi":{"$":0,"dscloud":{"$":0}},"mp":{"$":0},"mq":{"$":0},"mr":{"$":0,"gov":{"$":0},"blogspot":{"$":0}},"ms":{"$":0,"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"net":{"$":0},"org":{"$":0}},"mt":{"$":0,"com":{"$":0,"blogspot":{"$":0}},"edu":{"$":0},"net":{"$":0},"org":{"$":0}},"mu":{"$":0,"com":{"$":0},"net":{"$":0},"org":{"$":0},"gov":{"$":0},"ac":{"$":0},"co":{"$":0},"or":{"$":0}},"museum":{"$":0,"academy":{"$":0},"agriculture":{"$":0},"air":{"$":0},"airguard":{"$":0},"alabama":{"$":0},"alaska":{"$":0},"amber":{"$":0},"ambulance":{"$":0},"american":{"$":0},"americana":{"$":0},"americanantiques":{"$":0},"americanart":{"$":0},"amsterdam":{"$":0},"and":{"$":0},"annefrank":{"$":0},"anthro":{"$":0},"anthropology":{"$":0},"antiques":{"$":0},"aquarium":{"$":0},"arboretum":{"$":0},"archaeological":{"$":0},"archaeology":{"$":0},"architecture":{"$":0},"art":{"$":0},"artanddesign":{"$":0},"artcenter":{"$":0},"artdeco":{"$":0},"arteducation":{"$":0},"artgallery":{"$":0},"arts":{"$":0},"artsandcrafts":{"$":0},"asmatart":{"$":0},"assassination":{"$":0},"assisi":{"$":0},"association":{"$":0},"astronomy":{"$":0},"atlanta":{"$":0},"austin":{"$":0},"australia":{"$":0},"automotive":{"$":0},"aviation":{"$":0},"axis":{"$":0},"badajoz":{"$":0},"baghdad":{"$":0},"bahn":{"$":0},"bale":{"$":0},"baltimore":{"$":0},"barcelona":{"$":0},"baseball":{"$":0},"basel":{"$":0},"baths":{"$":0},"bauern":{"$":0},"beauxarts":{"$":0},"beeldengeluid":{"$":0},"bellevue":{"$":0},"bergbau":{"$":0},"berkeley":{"$":0},"berlin":{"$":0},"bern":{"$":0},"bible":{"$":0},"bilbao":{"$":0},"bill":{"$":0},"birdart":{"$":0},"birthplace":{"$":0},"bonn":{"$":0},"boston":{"$":0},"botanical":{"$":0},"botanicalgarden":{"$":0},"botanicgarden":{"$":0},"botany":{"$":0},"brandywinevalley":{"$":0},"brasil":{"$":0},"bristol":{"$":0},"british":{"$":0},"britishcolumbia":{"$":0},"broadcast":{"$":0},"brunel":{"$":0},"brussel":{"$":0},"brussels":{"$":0},"bruxelles":{"$":0},"building":{"$":0},"burghof":{"$":0},"bus":{"$":0},"bushey":{"$":0},"cadaques":{"$":0},"california":{"$":0},"cambridge":{"$":0},"can":{"$":0},"canada":{"$":0},"capebreton":{"$":0},"carrier":{"$":0},"cartoonart":{"$":0},"casadelamoneda":{"$":0},"castle":{"$":0},"castres":{"$":0},"celtic":{"$":0},"center":{"$":0},"chattanooga":{"$":0},"cheltenham":{"$":0},"chesapeakebay":{"$":0},"chicago":{"$":0},"children":{"$":0},"childrens":{"$":0},"childrensgarden":{"$":0},"chiropractic":{"$":0},"chocolate":{"$":0},"christiansburg":{"$":0},"cincinnati":{"$":0},"cinema":{"$":0},"circus":{"$":0},"civilisation":{"$":0},"civilization":{"$":0},"civilwar":{"$":0},"clinton":{"$":0},"clock":{"$":0},"coal":{"$":0},"coastaldefence":{"$":0},"cody":{"$":0},"coldwar":{"$":0},"collection":{"$":0},"colonialwilliamsburg":{"$":0},"coloradoplateau":{"$":0},"columbia":{"$":0},"columbus":{"$":0},"communication":{"$":0},"communications":{"$":0},"community":{"$":0},"computer":{"$":0},"computerhistory":{"$":0},"xn--comunicaes-v6a2o":{"$":0},"contemporary":{"$":0},"contemporaryart":{"$":0},"convent":{"$":0},"copenhagen":{"$":0},"corporation":{"$":0},"xn--correios-e-telecomunicaes-ghc29a":{"$":0},"corvette":{"$":0},"costume":{"$":0},"countryestate":{"$":0},"county":{"$":0},"crafts":{"$":0},"cranbrook":{"$":0},"creation":{"$":0},"cultural":{"$":0},"culturalcenter":{"$":0},"culture":{"$":0},"cyber":{"$":0},"cymru":{"$":0},"dali":{"$":0},"dallas":{"$":0},"database":{"$":0},"ddr":{"$":0},"decorativearts":{"$":0},"delaware":{"$":0},"delmenhorst":{"$":0},"denmark":{"$":0},"depot":{"$":0},"design":{"$":0},"detroit":{"$":0},"dinosaur":{"$":0},"discovery":{"$":0},"dolls":{"$":0},"donostia":{"$":0},"durham":{"$":0},"eastafrica":{"$":0},"eastcoast":{"$":0},"education":{"$":0},"educational":{"$":0},"egyptian":{"$":0},"eisenbahn":{"$":0},"elburg":{"$":0},"elvendrell":{"$":0},"embroidery":{"$":0},"encyclopedic":{"$":0},"england":{"$":0},"entomology":{"$":0},"environment":{"$":0},"environmentalconservation":{"$":0},"epilepsy":{"$":0},"essex":{"$":0},"estate":{"$":0},"ethnology":{"$":0},"exeter":{"$":0},"exhibition":{"$":0},"family":{"$":0},"farm":{"$":0},"farmequipment":{"$":0},"farmers":{"$":0},"farmstead":{"$":0},"field":{"$":0},"figueres":{"$":0},"filatelia":{"$":0},"film":{"$":0},"fineart":{"$":0},"finearts":{"$":0},"finland":{"$":0},"flanders":{"$":0},"florida":{"$":0},"force":{"$":0},"fortmissoula":{"$":0},"fortworth":{"$":0},"foundation":{"$":0},"francaise":{"$":0},"frankfurt":{"$":0},"franziskaner":{"$":0},"freemasonry":{"$":0},"freiburg":{"$":0},"fribourg":{"$":0},"frog":{"$":0},"fundacio":{"$":0},"furniture":{"$":0},"gallery":{"$":0},"garden":{"$":0},"gateway":{"$":0},"geelvinck":{"$":0},"gemological":{"$":0},"geology":{"$":0},"georgia":{"$":0},"giessen":{"$":0},"glas":{"$":0},"glass":{"$":0},"gorge":{"$":0},"grandrapids":{"$":0},"graz":{"$":0},"guernsey":{"$":0},"halloffame":{"$":0},"hamburg":{"$":0},"handson":{"$":0},"harvestcelebration":{"$":0},"hawaii":{"$":0},"health":{"$":0},"heimatunduhren":{"$":0},"hellas":{"$":0},"helsinki":{"$":0},"hembygdsforbund":{"$":0},"heritage":{"$":0},"histoire":{"$":0},"historical":{"$":0},"historicalsociety":{"$":0},"historichouses":{"$":0},"historisch":{"$":0},"historisches":{"$":0},"history":{"$":0},"historyofscience":{"$":0},"horology":{"$":0},"house":{"$":0},"humanities":{"$":0},"illustration":{"$":0},"imageandsound":{"$":0},"indian":{"$":0},"indiana":{"$":0},"indianapolis":{"$":0},"indianmarket":{"$":0},"intelligence":{"$":0},"interactive":{"$":0},"iraq":{"$":0},"iron":{"$":0},"isleofman":{"$":0},"jamison":{"$":0},"jefferson":{"$":0},"jerusalem":{"$":0},"jewelry":{"$":0},"jewish":{"$":0},"jewishart":{"$":0},"jfk":{"$":0},"journalism":{"$":0},"judaica":{"$":0},"judygarland":{"$":0},"juedisches":{"$":0},"juif":{"$":0},"karate":{"$":0},"karikatur":{"$":0},"kids":{"$":0},"koebenhavn":{"$":0},"koeln":{"$":0},"kunst":{"$":0},"kunstsammlung":{"$":0},"kunstunddesign":{"$":0},"labor":{"$":0},"labour":{"$":0},"lajolla":{"$":0},"lancashire":{"$":0},"landes":{"$":0},"lans":{"$":0},"xn--lns-qla":{"$":0},"larsson":{"$":0},"lewismiller":{"$":0},"lincoln":{"$":0},"linz":{"$":0},"living":{"$":0},"livinghistory":{"$":0},"localhistory":{"$":0},"london":{"$":0},"losangeles":{"$":0},"louvre":{"$":0},"loyalist":{"$":0},"lucerne":{"$":0},"luxembourg":{"$":0},"luzern":{"$":0},"mad":{"$":0},"madrid":{"$":0},"mallorca":{"$":0},"manchester":{"$":0},"mansion":{"$":0},"mansions":{"$":0},"manx":{"$":0},"marburg":{"$":0},"maritime":{"$":0},"maritimo":{"$":0},"maryland":{"$":0},"marylhurst":{"$":0},"media":{"$":0},"medical":{"$":0},"medizinhistorisches":{"$":0},"meeres":{"$":0},"memorial":{"$":0},"mesaverde":{"$":0},"michigan":{"$":0},"midatlantic":{"$":0},"military":{"$":0},"mill":{"$":0},"miners":{"$":0},"mining":{"$":0},"minnesota":{"$":0},"missile":{"$":0},"missoula":{"$":0},"modern":{"$":0},"moma":{"$":0},"money":{"$":0},"monmouth":{"$":0},"monticello":{"$":0},"montreal":{"$":0},"moscow":{"$":0},"motorcycle":{"$":0},"muenchen":{"$":0},"muenster":{"$":0},"mulhouse":{"$":0},"muncie":{"$":0},"museet":{"$":0},"museumcenter":{"$":0},"museumvereniging":{"$":0},"music":{"$":0},"national":{"$":0},"nationalfirearms":{"$":0},"nationalheritage":{"$":0},"nativeamerican":{"$":0},"naturalhistory":{"$":0},"naturalhistorymuseum":{"$":0},"naturalsciences":{"$":0},"nature":{"$":0},"naturhistorisches":{"$":0},"natuurwetenschappen":{"$":0},"naumburg":{"$":0},"naval":{"$":0},"nebraska":{"$":0},"neues":{"$":0},"newhampshire":{"$":0},"newjersey":{"$":0},"newmexico":{"$":0},"newport":{"$":0},"newspaper":{"$":0},"newyork":{"$":0},"niepce":{"$":0},"norfolk":{"$":0},"north":{"$":0},"nrw":{"$":0},"nuernberg":{"$":0},"nuremberg":{"$":0},"nyc":{"$":0},"nyny":{"$":0},"oceanographic":{"$":0},"oceanographique":{"$":0},"omaha":{"$":0},"online":{"$":0},"ontario":{"$":0},"openair":{"$":0},"oregon":{"$":0},"oregontrail":{"$":0},"otago":{"$":0},"oxford":{"$":0},"pacific":{"$":0},"paderborn":{"$":0},"palace":{"$":0},"paleo":{"$":0},"palmsprings":{"$":0},"panama":{"$":0},"paris":{"$":0},"pasadena":{"$":0},"pharmacy":{"$":0},"philadelphia":{"$":0},"philadelphiaarea":{"$":0},"philately":{"$":0},"phoenix":{"$":0},"photography":{"$":0},"pilots":{"$":0},"pittsburgh":{"$":0},"planetarium":{"$":0},"plantation":{"$":0},"plants":{"$":0},"plaza":{"$":0},"portal":{"$":0},"portland":{"$":0},"portlligat":{"$":0},"posts-and-telecommunications":{"$":0},"preservation":{"$":0},"presidio":{"$":0},"press":{"$":0},"project":{"$":0},"public":{"$":0},"pubol":{"$":0},"quebec":{"$":0},"railroad":{"$":0},"railway":{"$":0},"research":{"$":0},"resistance":{"$":0},"riodejaneiro":{"$":0},"rochester":{"$":0},"rockart":{"$":0},"roma":{"$":0},"russia":{"$":0},"saintlouis":{"$":0},"salem":{"$":0},"salvadordali":{"$":0},"salzburg":{"$":0},"sandiego":{"$":0},"sanfrancisco":{"$":0},"santabarbara":{"$":0},"santacruz":{"$":0},"santafe":{"$":0},"saskatchewan":{"$":0},"satx":{"$":0},"savannahga":{"$":0},"schlesisches":{"$":0},"schoenbrunn":{"$":0},"schokoladen":{"$":0},"school":{"$":0},"schweiz":{"$":0},"science":{"$":0},"scienceandhistory":{"$":0},"scienceandindustry":{"$":0},"sciencecenter":{"$":0},"sciencecenters":{"$":0},"science-fiction":{"$":0},"sciencehistory":{"$":0},"sciences":{"$":0},"sciencesnaturelles":{"$":0},"scotland":{"$":0},"seaport":{"$":0},"settlement":{"$":0},"settlers":{"$":0},"shell":{"$":0},"sherbrooke":{"$":0},"sibenik":{"$":0},"silk":{"$":0},"ski":{"$":0},"skole":{"$":0},"society":{"$":0},"sologne":{"$":0},"soundandvision":{"$":0},"southcarolina":{"$":0},"southwest":{"$":0},"space":{"$":0},"spy":{"$":0},"square":{"$":0},"stadt":{"$":0},"stalbans":{"$":0},"starnberg":{"$":0},"state":{"$":0},"stateofdelaware":{"$":0},"station":{"$":0},"steam":{"$":0},"steiermark":{"$":0},"stjohn":{"$":0},"stockholm":{"$":0},"stpetersburg":{"$":0},"stuttgart":{"$":0},"suisse":{"$":0},"surgeonshall":{"$":0},"surrey":{"$":0},"svizzera":{"$":0},"sweden":{"$":0},"sydney":{"$":0},"tank":{"$":0},"tcm":{"$":0},"technology":{"$":0},"telekommunikation":{"$":0},"television":{"$":0},"texas":{"$":0},"textile":{"$":0},"theater":{"$":0},"time":{"$":0},"timekeeping":{"$":0},"topology":{"$":0},"torino":{"$":0},"touch":{"$":0},"town":{"$":0},"transport":{"$":0},"tree":{"$":0},"trolley":{"$":0},"trust":{"$":0},"trustee":{"$":0},"uhren":{"$":0},"ulm":{"$":0},"undersea":{"$":0},"university":{"$":0},"usa":{"$":0},"usantiques":{"$":0},"usarts":{"$":0},"uscountryestate":{"$":0},"usculture":{"$":0},"usdecorativearts":{"$":0},"usgarden":{"$":0},"ushistory":{"$":0},"ushuaia":{"$":0},"uslivinghistory":{"$":0},"utah":{"$":0},"uvic":{"$":0},"valley":{"$":0},"vantaa":{"$":0},"versailles":{"$":0},"viking":{"$":0},"village":{"$":0},"virginia":{"$":0},"virtual":{"$":0},"virtuel":{"$":0},"vlaanderen":{"$":0},"volkenkunde":{"$":0},"wales":{"$":0},"wallonie":{"$":0},"war":{"$":0},"washingtondc":{"$":0},"watchandclock":{"$":0},"watch-and-clock":{"$":0},"western":{"$":0},"westfalen":{"$":0},"whaling":{"$":0},"wildlife":{"$":0},"williamsburg":{"$":0},"windmill":{"$":0},"workshop":{"$":0},"york":{"$":0},"yorkshire":{"$":0},"yosemite":{"$":0},"youth":{"$":0},"zoological":{"$":0},"zoology":{"$":0},"xn--9dbhblg6di":{"$":0},"xn--h1aegh":{"$":0}},"mv":{"$":0,"aero":{"$":0},"biz":{"$":0},"com":{"$":0},"coop":{"$":0},"edu":{"$":0},"gov":{"$":0},"info":{"$":0},"int":{"$":0},"mil":{"$":0},"museum":{"$":0},"name":{"$":0},"net":{"$":0},"org":{"$":0},"pro":{"$":0}},"mw":{"$":0,"ac":{"$":0},"biz":{"$":0},"co":{"$":0},"com":{"$":0},"coop":{"$":0},"edu":{"$":0},"gov":{"$":0},"int":{"$":0},"museum":{"$":0},"net":{"$":0},"org":{"$":0}},"mx":{"$":0,"com":{"$":0},"org":{"$":0},"gob":{"$":0},"edu":{"$":0},"net":{"$":0},"blogspot":{"$":0},"nym":{"$":0}},"my":{"$":0,"com":{"$":0},"net":{"$":0},"org":{"$":0},"gov":{"$":0},"edu":{"$":0},"mil":{"$":0},"name":{"$":0},"blogspot":{"$":0}},"mz":{"$":0,"ac":{"$":0},"adv":{"$":0},"co":{"$":0},"edu":{"$":0},"gov":{"$":0},"mil":{"$":0},"net":{"$":0},"org":{"$":0}},"na":{"$":0,"info":{"$":0},"pro":{"$":0},"name":{"$":0},"school":{"$":0},"or":{"$":0},"dr":{"$":0},"us":{"$":0},"mx":{"$":0},"ca":{"$":0},"in":{"$":0},"cc":{"$":0},"tv":{"$":0},"ws":{"$":0},"mobi":{"$":0},"co":{"$":0},"com":{"$":0},"org":{"$":0}},"name":{"$":0,"her":{"forgot":{"$":0}},"his":{"forgot":{"$":0}}},"nc":{"$":0,"asso":{"$":0},"nom":{"$":0}},"ne":{"$":0},"net":{"$":0,"alwaysdata":{"$":0},"cloudfront":{"$":0},"t3l3p0rt":{"$":0},"myfritz":{"$":0},"boomla":{"$":0},"bplaced":{"$":0},"square7":{"$":0},"gb":{"$":0},"hu":{"$":0},"jp":{"$":0},"se":{"$":0},"uk":{"$":0},"in":{"$":0},"cloudaccess":{"$":0},"cdn77-ssl":{"$":0},"cdn77":{"r":{"$":0}},"feste-ip":{"$":0},"knx-server":{"$":0},"static-access":{"$":0},"cryptonomic":{"*":{"$":0}},"debian":{"$":0},"at-band-camp":{"$":0},"blogdns":{"$":0},"broke-it":{"$":0},"buyshouses":{"$":0},"dnsalias":{"$":0},"dnsdojo":{"$":0},"does-it":{"$":0},"dontexist":{"$":0},"dynalias":{"$":0},"dynathome":{"$":0},"endofinternet":{"$":0},"from-az":{"$":0},"from-co":{"$":0},"from-la":{"$":0},"from-ny":{"$":0},"gets-it":{"$":0},"ham-radio-op":{"$":0},"homeftp":{"$":0},"homeip":{"$":0},"homelinux":{"$":0},"homeunix":{"$":0},"in-the-band":{"$":0},"is-a-chef":{"$":0},"is-a-geek":{"$":0},"isa-geek":{"$":0},"kicks-ass":{"$":0},"office-on-the":{"$":0},"podzone":{"$":0},"scrapper-site":{"$":0},"selfip":{"$":0},"sells-it":{"$":0},"servebbs":{"$":0},"serveftp":{"$":0},"thruhere":{"$":0},"webhop":{"$":0},"definima":{"$":0},"casacam":{"$":0},"dynu":{"$":0},"dynv6":{"$":0},"twmail":{"$":0},"ru":{"$":0},"channelsdvr":{"$":0},"fastlylb":{"$":0,"map":{"$":0}},"fastly":{"freetls":{"$":0},"map":{"$":0},"prod":{"a":{"$":0},"global":{"$":0}},"ssl":{"a":{"$":0},"b":{"$":0},"global":{"$":0}}},"flynnhosting":{"$":0},"cloudfunctions":{"$":0},"moonscale":{"$":0},"ipifony":{"$":0},"barsy":{"$":0},"azurewebsites":{"$":0},"azure-mobile":{"$":0},"cloudapp":{"$":0},"eating-organic":{"$":0},"mydissent":{"$":0},"myeffect":{"$":0},"mymediapc":{"$":0},"mypsx":{"$":0},"mysecuritycamera":{"$":0},"nhlfan":{"$":0},"no-ip":{"$":0},"pgafan":{"$":0},"privatizehealthinsurance":{"$":0},"bounceme":{"$":0},"ddns":{"$":0},"redirectme":{"$":0},"serveblog":{"$":0},"serveminecraft":{"$":0},"sytes":{"$":0},"rackmaze":{"$":0},"firewall-gateway":{"$":0},"dsmynas":{"$":0},"familyds":{"$":0},"za":{"$":0}},"nf":{"$":0,"com":{"$":0},"net":{"$":0},"per":{"$":0},"rec":{"$":0},"web":{"$":0},"arts":{"$":0},"firm":{"$":0},"info":{"$":0},"other":{"$":0},"store":{"$":0}},"ng":{"$":0,"com":{"$":0,"blogspot":{"$":0}},"edu":{"$":0},"gov":{"$":0},"i":{"$":0},"mil":{"$":0},"mobi":{"$":0},"name":{"$":0},"net":{"$":0},"org":{"$":0},"sch":{"$":0}},"ni":{"$":0,"ac":{"$":0},"biz":{"$":0},"co":{"$":0},"com":{"$":0},"edu":{"$":0},"gob":{"$":0},"in":{"$":0},"info":{"$":0},"int":{"$":0},"mil":{"$":0},"net":{"$":0},"nom":{"$":0},"org":{"$":0},"web":{"$":0}},"nl":{"$":0,"bv":{"$":0},"virtueeldomein":{"$":0},"co":{"$":0},"hosting-cluster":{"$":0},"blogspot":{"$":0},"transurl":{"*":{"$":0}},"cistron":{"$":0},"demon":{"$":0}},"no":{"$":0,"fhs":{"$":0},"vgs":{"$":0},"fylkesbibl":{"$":0},"folkebibl":{"$":0},"museum":{"$":0},"idrett":{"$":0},"priv":{"$":0},"mil":{"$":0},"stat":{"$":0},"dep":{"$":0},"kommune":{"$":0},"herad":{"$":0},"aa":{"$":0,"gs":{"$":0}},"ah":{"$":0,"gs":{"$":0}},"bu":{"$":0,"gs":{"$":0}},"fm":{"$":0,"gs":{"$":0}},"hl":{"$":0,"gs":{"$":0}},"hm":{"$":0,"gs":{"$":0}},"jan-mayen":{"$":0,"gs":{"$":0}},"mr":{"$":0,"gs":{"$":0}},"nl":{"$":0,"gs":{"$":0}},"nt":{"$":0,"gs":{"$":0}},"of":{"$":0,"gs":{"$":0}},"ol":{"$":0,"gs":{"$":0}},"oslo":{"$":0,"gs":{"$":0}},"rl":{"$":0,"gs":{"$":0}},"sf":{"$":0,"gs":{"$":0}},"st":{"$":0,"gs":{"$":0}},"svalbard":{"$":0,"gs":{"$":0}},"tm":{"$":0,"gs":{"$":0}},"tr":{"$":0,"gs":{"$":0}},"va":{"$":0,"gs":{"$":0}},"vf":{"$":0,"gs":{"$":0}},"akrehamn":{"$":0},"xn--krehamn-dxa":{"$":0},"algard":{"$":0},"xn--lgrd-poac":{"$":0},"arna":{"$":0},"brumunddal":{"$":0},"bryne":{"$":0},"bronnoysund":{"$":0},"xn--brnnysund-m8ac":{"$":0},"drobak":{"$":0},"xn--drbak-wua":{"$":0},"egersund":{"$":0},"fetsund":{"$":0},"floro":{"$":0},"xn--flor-jra":{"$":0},"fredrikstad":{"$":0},"hokksund":{"$":0},"honefoss":{"$":0},"xn--hnefoss-q1a":{"$":0},"jessheim":{"$":0},"jorpeland":{"$":0},"xn--jrpeland-54a":{"$":0},"kirkenes":{"$":0},"kopervik":{"$":0},"krokstadelva":{"$":0},"langevag":{"$":0},"xn--langevg-jxa":{"$":0},"leirvik":{"$":0},"mjondalen":{"$":0},"xn--mjndalen-64a":{"$":0},"mo-i-rana":{"$":0},"mosjoen":{"$":0},"xn--mosjen-eya":{"$":0},"nesoddtangen":{"$":0},"orkanger":{"$":0},"osoyro":{"$":0},"xn--osyro-wua":{"$":0},"raholt":{"$":0},"xn--rholt-mra":{"$":0},"sandnessjoen":{"$":0},"xn--sandnessjen-ogb":{"$":0},"skedsmokorset":{"$":0},"slattum":{"$":0},"spjelkavik":{"$":0},"stathelle":{"$":0},"stavern":{"$":0},"stjordalshalsen":{"$":0},"xn--stjrdalshalsen-sqb":{"$":0},"tananger":{"$":0},"tranby":{"$":0},"vossevangen":{"$":0},"afjord":{"$":0},"xn--fjord-lra":{"$":0},"agdenes":{"$":0},"al":{"$":0},"xn--l-1fa":{"$":0},"alesund":{"$":0},"xn--lesund-hua":{"$":0},"alstahaug":{"$":0},"alta":{"$":0},"xn--lt-liac":{"$":0},"alaheadju":{"$":0},"xn--laheadju-7ya":{"$":0},"alvdal":{"$":0},"amli":{"$":0},"xn--mli-tla":{"$":0},"amot":{"$":0},"xn--mot-tla":{"$":0},"andebu":{"$":0},"andoy":{"$":0},"xn--andy-ira":{"$":0},"andasuolo":{"$":0},"ardal":{"$":0},"xn--rdal-poa":{"$":0},"aremark":{"$":0},"arendal":{"$":0},"xn--s-1fa":{"$":0},"aseral":{"$":0},"xn--seral-lra":{"$":0},"asker":{"$":0},"askim":{"$":0},"askvoll":{"$":0},"askoy":{"$":0},"xn--asky-ira":{"$":0},"asnes":{"$":0},"xn--snes-poa":{"$":0},"audnedaln":{"$":0},"aukra":{"$":0},"aure":{"$":0},"aurland":{"$":0},"aurskog-holand":{"$":0},"xn--aurskog-hland-jnb":{"$":0},"austevoll":{"$":0},"austrheim":{"$":0},"averoy":{"$":0},"xn--avery-yua":{"$":0},"balestrand":{"$":0},"ballangen":{"$":0},"balat":{"$":0},"xn--blt-elab":{"$":0},"balsfjord":{"$":0},"bahccavuotna":{"$":0},"xn--bhccavuotna-k7a":{"$":0},"bamble":{"$":0},"bardu":{"$":0},"beardu":{"$":0},"beiarn":{"$":0},"bajddar":{"$":0},"xn--bjddar-pta":{"$":0},"baidar":{"$":0},"xn--bidr-5nac":{"$":0},"berg":{"$":0},"bergen":{"$":0},"berlevag":{"$":0},"xn--berlevg-jxa":{"$":0},"bearalvahki":{"$":0},"xn--bearalvhki-y4a":{"$":0},"bindal":{"$":0},"birkenes":{"$":0},"bjarkoy":{"$":0},"xn--bjarky-fya":{"$":0},"bjerkreim":{"$":0},"bjugn":{"$":0},"bodo":{"$":0},"xn--bod-2na":{"$":0},"badaddja":{"$":0},"xn--bdddj-mrabd":{"$":0},"budejju":{"$":0},"bokn":{"$":0},"bremanger":{"$":0},"bronnoy":{"$":0},"xn--brnny-wuac":{"$":0},"bygland":{"$":0},"bykle":{"$":0},"barum":{"$":0},"xn--brum-voa":{"$":0},"telemark":{"bo":{"$":0},"xn--b-5ga":{"$":0}},"nordland":{"bo":{"$":0},"xn--b-5ga":{"$":0},"heroy":{"$":0},"xn--hery-ira":{"$":0}},"bievat":{"$":0},"xn--bievt-0qa":{"$":0},"bomlo":{"$":0},"xn--bmlo-gra":{"$":0},"batsfjord":{"$":0},"xn--btsfjord-9za":{"$":0},"bahcavuotna":{"$":0},"xn--bhcavuotna-s4a":{"$":0},"dovre":{"$":0},"drammen":{"$":0},"drangedal":{"$":0},"dyroy":{"$":0},"xn--dyry-ira":{"$":0},"donna":{"$":0},"xn--dnna-gra":{"$":0},"eid":{"$":0},"eidfjord":{"$":0},"eidsberg":{"$":0},"eidskog":{"$":0},"eidsvoll":{"$":0},"eigersund":{"$":0},"elverum":{"$":0},"enebakk":{"$":0},"engerdal":{"$":0},"etne":{"$":0},"etnedal":{"$":0},"evenes":{"$":0},"evenassi":{"$":0},"xn--eveni-0qa01ga":{"$":0},"evje-og-hornnes":{"$":0},"farsund":{"$":0},"fauske":{"$":0},"fuossko":{"$":0},"fuoisku":{"$":0},"fedje":{"$":0},"fet":{"$":0},"finnoy":{"$":0},"xn--finny-yua":{"$":0},"fitjar":{"$":0},"fjaler":{"$":0},"fjell":{"$":0},"flakstad":{"$":0},"flatanger":{"$":0},"flekkefjord":{"$":0},"flesberg":{"$":0},"flora":{"$":0},"fla":{"$":0},"xn--fl-zia":{"$":0},"folldal":{"$":0},"forsand":{"$":0},"fosnes":{"$":0},"frei":{"$":0},"frogn":{"$":0},"froland":{"$":0},"frosta":{"$":0},"frana":{"$":0},"xn--frna-woa":{"$":0},"froya":{"$":0},"xn--frya-hra":{"$":0},"fusa":{"$":0},"fyresdal":{"$":0},"forde":{"$":0},"xn--frde-gra":{"$":0},"gamvik":{"$":0},"gangaviika":{"$":0},"xn--ggaviika-8ya47h":{"$":0},"gaular":{"$":0},"gausdal":{"$":0},"gildeskal":{"$":0},"xn--gildeskl-g0a":{"$":0},"giske":{"$":0},"gjemnes":{"$":0},"gjerdrum":{"$":0},"gjerstad":{"$":0},"gjesdal":{"$":0},"gjovik":{"$":0},"xn--gjvik-wua":{"$":0},"gloppen":{"$":0},"gol":{"$":0},"gran":{"$":0},"grane":{"$":0},"granvin":{"$":0},"gratangen":{"$":0},"grimstad":{"$":0},"grong":{"$":0},"kraanghke":{"$":0},"xn--kranghke-b0a":{"$":0},"grue":{"$":0},"gulen":{"$":0},"hadsel":{"$":0},"halden":{"$":0},"halsa":{"$":0},"hamar":{"$":0},"hamaroy":{"$":0},"habmer":{"$":0},"xn--hbmer-xqa":{"$":0},"hapmir":{"$":0},"xn--hpmir-xqa":{"$":0},"hammerfest":{"$":0},"hammarfeasta":{"$":0},"xn--hmmrfeasta-s4ac":{"$":0},"haram":{"$":0},"hareid":{"$":0},"harstad":{"$":0},"hasvik":{"$":0},"aknoluokta":{"$":0},"xn--koluokta-7ya57h":{"$":0},"hattfjelldal":{"$":0},"aarborte":{"$":0},"haugesund":{"$":0},"hemne":{"$":0},"hemnes":{"$":0},"hemsedal":{"$":0},"more-og-romsdal":{"heroy":{"$":0},"sande":{"$":0}},"xn--mre-og-romsdal-qqb":{"xn--hery-ira":{"$":0},"sande":{"$":0}},"hitra":{"$":0},"hjartdal":{"$":0},"hjelmeland":{"$":0},"hobol":{"$":0},"xn--hobl-ira":{"$":0},"hof":{"$":0},"hol":{"$":0},"hole":{"$":0},"holmestrand":{"$":0},"holtalen":{"$":0},"xn--holtlen-hxa":{"$":0},"hornindal":{"$":0},"horten":{"$":0},"hurdal":{"$":0},"hurum":{"$":0},"hvaler":{"$":0},"hyllestad":{"$":0},"hagebostad":{"$":0},"xn--hgebostad-g3a":{"$":0},"hoyanger":{"$":0},"xn--hyanger-q1a":{"$":0},"hoylandet":{"$":0},"xn--hylandet-54a":{"$":0},"ha":{"$":0},"xn--h-2fa":{"$":0},"ibestad":{"$":0},"inderoy":{"$":0},"xn--indery-fya":{"$":0},"iveland":{"$":0},"jevnaker":{"$":0},"jondal":{"$":0},"jolster":{"$":0},"xn--jlster-bya":{"$":0},"karasjok":{"$":0},"karasjohka":{"$":0},"xn--krjohka-hwab49j":{"$":0},"karlsoy":{"$":0},"galsa":{"$":0},"xn--gls-elac":{"$":0},"karmoy":{"$":0},"xn--karmy-yua":{"$":0},"kautokeino":{"$":0},"guovdageaidnu":{"$":0},"klepp":{"$":0},"klabu":{"$":0},"xn--klbu-woa":{"$":0},"kongsberg":{"$":0},"kongsvinger":{"$":0},"kragero":{"$":0},"xn--krager-gya":{"$":0},"kristiansand":{"$":0},"kristiansund":{"$":0},"krodsherad":{"$":0},"xn--krdsherad-m8a":{"$":0},"kvalsund":{"$":0},"rahkkeravju":{"$":0},"xn--rhkkervju-01af":{"$":0},"kvam":{"$":0},"kvinesdal":{"$":0},"kvinnherad":{"$":0},"kviteseid":{"$":0},"kvitsoy":{"$":0},"xn--kvitsy-fya":{"$":0},"kvafjord":{"$":0},"xn--kvfjord-nxa":{"$":0},"giehtavuoatna":{"$":0},"kvanangen":{"$":0},"xn--kvnangen-k0a":{"$":0},"navuotna":{"$":0},"xn--nvuotna-hwa":{"$":0},"kafjord":{"$":0},"xn--kfjord-iua":{"$":0},"gaivuotna":{"$":0},"xn--givuotna-8ya":{"$":0},"larvik":{"$":0},"lavangen":{"$":0},"lavagis":{"$":0},"loabat":{"$":0},"xn--loabt-0qa":{"$":0},"lebesby":{"$":0},"davvesiida":{"$":0},"leikanger":{"$":0},"leirfjord":{"$":0},"leka":{"$":0},"leksvik":{"$":0},"lenvik":{"$":0},"leangaviika":{"$":0},"xn--leagaviika-52b":{"$":0},"lesja":{"$":0},"levanger":{"$":0},"lier":{"$":0},"lierne":{"$":0},"lillehammer":{"$":0},"lillesand":{"$":0},"lindesnes":{"$":0},"lindas":{"$":0},"xn--linds-pra":{"$":0},"lom":{"$":0},"loppa":{"$":0},"lahppi":{"$":0},"xn--lhppi-xqa":{"$":0},"lund":{"$":0},"lunner":{"$":0},"luroy":{"$":0},"xn--lury-ira":{"$":0},"luster":{"$":0},"lyngdal":{"$":0},"lyngen":{"$":0},"ivgu":{"$":0},"lardal":{"$":0},"lerdal":{"$":0},"xn--lrdal-sra":{"$":0},"lodingen":{"$":0},"xn--ldingen-q1a":{"$":0},"lorenskog":{"$":0},"xn--lrenskog-54a":{"$":0},"loten":{"$":0},"xn--lten-gra":{"$":0},"malvik":{"$":0},"masoy":{"$":0},"xn--msy-ula0h":{"$":0},"muosat":{"$":0},"xn--muost-0qa":{"$":0},"mandal":{"$":0},"marker":{"$":0},"marnardal":{"$":0},"masfjorden":{"$":0},"meland":{"$":0},"meldal":{"$":0},"melhus":{"$":0},"meloy":{"$":0},"xn--mely-ira":{"$":0},"meraker":{"$":0},"xn--merker-kua":{"$":0},"moareke":{"$":0},"xn--moreke-jua":{"$":0},"midsund":{"$":0},"midtre-gauldal":{"$":0},"modalen":{"$":0},"modum":{"$":0},"molde":{"$":0},"moskenes":{"$":0},"moss":{"$":0},"mosvik":{"$":0},"malselv":{"$":0},"xn--mlselv-iua":{"$":0},"malatvuopmi":{"$":0},"xn--mlatvuopmi-s4a":{"$":0},"namdalseid":{"$":0},"aejrie":{"$":0},"namsos":{"$":0},"namsskogan":{"$":0},"naamesjevuemie":{"$":0},"xn--nmesjevuemie-tcba":{"$":0},"laakesvuemie":{"$":0},"nannestad":{"$":0},"narvik":{"$":0},"narviika":{"$":0},"naustdal":{"$":0},"nedre-eiker":{"$":0},"akershus":{"nes":{"$":0}},"buskerud":{"nes":{"$":0}},"nesna":{"$":0},"nesodden":{"$":0},"nesseby":{"$":0},"unjarga":{"$":0},"xn--unjrga-rta":{"$":0},"nesset":{"$":0},"nissedal":{"$":0},"nittedal":{"$":0},"nord-aurdal":{"$":0},"nord-fron":{"$":0},"nord-odal":{"$":0},"norddal":{"$":0},"nordkapp":{"$":0},"davvenjarga":{"$":0},"xn--davvenjrga-y4a":{"$":0},"nordre-land":{"$":0},"nordreisa":{"$":0},"raisa":{"$":0},"xn--risa-5na":{"$":0},"nore-og-uvdal":{"$":0},"notodden":{"$":0},"naroy":{"$":0},"xn--nry-yla5g":{"$":0},"notteroy":{"$":0},"xn--nttery-byae":{"$":0},"odda":{"$":0},"oksnes":{"$":0},"xn--ksnes-uua":{"$":0},"oppdal":{"$":0},"oppegard":{"$":0},"xn--oppegrd-ixa":{"$":0},"orkdal":{"$":0},"orland":{"$":0},"xn--rland-uua":{"$":0},"orskog":{"$":0},"xn--rskog-uua":{"$":0},"orsta":{"$":0},"xn--rsta-fra":{"$":0},"hedmark":{"os":{"$":0},"valer":{"$":0},"xn--vler-qoa":{"$":0}},"hordaland":{"os":{"$":0}},"osen":{"$":0},"osteroy":{"$":0},"xn--ostery-fya":{"$":0},"ostre-toten":{"$":0},"xn--stre-toten-zcb":{"$":0},"overhalla":{"$":0},"ovre-eiker":{"$":0},"xn--vre-eiker-k8a":{"$":0},"oyer":{"$":0},"xn--yer-zna":{"$":0},"oygarden":{"$":0},"xn--ygarden-p1a":{"$":0},"oystre-slidre":{"$":0},"xn--ystre-slidre-ujb":{"$":0},"porsanger":{"$":0},"porsangu":{"$":0},"xn--porsgu-sta26f":{"$":0},"porsgrunn":{"$":0},"radoy":{"$":0},"xn--rady-ira":{"$":0},"rakkestad":{"$":0},"rana":{"$":0},"ruovat":{"$":0},"randaberg":{"$":0},"rauma":{"$":0},"rendalen":{"$":0},"rennebu":{"$":0},"rennesoy":{"$":0},"xn--rennesy-v1a":{"$":0},"rindal":{"$":0},"ringebu":{"$":0},"ringerike":{"$":0},"ringsaker":{"$":0},"rissa":{"$":0},"risor":{"$":0},"xn--risr-ira":{"$":0},"roan":{"$":0},"rollag":{"$":0},"rygge":{"$":0},"ralingen":{"$":0},"xn--rlingen-mxa":{"$":0},"rodoy":{"$":0},"xn--rdy-0nab":{"$":0},"romskog":{"$":0},"xn--rmskog-bya":{"$":0},"roros":{"$":0},"xn--rros-gra":{"$":0},"rost":{"$":0},"xn--rst-0na":{"$":0},"royken":{"$":0},"xn--ryken-vua":{"$":0},"royrvik":{"$":0},"xn--ryrvik-bya":{"$":0},"rade":{"$":0},"xn--rde-ula":{"$":0},"salangen":{"$":0},"siellak":{"$":0},"saltdal":{"$":0},"salat":{"$":0},"xn--slt-elab":{"$":0},"xn--slat-5na":{"$":0},"samnanger":{"$":0},"vestfold":{"sande":{"$":0}},"sandefjord":{"$":0},"sandnes":{"$":0},"sandoy":{"$":0},"xn--sandy-yua":{"$":0},"sarpsborg":{"$":0},"sauda":{"$":0},"sauherad":{"$":0},"sel":{"$":0},"selbu":{"$":0},"selje":{"$":0},"seljord":{"$":0},"sigdal":{"$":0},"siljan":{"$":0},"sirdal":{"$":0},"skaun":{"$":0},"skedsmo":{"$":0},"ski":{"$":0},"skien":{"$":0},"skiptvet":{"$":0},"skjervoy":{"$":0},"xn--skjervy-v1a":{"$":0},"skierva":{"$":0},"xn--skierv-uta":{"$":0},"skjak":{"$":0},"xn--skjk-soa":{"$":0},"skodje":{"$":0},"skanland":{"$":0},"xn--sknland-fxa":{"$":0},"skanit":{"$":0},"xn--sknit-yqa":{"$":0},"smola":{"$":0},"xn--smla-hra":{"$":0},"snillfjord":{"$":0},"snasa":{"$":0},"xn--snsa-roa":{"$":0},"snoasa":{"$":0},"snaase":{"$":0},"xn--snase-nra":{"$":0},"sogndal":{"$":0},"sokndal":{"$":0},"sola":{"$":0},"solund":{"$":0},"songdalen":{"$":0},"sortland":{"$":0},"spydeberg":{"$":0},"stange":{"$":0},"stavanger":{"$":0},"steigen":{"$":0},"steinkjer":{"$":0},"stjordal":{"$":0},"xn--stjrdal-s1a":{"$":0},"stokke":{"$":0},"stor-elvdal":{"$":0},"stord":{"$":0},"stordal":{"$":0},"storfjord":{"$":0},"omasvuotna":{"$":0},"strand":{"$":0},"stranda":{"$":0},"stryn":{"$":0},"sula":{"$":0},"suldal":{"$":0},"sund":{"$":0},"sunndal":{"$":0},"surnadal":{"$":0},"sveio":{"$":0},"svelvik":{"$":0},"sykkylven":{"$":0},"sogne":{"$":0},"xn--sgne-gra":{"$":0},"somna":{"$":0},"xn--smna-gra":{"$":0},"sondre-land":{"$":0},"xn--sndre-land-0cb":{"$":0},"sor-aurdal":{"$":0},"xn--sr-aurdal-l8a":{"$":0},"sor-fron":{"$":0},"xn--sr-fron-q1a":{"$":0},"sor-odal":{"$":0},"xn--sr-odal-q1a":{"$":0},"sor-varanger":{"$":0},"xn--sr-varanger-ggb":{"$":0},"matta-varjjat":{"$":0},"xn--mtta-vrjjat-k7af":{"$":0},"sorfold":{"$":0},"xn--srfold-bya":{"$":0},"sorreisa":{"$":0},"xn--srreisa-q1a":{"$":0},"sorum":{"$":0},"xn--srum-gra":{"$":0},"tana":{"$":0},"deatnu":{"$":0},"time":{"$":0},"tingvoll":{"$":0},"tinn":{"$":0},"tjeldsund":{"$":0},"dielddanuorri":{"$":0},"tjome":{"$":0},"xn--tjme-hra":{"$":0},"tokke":{"$":0},"tolga":{"$":0},"torsken":{"$":0},"tranoy":{"$":0},"xn--trany-yua":{"$":0},"tromso":{"$":0},"xn--troms-zua":{"$":0},"tromsa":{"$":0},"romsa":{"$":0},"trondheim":{"$":0},"troandin":{"$":0},"trysil":{"$":0},"trana":{"$":0},"xn--trna-woa":{"$":0},"trogstad":{"$":0},"xn--trgstad-r1a":{"$":0},"tvedestrand":{"$":0},"tydal":{"$":0},"tynset":{"$":0},"tysfjord":{"$":0},"divtasvuodna":{"$":0},"divttasvuotna":{"$":0},"tysnes":{"$":0},"tysvar":{"$":0},"xn--tysvr-vra":{"$":0},"tonsberg":{"$":0},"xn--tnsberg-q1a":{"$":0},"ullensaker":{"$":0},"ullensvang":{"$":0},"ulvik":{"$":0},"utsira":{"$":0},"vadso":{"$":0},"xn--vads-jra":{"$":0},"cahcesuolo":{"$":0},"xn--hcesuolo-7ya35b":{"$":0},"vaksdal":{"$":0},"valle":{"$":0},"vang":{"$":0},"vanylven":{"$":0},"vardo":{"$":0},"xn--vard-jra":{"$":0},"varggat":{"$":0},"xn--vrggt-xqad":{"$":0},"vefsn":{"$":0},"vaapste":{"$":0},"vega":{"$":0},"vegarshei":{"$":0},"xn--vegrshei-c0a":{"$":0},"vennesla":{"$":0},"verdal":{"$":0},"verran":{"$":0},"vestby":{"$":0},"vestnes":{"$":0},"vestre-slidre":{"$":0},"vestre-toten":{"$":0},"vestvagoy":{"$":0},"xn--vestvgy-ixa6o":{"$":0},"vevelstad":{"$":0},"vik":{"$":0},"vikna":{"$":0},"vindafjord":{"$":0},"volda":{"$":0},"voss":{"$":0},"varoy":{"$":0},"xn--vry-yla5g":{"$":0},"vagan":{"$":0},"xn--vgan-qoa":{"$":0},"voagat":{"$":0},"vagsoy":{"$":0},"xn--vgsy-qoa0j":{"$":0},"vaga":{"$":0},"xn--vg-yiab":{"$":0},"ostfold":{"valer":{"$":0}},"xn--stfold-9xa":{"xn--vler-qoa":{"$":0}},"co":{"$":0},"blogspot":{"$":0}},"np":{"*":{"$":0}},"nr":{"$":0,"biz":{"$":0},"info":{"$":0},"gov":{"$":0},"edu":{"$":0},"org":{"$":0},"net":{"$":0},"com":{"$":0}},"nu":{"$":0,"merseine":{"$":0},"mine":{"$":0},"shacknet":{"$":0},"nom":{"$":0}},"nz":{"$":0,"ac":{"$":0},"co":{"$":0,"blogspot":{"$":0}},"cri":{"$":0},"geek":{"$":0},"gen":{"$":0},"govt":{"$":0},"health":{"$":0},"iwi":{"$":0},"kiwi":{"$":0},"maori":{"$":0},"mil":{"$":0},"xn--mori-qsa":{"$":0},"net":{"$":0},"org":{"$":0},"parliament":{"$":0},"school":{"$":0},"nym":{"$":0}},"om":{"$":0,"co":{"$":0},"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"med":{"$":0},"museum":{"$":0},"net":{"$":0},"org":{"$":0},"pro":{"$":0}},"onion":{"$":0},"org":{"$":0,"amune":{"tele":{"$":0}},"pimienta":{"$":0},"poivron":{"$":0},"potager":{"$":0},"sweetpepper":{"$":0},"ae":{"$":0},"us":{"$":0},"certmgr":{"$":0},"cdn77":{"c":{"$":0},"rsc":{"$":0}},"cdn77-secure":{"origin":{"ssl":{"$":0}}},"cloudns":{"$":0},"duckdns":{"$":0},"tunk":{"$":0},"dyndns":{"$":0,"go":{"$":0},"home":{"$":0}},"blogdns":{"$":0},"blogsite":{"$":0},"boldlygoingnowhere":{"$":0},"dnsalias":{"$":0},"dnsdojo":{"$":0},"doesntexist":{"$":0},"dontexist":{"$":0},"doomdns":{"$":0},"dvrdns":{"$":0},"dynalias":{"$":0},"endofinternet":{"$":0},"endoftheinternet":{"$":0},"from-me":{"$":0},"game-host":{"$":0},"gotdns":{"$":0},"hobby-site":{"$":0},"homedns":{"$":0},"homeftp":{"$":0},"homelinux":{"$":0},"homeunix":{"$":0},"is-a-bruinsfan":{"$":0},"is-a-candidate":{"$":0},"is-a-celticsfan":{"$":0},"is-a-chef":{"$":0},"is-a-geek":{"$":0},"is-a-knight":{"$":0},"is-a-linux-user":{"$":0},"is-a-patsfan":{"$":0},"is-a-soxfan":{"$":0},"is-found":{"$":0},"is-lost":{"$":0},"is-saved":{"$":0},"is-very-bad":{"$":0},"is-very-evil":{"$":0},"is-very-good":{"$":0},"is-very-nice":{"$":0},"is-very-sweet":{"$":0},"isa-geek":{"$":0},"kicks-ass":{"$":0},"misconfused":{"$":0},"podzone":{"$":0},"readmyblog":{"$":0},"selfip":{"$":0},"sellsyourhome":{"$":0},"servebbs":{"$":0},"serveftp":{"$":0},"servegame":{"$":0},"stuff-4-sale":{"$":0},"webhop":{"$":0},"ddnss":{"$":0},"accesscam":{"$":0},"camdvr":{"$":0},"freeddns":{"$":0},"mywire":{"$":0},"webredirect":{"$":0},"eu":{"$":0,"al":{"$":0},"asso":{"$":0},"at":{"$":0},"au":{"$":0},"be":{"$":0},"bg":{"$":0},"ca":{"$":0},"cd":{"$":0},"ch":{"$":0},"cn":{"$":0},"cy":{"$":0},"cz":{"$":0},"de":{"$":0},"dk":{"$":0},"edu":{"$":0},"ee":{"$":0},"es":{"$":0},"fi":{"$":0},"fr":{"$":0},"gr":{"$":0},"hr":{"$":0},"hu":{"$":0},"ie":{"$":0},"il":{"$":0},"in":{"$":0},"int":{"$":0},"is":{"$":0},"it":{"$":0},"jp":{"$":0},"kr":{"$":0},"lt":{"$":0},"lu":{"$":0},"lv":{"$":0},"mc":{"$":0},"me":{"$":0},"mk":{"$":0},"mt":{"$":0},"my":{"$":0},"net":{"$":0},"ng":{"$":0},"nl":{"$":0},"no":{"$":0},"nz":{"$":0},"paris":{"$":0},"pl":{"$":0},"pt":{"$":0},"q-a":{"$":0},"ro":{"$":0},"ru":{"$":0},"se":{"$":0},"si":{"$":0},"sk":{"$":0},"tr":{"$":0},"uk":{"$":0},"us":{"$":0}},"twmail":{"$":0},"fedorainfracloud":{"$":0},"fedorapeople":{"$":0},"fedoraproject":{"cloud":{"$":0},"os":{"app":{"$":0}},"stg":{"os":{"app":{"$":0}}}},"hepforge":{"$":0},"js":{"$":0},"bmoattachments":{"$":0},"cable-modem":{"$":0},"collegefan":{"$":0},"couchpotatofries":{"$":0},"mlbfan":{"$":0},"mysecuritycamera":{"$":0},"nflfan":{"$":0},"read-books":{"$":0},"ufcfan":{"$":0},"hopto":{"$":0},"myftp":{"$":0},"no-ip":{"$":0},"zapto":{"$":0},"my-firewall":{"$":0},"myfirewall":{"$":0},"spdns":{"$":0},"dsmynas":{"$":0},"familyds":{"$":0},"tuxfamily":{"$":0},"diskstation":{"$":0},"hk":{"$":0},"wmflabs":{"$":0},"za":{"$":0}},"pa":{"$":0,"ac":{"$":0},"gob":{"$":0},"com":{"$":0},"org":{"$":0},"sld":{"$":0},"edu":{"$":0},"net":{"$":0},"ing":{"$":0},"abo":{"$":0},"med":{"$":0},"nom":{"$":0}},"pe":{"$":0,"edu":{"$":0},"gob":{"$":0},"nom":{"$":0},"mil":{"$":0},"org":{"$":0},"com":{"$":0},"net":{"$":0},"blogspot":{"$":0},"nym":{"$":0}},"pf":{"$":0,"com":{"$":0},"org":{"$":0},"edu":{"$":0}},"pg":{"*":{"$":0}},"ph":{"$":0,"com":{"$":0},"net":{"$":0},"org":{"$":0},"gov":{"$":0},"edu":{"$":0},"ngo":{"$":0},"mil":{"$":0},"i":{"$":0}},"pk":{"$":0,"com":{"$":0},"net":{"$":0},"edu":{"$":0},"org":{"$":0},"fam":{"$":0},"biz":{"$":0},"web":{"$":0},"gov":{"$":0},"gob":{"$":0},"gok":{"$":0},"gon":{"$":0},"gop":{"$":0},"gos":{"$":0},"info":{"$":0}},"pl":{"$":0,"com":{"$":0},"net":{"$":0},"org":{"$":0},"aid":{"$":0},"agro":{"$":0},"atm":{"$":0},"auto":{"$":0},"biz":{"$":0},"edu":{"$":0},"gmina":{"$":0},"gsm":{"$":0},"info":{"$":0},"mail":{"$":0},"miasta":{"$":0},"media":{"$":0},"mil":{"$":0},"nieruchomosci":{"$":0},"nom":{"$":0},"pc":{"$":0},"powiat":{"$":0},"priv":{"$":0},"realestate":{"$":0},"rel":{"$":0},"sex":{"$":0},"shop":{"$":0},"sklep":{"$":0},"sos":{"$":0},"szkola":{"$":0},"targi":{"$":0},"tm":{"$":0},"tourism":{"$":0},"travel":{"$":0},"turystyka":{"$":0},"gov":{"$":0,"ap":{"$":0},"ic":{"$":0},"is":{"$":0},"us":{"$":0},"kmpsp":{"$":0},"kppsp":{"$":0},"kwpsp":{"$":0},"psp":{"$":0},"wskr":{"$":0},"kwp":{"$":0},"mw":{"$":0},"ug":{"$":0},"um":{"$":0},"umig":{"$":0},"ugim":{"$":0},"upow":{"$":0},"uw":{"$":0},"starostwo":{"$":0},"pa":{"$":0},"po":{"$":0},"psse":{"$":0},"pup":{"$":0},"rzgw":{"$":0},"sa":{"$":0},"so":{"$":0},"sr":{"$":0},"wsa":{"$":0},"sko":{"$":0},"uzs":{"$":0},"wiih":{"$":0},"winb":{"$":0},"pinb":{"$":0},"wios":{"$":0},"witd":{"$":0},"wzmiuw":{"$":0},"piw":{"$":0},"wiw":{"$":0},"griw":{"$":0},"wif":{"$":0},"oum":{"$":0},"sdn":{"$":0},"zp":{"$":0},"uppo":{"$":0},"mup":{"$":0},"wuoz":{"$":0},"konsulat":{"$":0},"oirm":{"$":0}},"augustow":{"$":0},"babia-gora":{"$":0},"bedzin":{"$":0},"beskidy":{"$":0},"bialowieza":{"$":0},"bialystok":{"$":0},"bielawa":{"$":0},"bieszczady":{"$":0},"boleslawiec":{"$":0},"bydgoszcz":{"$":0},"bytom":{"$":0},"cieszyn":{"$":0},"czeladz":{"$":0},"czest":{"$":0},"dlugoleka":{"$":0},"elblag":{"$":0},"elk":{"$":0},"glogow":{"$":0},"gniezno":{"$":0},"gorlice":{"$":0},"grajewo":{"$":0},"ilawa":{"$":0},"jaworzno":{"$":0},"jelenia-gora":{"$":0},"jgora":{"$":0},"kalisz":{"$":0},"kazimierz-dolny":{"$":0},"karpacz":{"$":0},"kartuzy":{"$":0},"kaszuby":{"$":0},"katowice":{"$":0},"kepno":{"$":0},"ketrzyn":{"$":0},"klodzko":{"$":0},"kobierzyce":{"$":0},"kolobrzeg":{"$":0},"konin":{"$":0},"konskowola":{"$":0},"kutno":{"$":0},"lapy":{"$":0},"lebork":{"$":0},"legnica":{"$":0},"lezajsk":{"$":0},"limanowa":{"$":0},"lomza":{"$":0},"lowicz":{"$":0},"lubin":{"$":0},"lukow":{"$":0},"malbork":{"$":0},"malopolska":{"$":0},"mazowsze":{"$":0},"mazury":{"$":0},"mielec":{"$":0},"mielno":{"$":0},"mragowo":{"$":0},"naklo":{"$":0},"nowaruda":{"$":0},"nysa":{"$":0},"olawa":{"$":0},"olecko":{"$":0},"olkusz":{"$":0},"olsztyn":{"$":0},"opoczno":{"$":0},"opole":{"$":0},"ostroda":{"$":0},"ostroleka":{"$":0},"ostrowiec":{"$":0},"ostrowwlkp":{"$":0},"pila":{"$":0},"pisz":{"$":0},"podhale":{"$":0},"podlasie":{"$":0},"polkowice":{"$":0},"pomorze":{"$":0},"pomorskie":{"$":0},"prochowice":{"$":0},"pruszkow":{"$":0},"przeworsk":{"$":0},"pulawy":{"$":0},"radom":{"$":0},"rawa-maz":{"$":0},"rybnik":{"$":0},"rzeszow":{"$":0},"sanok":{"$":0},"sejny":{"$":0},"slask":{"$":0},"slupsk":{"$":0},"sosnowiec":{"$":0},"stalowa-wola":{"$":0},"skoczow":{"$":0},"starachowice":{"$":0},"stargard":{"$":0},"suwalki":{"$":0},"swidnica":{"$":0},"swiebodzin":{"$":0},"swinoujscie":{"$":0},"szczecin":{"$":0},"szczytno":{"$":0},"tarnobrzeg":{"$":0},"tgory":{"$":0},"turek":{"$":0},"tychy":{"$":0},"ustka":{"$":0},"walbrzych":{"$":0},"warmia":{"$":0},"warszawa":{"$":0},"waw":{"$":0},"wegrow":{"$":0},"wielun":{"$":0},"wlocl":{"$":0},"wloclawek":{"$":0},"wodzislaw":{"$":0},"wolomin":{"$":0},"wroclaw":{"$":0},"zachpomor":{"$":0},"zagan":{"$":0},"zarow":{"$":0},"zgora":{"$":0},"zgorzelec":{"$":0},"beep":{"$":0},"co":{"$":0},"art":{"$":0},"gliwice":{"$":0},"krakow":{"$":0},"poznan":{"$":0},"wroc":{"$":0},"zakopane":{"$":0},"gda":{"$":0},"gdansk":{"$":0},"gdynia":{"$":0},"med":{"$":0},"sopot":{"$":0}},"pm":{"$":0},"pn":{"$":0,"gov":{"$":0},"co":{"$":0},"org":{"$":0},"edu":{"$":0},"net":{"$":0}},"post":{"$":0},"pr":{"$":0,"com":{"$":0},"net":{"$":0},"org":{"$":0},"gov":{"$":0},"edu":{"$":0},"isla":{"$":0},"pro":{"$":0},"biz":{"$":0},"info":{"$":0},"name":{"$":0},"est":{"$":0},"prof":{"$":0},"ac":{"$":0}},"pro":{"$":0,"aaa":{"$":0},"aca":{"$":0},"acct":{"$":0},"avocat":{"$":0},"bar":{"$":0},"cpa":{"$":0},"eng":{"$":0},"jur":{"$":0},"law":{"$":0},"med":{"$":0},"recht":{"$":0},"cloudns":{"$":0}},"ps":{"$":0,"edu":{"$":0},"gov":{"$":0},"sec":{"$":0},"plo":{"$":0},"com":{"$":0},"org":{"$":0},"net":{"$":0}},"pt":{"$":0,"net":{"$":0},"gov":{"$":0},"org":{"$":0},"edu":{"$":0},"int":{"$":0},"publ":{"$":0},"com":{"$":0},"nome":{"$":0},"blogspot":{"$":0},"nym":{"$":0}},"pw":{"$":0,"co":{"$":0},"ne":{"$":0},"or":{"$":0},"ed":{"$":0},"go":{"$":0},"belau":{"$":0},"cloudns":{"$":0},"nom":{"$":0}},"py":{"$":0,"com":{"$":0},"coop":{"$":0},"edu":{"$":0},"gov":{"$":0},"mil":{"$":0},"net":{"$":0},"org":{"$":0}},"qa":{"$":0,"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"mil":{"$":0},"name":{"$":0},"net":{"$":0},"org":{"$":0},"sch":{"$":0},"blogspot":{"$":0},"nom":{"$":0}},"re":{"$":0,"asso":{"$":0},"com":{"$":0},"nom":{"$":0},"blogspot":{"$":0}},"ro":{"$":0,"arts":{"$":0},"com":{"$":0},"firm":{"$":0},"info":{"$":0},"nom":{"$":0},"nt":{"$":0},"org":{"$":0},"rec":{"$":0},"store":{"$":0},"tm":{"$":0},"www":{"$":0},"shop":{"$":0},"blogspot":{"$":0}},"rs":{"$":0,"ac":{"$":0},"co":{"$":0},"edu":{"$":0},"gov":{"$":0},"in":{"$":0},"org":{"$":0},"blogspot":{"$":0},"nom":{"$":0}},"ru":{"$":0,"ac":{"$":0},"edu":{"$":0},"gov":{"$":0},"int":{"$":0},"mil":{"$":0},"test":{"$":0},"adygeya":{"$":0},"bashkiria":{"$":0},"bir":{"$":0},"cbg":{"$":0},"com":{"$":0},"dagestan":{"$":0},"grozny":{"$":0},"kalmykia":{"$":0},"kustanai":{"$":0},"marine":{"$":0},"mordovia":{"$":0},"msk":{"$":0},"mytis":{"$":0},"nalchik":{"$":0},"nov":{"$":0},"pyatigorsk":{"$":0},"spb":{"$":0},"vladikavkaz":{"$":0},"vladimir":{"$":0},"blogspot":{"$":0},"cldmail":{"hb":{"$":0}},"net":{"$":0},"org":{"$":0},"pp":{"$":0}},"rw":{"$":0,"gov":{"$":0},"net":{"$":0},"edu":{"$":0},"ac":{"$":0},"com":{"$":0},"co":{"$":0},"int":{"$":0},"mil":{"$":0},"gouv":{"$":0}},"sa":{"$":0,"com":{"$":0},"net":{"$":0},"org":{"$":0},"gov":{"$":0},"med":{"$":0},"pub":{"$":0},"edu":{"$":0},"sch":{"$":0}},"sb":{"$":0,"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"net":{"$":0},"org":{"$":0}},"sc":{"$":0,"com":{"$":0},"gov":{"$":0},"net":{"$":0},"org":{"$":0},"edu":{"$":0}},"sd":{"$":0,"com":{"$":0},"net":{"$":0},"org":{"$":0},"edu":{"$":0},"med":{"$":0},"tv":{"$":0},"gov":{"$":0},"info":{"$":0}},"se":{"$":0,"a":{"$":0},"ac":{"$":0},"b":{"$":0},"bd":{"$":0},"brand":{"$":0},"c":{"$":0},"d":{"$":0},"e":{"$":0},"f":{"$":0},"fh":{"$":0},"fhsk":{"$":0},"fhv":{"$":0},"g":{"$":0},"h":{"$":0},"i":{"$":0},"k":{"$":0},"komforb":{"$":0},"kommunalforbund":{"$":0},"komvux":{"$":0},"l":{"$":0},"lanbib":{"$":0},"m":{"$":0},"n":{"$":0},"naturbruksgymn":{"$":0},"o":{"$":0},"org":{"$":0},"p":{"$":0},"parti":{"$":0},"pp":{"$":0},"press":{"$":0},"r":{"$":0},"s":{"$":0},"t":{"$":0},"tm":{"$":0},"u":{"$":0},"w":{"$":0},"x":{"$":0},"y":{"$":0},"z":{"$":0},"com":{"$":0},"blogspot":{"$":0}},"sg":{"$":0,"com":{"$":0},"net":{"$":0},"org":{"$":0},"gov":{"$":0},"edu":{"$":0},"per":{"$":0},"blogspot":{"$":0}},"sh":{"$":0,"com":{"$":0},"net":{"$":0},"gov":{"$":0},"org":{"$":0},"mil":{"$":0},"hashbang":{"$":0},"platform":{"*":{"$":0}},"wedeploy":{"$":0},"now":{"$":0}},"si":{"$":0,"blogspot":{"$":0},"nom":{"$":0}},"sj":{"$":0},"sk":{"$":0,"blogspot":{"$":0},"nym":{"$":0}},"sl":{"$":0,"com":{"$":0},"net":{"$":0},"edu":{"$":0},"gov":{"$":0},"org":{"$":0}},"sm":{"$":0},"sn":{"$":0,"art":{"$":0},"com":{"$":0},"edu":{"$":0},"gouv":{"$":0},"org":{"$":0},"perso":{"$":0},"univ":{"$":0},"blogspot":{"$":0}},"so":{"$":0,"com":{"$":0},"net":{"$":0},"org":{"$":0}},"sr":{"$":0},"st":{"$":0,"co":{"$":0},"com":{"$":0},"consulado":{"$":0},"edu":{"$":0},"embaixada":{"$":0},"gov":{"$":0},"mil":{"$":0},"net":{"$":0},"org":{"$":0},"principe":{"$":0},"saotome":{"$":0},"store":{"$":0}},"su":{"$":0,"abkhazia":{"$":0},"adygeya":{"$":0},"aktyubinsk":{"$":0},"arkhangelsk":{"$":0},"armenia":{"$":0},"ashgabad":{"$":0},"azerbaijan":{"$":0},"balashov":{"$":0},"bashkiria":{"$":0},"bryansk":{"$":0},"bukhara":{"$":0},"chimkent":{"$":0},"dagestan":{"$":0},"east-kazakhstan":{"$":0},"exnet":{"$":0},"georgia":{"$":0},"grozny":{"$":0},"ivanovo":{"$":0},"jambyl":{"$":0},"kalmykia":{"$":0},"kaluga":{"$":0},"karacol":{"$":0},"karaganda":{"$":0},"karelia":{"$":0},"khakassia":{"$":0},"krasnodar":{"$":0},"kurgan":{"$":0},"kustanai":{"$":0},"lenug":{"$":0},"mangyshlak":{"$":0},"mordovia":{"$":0},"msk":{"$":0},"murmansk":{"$":0},"nalchik":{"$":0},"navoi":{"$":0},"north-kazakhstan":{"$":0},"nov":{"$":0},"obninsk":{"$":0},"penza":{"$":0},"pokrovsk":{"$":0},"sochi":{"$":0},"spb":{"$":0},"tashkent":{"$":0},"termez":{"$":0},"togliatti":{"$":0},"troitsk":{"$":0},"tselinograd":{"$":0},"tula":{"$":0},"tuva":{"$":0},"vladikavkaz":{"$":0},"vladimir":{"$":0},"vologda":{"$":0},"nym":{"$":0}},"sv":{"$":0,"com":{"$":0},"edu":{"$":0},"gob":{"$":0},"org":{"$":0},"red":{"$":0}},"sx":{"$":0,"gov":{"$":0},"nym":{"$":0}},"sy":{"$":0,"edu":{"$":0},"gov":{"$":0},"net":{"$":0},"mil":{"$":0},"com":{"$":0},"org":{"$":0}},"sz":{"$":0,"co":{"$":0},"ac":{"$":0},"org":{"$":0}},"tc":{"$":0},"td":{"$":0,"blogspot":{"$":0}},"tel":{"$":0},"tf":{"$":0},"tg":{"$":0},"th":{"$":0,"ac":{"$":0},"co":{"$":0},"go":{"$":0},"in":{"$":0},"mi":{"$":0},"net":{"$":0},"or":{"$":0}},"tj":{"$":0,"ac":{"$":0},"biz":{"$":0},"co":{"$":0},"com":{"$":0},"edu":{"$":0},"go":{"$":0},"gov":{"$":0},"int":{"$":0},"mil":{"$":0},"name":{"$":0},"net":{"$":0},"nic":{"$":0},"org":{"$":0},"test":{"$":0},"web":{"$":0}},"tk":{"$":0},"tl":{"$":0,"gov":{"$":0}},"tm":{"$":0,"com":{"$":0},"co":{"$":0},"org":{"$":0},"net":{"$":0},"nom":{"$":0},"gov":{"$":0},"mil":{"$":0},"edu":{"$":0}},"tn":{"$":0,"com":{"$":0},"ens":{"$":0},"fin":{"$":0},"gov":{"$":0},"ind":{"$":0},"intl":{"$":0},"nat":{"$":0},"net":{"$":0},"org":{"$":0},"info":{"$":0},"perso":{"$":0},"tourism":{"$":0},"edunet":{"$":0},"rnrt":{"$":0},"rns":{"$":0},"rnu":{"$":0},"mincom":{"$":0},"agrinet":{"$":0},"defense":{"$":0},"turen":{"$":0}},"to":{"$":0,"com":{"$":0},"gov":{"$":0},"net":{"$":0},"org":{"$":0},"edu":{"$":0},"mil":{"$":0},"vpnplus":{"$":0}},"tr":{"$":0,"com":{"$":0,"blogspot":{"$":0}},"info":{"$":0},"biz":{"$":0},"net":{"$":0},"org":{"$":0},"web":{"$":0},"gen":{"$":0},"tv":{"$":0},"av":{"$":0},"dr":{"$":0},"bbs":{"$":0},"name":{"$":0},"tel":{"$":0},"gov":{"$":0},"bel":{"$":0},"pol":{"$":0},"mil":{"$":0},"k12":{"$":0},"edu":{"$":0},"kep":{"$":0},"nc":{"$":0,"gov":{"$":0}}},"travel":{"$":0},"tt":{"$":0,"co":{"$":0},"com":{"$":0},"org":{"$":0},"net":{"$":0},"biz":{"$":0},"info":{"$":0},"pro":{"$":0},"int":{"$":0},"coop":{"$":0},"jobs":{"$":0},"mobi":{"$":0},"travel":{"$":0},"museum":{"$":0},"aero":{"$":0},"name":{"$":0},"gov":{"$":0},"edu":{"$":0}},"tv":{"$":0,"dyndns":{"$":0},"better-than":{"$":0},"on-the-web":{"$":0},"worse-than":{"$":0}},"tw":{"$":0,"edu":{"$":0},"gov":{"$":0},"mil":{"$":0},"com":{"$":0,"mymailer":{"$":0}},"net":{"$":0},"org":{"$":0},"idv":{"$":0},"game":{"$":0},"ebiz":{"$":0},"club":{"$":0},"xn--zf0ao64a":{"$":0},"xn--uc0atv":{"$":0},"xn--czrw28b":{"$":0},"url":{"$":0},"blogspot":{"$":0},"nym":{"$":0}},"tz":{"$":0,"ac":{"$":0},"co":{"$":0},"go":{"$":0},"hotel":{"$":0},"info":{"$":0},"me":{"$":0},"mil":{"$":0},"mobi":{"$":0},"ne":{"$":0},"or":{"$":0},"sc":{"$":0},"tv":{"$":0}},"ua":{"$":0,"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"in":{"$":0},"net":{"$":0},"org":{"$":0},"cherkassy":{"$":0},"cherkasy":{"$":0},"chernigov":{"$":0},"chernihiv":{"$":0},"chernivtsi":{"$":0},"chernovtsy":{"$":0},"ck":{"$":0},"cn":{"$":0},"cr":{"$":0},"crimea":{"$":0},"cv":{"$":0},"dn":{"$":0},"dnepropetrovsk":{"$":0},"dnipropetrovsk":{"$":0},"dominic":{"$":0},"donetsk":{"$":0},"dp":{"$":0},"if":{"$":0},"ivano-frankivsk":{"$":0},"kh":{"$":0},"kharkiv":{"$":0},"kharkov":{"$":0},"kherson":{"$":0},"khmelnitskiy":{"$":0},"khmelnytskyi":{"$":0},"kiev":{"$":0},"kirovograd":{"$":0},"km":{"$":0},"kr":{"$":0},"krym":{"$":0},"ks":{"$":0},"kv":{"$":0},"kyiv":{"$":0},"lg":{"$":0},"lt":{"$":0},"lugansk":{"$":0},"lutsk":{"$":0},"lv":{"$":0},"lviv":{"$":0},"mk":{"$":0},"mykolaiv":{"$":0},"nikolaev":{"$":0},"od":{"$":0},"odesa":{"$":0},"odessa":{"$":0},"pl":{"$":0},"poltava":{"$":0},"rivne":{"$":0},"rovno":{"$":0},"rv":{"$":0},"sb":{"$":0},"sebastopol":{"$":0},"sevastopol":{"$":0},"sm":{"$":0},"sumy":{"$":0},"te":{"$":0},"ternopil":{"$":0},"uz":{"$":0},"uzhgorod":{"$":0},"vinnica":{"$":0},"vinnytsia":{"$":0},"vn":{"$":0},"volyn":{"$":0},"yalta":{"$":0},"zaporizhzhe":{"$":0},"zaporizhzhia":{"$":0},"zhitomir":{"$":0},"zhytomyr":{"$":0},"zp":{"$":0},"zt":{"$":0},"cc":{"$":0},"inf":{"$":0},"ltd":{"$":0},"biz":{"$":0},"co":{"$":0},"pp":{"$":0}},"ug":{"$":0,"co":{"$":0},"or":{"$":0},"ac":{"$":0},"sc":{"$":0},"go":{"$":0},"ne":{"$":0},"com":{"$":0},"org":{"$":0},"blogspot":{"$":0},"nom":{"$":0}},"uk":{"$":0,"ac":{"$":0},"co":{"$":0,"blogspot":{"$":0},"nh-serv":{"$":0},"no-ip":{"$":0},"wellbeingzone":{"$":0}},"gov":{"$":0,"service":{"$":0},"homeoffice":{"$":0}},"ltd":{"$":0},"me":{"$":0},"net":{"$":0},"nhs":{"$":0},"org":{"$":0},"plc":{"$":0},"police":{"$":0},"sch":{"*":{"$":0}}},"us":{"$":0,"dni":{"$":0},"fed":{"$":0},"isa":{"$":0},"kids":{"$":0},"nsn":{"$":0},"ak":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"al":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"ar":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"as":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"az":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"ca":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"co":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"ct":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"dc":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"de":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"fl":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"ga":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"gu":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"hi":{"$":0,"cc":{"$":0},"lib":{"$":0}},"ia":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"id":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"il":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"in":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"ks":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"ky":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"la":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"ma":{"$":0,"k12":{"$":0,"pvt":{"$":0},"chtr":{"$":0},"paroch":{"$":0}},"cc":{"$":0},"lib":{"$":0}},"md":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"me":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"mi":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0},"ann-arbor":{"$":0},"cog":{"$":0},"dst":{"$":0},"eaton":{"$":0},"gen":{"$":0},"mus":{"$":0},"tec":{"$":0},"washtenaw":{"$":0}},"mn":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"mo":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"ms":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"mt":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"nc":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"nd":{"$":0,"cc":{"$":0},"lib":{"$":0}},"ne":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"nh":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"nj":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"nm":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"nv":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"ny":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"oh":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"ok":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"or":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"pa":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"pr":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"ri":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"sc":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"sd":{"$":0,"cc":{"$":0},"lib":{"$":0}},"tn":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"tx":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"ut":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"vi":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"vt":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"va":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"wa":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"wi":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"wv":{"$":0,"cc":{"$":0}},"wy":{"$":0,"k12":{"$":0},"cc":{"$":0},"lib":{"$":0}},"cloudns":{"$":0},"drud":{"$":0},"is-by":{"$":0},"land-4-sale":{"$":0},"stuff-4-sale":{"$":0},"golffan":{"$":0},"noip":{"$":0},"pointto":{"$":0}},"uy":{"$":0,"com":{"$":0,"blogspot":{"$":0}},"edu":{"$":0},"gub":{"$":0},"mil":{"$":0},"net":{"$":0},"org":{"$":0},"nom":{"$":0}},"uz":{"$":0,"co":{"$":0},"com":{"$":0},"net":{"$":0},"org":{"$":0}},"va":{"$":0},"vc":{"$":0,"com":{"$":0},"net":{"$":0},"org":{"$":0},"gov":{"$":0},"mil":{"$":0},"edu":{"$":0},"nom":{"$":0}},"ve":{"$":0,"arts":{"$":0},"co":{"$":0},"com":{"$":0},"e12":{"$":0},"edu":{"$":0},"firm":{"$":0},"gob":{"$":0},"gov":{"$":0},"info":{"$":0},"int":{"$":0},"mil":{"$":0},"net":{"$":0},"org":{"$":0},"rec":{"$":0},"store":{"$":0},"tec":{"$":0},"web":{"$":0}},"vg":{"$":0,"nom":{"$":0}},"vi":{"$":0,"co":{"$":0},"com":{"$":0},"k12":{"$":0},"net":{"$":0},"org":{"$":0}},"vn":{"$":0,"com":{"$":0},"net":{"$":0},"org":{"$":0},"edu":{"$":0},"gov":{"$":0},"int":{"$":0},"ac":{"$":0},"biz":{"$":0},"info":{"$":0},"name":{"$":0},"pro":{"$":0},"health":{"$":0},"blogspot":{"$":0}},"vu":{"$":0,"com":{"$":0},"edu":{"$":0},"net":{"$":0},"org":{"$":0}},"wf":{"$":0},"ws":{"$":0,"com":{"$":0},"net":{"$":0},"org":{"$":0},"gov":{"$":0},"edu":{"$":0},"advisor":{"*":{"$":0}},"dyndns":{"$":0},"mypets":{"$":0}},"yt":{"$":0},"xn--mgbaam7a8h":{"$":0},"xn--y9a3aq":{"$":0},"xn--54b7fta0cc":{"$":0},"xn--90ae":{"$":0},"xn--90ais":{"$":0},"xn--fiqs8s":{"$":0},"xn--fiqz9s":{"$":0},"xn--lgbbat1ad8j":{"$":0},"xn--wgbh1c":{"$":0},"xn--e1a4c":{"$":0},"xn--node":{"$":0},"xn--qxam":{"$":0},"xn--j6w193g":{"$":0},"xn--2scrj9c":{"$":0},"xn--3hcrj9c":{"$":0},"xn--45br5cyl":{"$":0},"xn--h2breg3eve":{"$":0},"xn--h2brj9c8c":{"$":0},"xn--mgbgu82a":{"$":0},"xn--rvc1e0am3e":{"$":0},"xn--h2brj9c":{"$":0},"xn--mgbbh1a71e":{"$":0},"xn--fpcrj9c3d":{"$":0},"xn--gecrj9c":{"$":0},"xn--s9brj9c":{"$":0},"xn--45brj9c":{"$":0},"xn--xkc2dl3a5ee0h":{"$":0},"xn--mgba3a4f16a":{"$":0},"xn--mgba3a4fra":{"$":0},"xn--mgbtx2b":{"$":0},"xn--mgbayh7gpa":{"$":0},"xn--3e0b707e":{"$":0},"xn--80ao21a":{"$":0},"xn--fzc2c9e2c":{"$":0},"xn--xkc2al3hye2a":{"$":0},"xn--mgbc0a9azcg":{"$":0},"xn--d1alf":{"$":0},"xn--l1acc":{"$":0},"xn--mix891f":{"$":0},"xn--mix082f":{"$":0},"xn--mgbx4cd0ab":{"$":0},"xn--mgb9awbf":{"$":0},"xn--mgbai9azgqp6j":{"$":0},"xn--mgbai9a5eva00b":{"$":0},"xn--ygbi2ammx":{"$":0},"xn--90a3ac":{"$":0,"xn--o1ac":{"$":0},"xn--c1avg":{"$":0},"xn--90azh":{"$":0},"xn--d1at":{"$":0},"xn--o1ach":{"$":0},"xn--80au":{"$":0}},"xn--p1ai":{"$":0},"xn--wgbl6a":{"$":0},"xn--mgberp4a5d4ar":{"$":0},"xn--mgberp4a5d4a87g":{"$":0},"xn--mgbqly7c0a67fbc":{"$":0},"xn--mgbqly7cvafr":{"$":0},"xn--mgbpl2fh":{"$":0},"xn--yfro4i67o":{"$":0},"xn--clchc0ea0b2g2a9gcd":{"$":0},"xn--ogbpf8fl":{"$":0},"xn--mgbtf8fl":{"$":0},"xn--o3cw4h":{"$":0,"xn--12c1fe0br":{"$":0},"xn--12co0c3b4eva":{"$":0},"xn--h3cuzk1di":{"$":0},"xn--o3cyx2a":{"$":0},"xn--m3ch0j3a":{"$":0},"xn--12cfi8ixb8l":{"$":0}},"xn--pgbs0dh":{"$":0},"xn--kpry57d":{"$":0},"xn--kprw13d":{"$":0},"xn--nnx388a":{"$":0},"xn--j1amh":{"$":0},"xn--mgb2ddes":{"$":0},"xxx":{"$":0},"ye":{"*":{"$":0}},"za":{"ac":{"$":0},"agric":{"$":0},"alt":{"$":0},"co":{"$":0,"blogspot":{"$":0}},"edu":{"$":0},"gov":{"$":0},"grondar":{"$":0},"law":{"$":0},"mil":{"$":0},"net":{"$":0},"ngo":{"$":0},"nis":{"$":0},"nom":{"$":0},"org":{"$":0},"school":{"$":0},"tm":{"$":0},"web":{"$":0}},"zm":{"$":0,"ac":{"$":0},"biz":{"$":0},"co":{"$":0},"com":{"$":0},"edu":{"$":0},"gov":{"$":0},"info":{"$":0},"mil":{"$":0},"net":{"$":0},"org":{"$":0},"sch":{"$":0}},"zw":{"$":0,"ac":{"$":0},"co":{"$":0},"gov":{"$":0},"mil":{"$":0},"org":{"$":0}},"aaa":{"$":0},"aarp":{"$":0},"abarth":{"$":0},"abb":{"$":0},"abbott":{"$":0},"abbvie":{"$":0},"abc":{"$":0},"able":{"$":0},"abogado":{"$":0},"abudhabi":{"$":0},"academy":{"$":0},"accenture":{"$":0},"accountant":{"$":0},"accountants":{"$":0},"aco":{"$":0},"active":{"$":0},"actor":{"$":0},"adac":{"$":0},"ads":{"$":0},"adult":{"$":0},"aeg":{"$":0},"aetna":{"$":0},"afamilycompany":{"$":0},"afl":{"$":0},"africa":{"$":0},"agakhan":{"$":0},"agency":{"$":0},"aig":{"$":0},"aigo":{"$":0},"airbus":{"$":0},"airforce":{"$":0},"airtel":{"$":0},"akdn":{"$":0},"alfaromeo":{"$":0},"alibaba":{"$":0},"alipay":{"$":0},"allfinanz":{"$":0},"allstate":{"$":0},"ally":{"$":0},"alsace":{"$":0},"alstom":{"$":0},"americanexpress":{"$":0},"americanfamily":{"$":0},"amex":{"$":0},"amfam":{"$":0},"amica":{"$":0},"amsterdam":{"$":0},"analytics":{"$":0},"android":{"$":0},"anquan":{"$":0},"anz":{"$":0},"aol":{"$":0},"apartments":{"$":0},"app":{"$":0},"apple":{"$":0},"aquarelle":{"$":0},"arab":{"$":0},"aramco":{"$":0},"archi":{"$":0},"army":{"$":0},"art":{"$":0},"arte":{"$":0},"asda":{"$":0},"associates":{"$":0},"athleta":{"$":0},"attorney":{"$":0},"auction":{"$":0},"audi":{"$":0},"audible":{"$":0},"audio":{"$":0},"auspost":{"$":0},"author":{"$":0},"auto":{"$":0},"autos":{"$":0},"avianca":{"$":0},"aws":{"$":0},"axa":{"$":0},"azure":{"$":0},"baby":{"$":0},"baidu":{"$":0},"banamex":{"$":0},"bananarepublic":{"$":0},"band":{"$":0},"bank":{"$":0},"bar":{"$":0},"barcelona":{"$":0},"barclaycard":{"$":0},"barclays":{"$":0},"barefoot":{"$":0},"bargains":{"$":0},"baseball":{"$":0},"basketball":{"$":0},"bauhaus":{"$":0},"bayern":{"$":0},"bbc":{"$":0},"bbt":{"$":0},"bbva":{"$":0},"bcg":{"$":0},"bcn":{"$":0},"beats":{"$":0},"beauty":{"$":0},"beer":{"$":0},"bentley":{"$":0},"berlin":{"$":0},"best":{"$":0},"bestbuy":{"$":0},"bet":{"$":0},"bharti":{"$":0},"bible":{"$":0},"bid":{"$":0},"bike":{"$":0},"bing":{"$":0},"bingo":{"$":0},"bio":{"$":0},"black":{"$":0},"blackfriday":{"$":0},"blanco":{"$":0},"blockbuster":{"$":0},"blog":{"$":0},"bloomberg":{"$":0},"blue":{"$":0},"bms":{"$":0},"bmw":{"$":0},"bnl":{"$":0},"bnpparibas":{"$":0},"boats":{"$":0},"boehringer":{"$":0},"bofa":{"$":0},"bom":{"$":0},"bond":{"$":0},"boo":{"$":0},"book":{"$":0},"booking":{"$":0},"boots":{"$":0},"bosch":{"$":0},"bostik":{"$":0},"boston":{"$":0},"bot":{"$":0},"boutique":{"$":0},"box":{"$":0},"bradesco":{"$":0},"bridgestone":{"$":0},"broadway":{"$":0},"broker":{"$":0},"brother":{"$":0},"brussels":{"$":0},"budapest":{"$":0},"bugatti":{"$":0},"build":{"$":0},"builders":{"$":0},"business":{"$":0},"buy":{"$":0},"buzz":{"$":0},"bzh":{"$":0},"cab":{"$":0},"cafe":{"$":0},"cal":{"$":0},"call":{"$":0},"calvinklein":{"$":0},"cam":{"$":0},"camera":{"$":0},"camp":{"$":0},"cancerresearch":{"$":0},"canon":{"$":0},"capetown":{"$":0},"capital":{"$":0},"capitalone":{"$":0},"car":{"$":0},"caravan":{"$":0},"cards":{"$":0},"care":{"$":0},"career":{"$":0},"careers":{"$":0},"cars":{"$":0},"cartier":{"$":0},"casa":{"$":0},"case":{"$":0},"caseih":{"$":0},"cash":{"$":0},"casino":{"$":0},"catering":{"$":0},"catholic":{"$":0},"cba":{"$":0},"cbn":{"$":0},"cbre":{"$":0},"cbs":{"$":0},"ceb":{"$":0},"center":{"$":0},"ceo":{"$":0},"cern":{"$":0},"cfa":{"$":0},"cfd":{"$":0},"chanel":{"$":0},"channel":{"$":0},"chase":{"$":0},"chat":{"$":0},"cheap":{"$":0},"chintai":{"$":0},"christmas":{"$":0},"chrome":{"$":0},"chrysler":{"$":0},"church":{"$":0},"cipriani":{"$":0},"circle":{"$":0},"cisco":{"$":0},"citadel":{"$":0},"citi":{"$":0},"citic":{"$":0},"city":{"$":0},"cityeats":{"$":0},"claims":{"$":0},"cleaning":{"$":0},"click":{"$":0},"clinic":{"$":0},"clinique":{"$":0},"clothing":{"$":0},"cloud":{"$":0,"statics":{"*":{"$":0}},"magentosite":{"*":{"$":0}},"vapor":{"$":0},"sensiosite":{"*":{"$":0}},"trafficplex":{"$":0}},"club":{"$":0,"cloudns":{"$":0}},"clubmed":{"$":0},"coach":{"$":0},"codes":{"$":0},"coffee":{"$":0},"college":{"$":0},"cologne":{"$":0},"comcast":{"$":0},"commbank":{"$":0},"community":{"$":0},"company":{"$":0},"compare":{"$":0},"computer":{"$":0},"comsec":{"$":0},"condos":{"$":0},"construction":{"$":0},"consulting":{"$":0},"contact":{"$":0},"contractors":{"$":0},"cooking":{"$":0},"cookingchannel":{"$":0},"cool":{"$":0,"de":{"$":0}},"corsica":{"$":0},"country":{"$":0},"coupon":{"$":0},"coupons":{"$":0},"courses":{"$":0},"credit":{"$":0},"creditcard":{"$":0},"creditunion":{"$":0},"cricket":{"$":0},"crown":{"$":0},"crs":{"$":0},"cruise":{"$":0},"cruises":{"$":0},"csc":{"$":0},"cuisinella":{"$":0},"cymru":{"$":0},"cyou":{"$":0},"dabur":{"$":0},"dad":{"$":0},"dance":{"$":0},"data":{"$":0},"date":{"$":0},"dating":{"$":0},"datsun":{"$":0},"day":{"$":0},"dclk":{"$":0},"dds":{"$":0},"deal":{"$":0},"dealer":{"$":0},"deals":{"$":0},"degree":{"$":0},"delivery":{"$":0},"dell":{"$":0},"deloitte":{"$":0},"delta":{"$":0},"democrat":{"$":0},"dental":{"$":0},"dentist":{"$":0},"desi":{"$":0},"design":{"$":0},"dev":{"$":0},"dhl":{"$":0},"diamonds":{"$":0},"diet":{"$":0},"digital":{"$":0},"direct":{"$":0},"directory":{"$":0},"discount":{"$":0},"discover":{"$":0},"dish":{"$":0},"diy":{"$":0},"dnp":{"$":0},"docs":{"$":0},"doctor":{"$":0},"dodge":{"$":0},"dog":{"$":0},"doha":{"$":0},"domains":{"$":0},"dot":{"$":0},"download":{"$":0},"drive":{"$":0},"dtv":{"$":0},"dubai":{"$":0},"duck":{"$":0},"dunlop":{"$":0},"duns":{"$":0},"dupont":{"$":0},"durban":{"$":0},"dvag":{"$":0},"dvr":{"$":0},"earth":{"$":0},"eat":{"$":0},"eco":{"$":0},"edeka":{"$":0},"education":{"$":0},"email":{"$":0},"emerck":{"$":0},"energy":{"$":0},"engineer":{"$":0},"engineering":{"$":0},"enterprises":{"$":0},"epost":{"$":0},"epson":{"$":0},"equipment":{"$":0},"ericsson":{"$":0},"erni":{"$":0},"esq":{"$":0},"estate":{"$":0,"compute":{"*":{"$":0}}},"esurance":{"$":0},"etisalat":{"$":0},"eurovision":{"$":0},"eus":{"$":0,"party":{"user":{"$":0}}},"events":{"$":0},"everbank":{"$":0},"exchange":{"$":0},"expert":{"$":0},"exposed":{"$":0},"express":{"$":0},"extraspace":{"$":0},"fage":{"$":0},"fail":{"$":0},"fairwinds":{"$":0},"faith":{"$":0,"ybo":{"$":0}},"family":{"$":0},"fan":{"$":0},"fans":{"$":0},"farm":{"$":0,"storj":{"$":0}},"farmers":{"$":0},"fashion":{"$":0},"fast":{"$":0},"fedex":{"$":0},"feedback":{"$":0},"ferrari":{"$":0},"ferrero":{"$":0},"fiat":{"$":0},"fidelity":{"$":0},"fido":{"$":0},"film":{"$":0},"final":{"$":0},"finance":{"$":0},"financial":{"$":0},"fire":{"$":0},"firestone":{"$":0},"firmdale":{"$":0},"fish":{"$":0},"fishing":{"$":0},"fit":{"$":0,"ptplus":{"$":0}},"fitness":{"$":0},"flickr":{"$":0},"flights":{"$":0},"flir":{"$":0},"florist":{"$":0},"flowers":{"$":0},"fly":{"$":0},"foo":{"$":0},"food":{"$":0},"foodnetwork":{"$":0},"football":{"$":0},"ford":{"$":0},"forex":{"$":0},"forsale":{"$":0},"forum":{"$":0},"foundation":{"$":0},"fox":{"$":0},"free":{"$":0},"fresenius":{"$":0},"frl":{"$":0},"frogans":{"$":0},"frontdoor":{"$":0},"frontier":{"$":0},"ftr":{"$":0},"fujitsu":{"$":0},"fujixerox":{"$":0},"fun":{"$":0},"fund":{"$":0},"furniture":{"$":0},"futbol":{"$":0},"fyi":{"$":0},"gal":{"$":0},"gallery":{"$":0},"gallo":{"$":0},"gallup":{"$":0},"game":{"$":0},"games":{"$":0},"gap":{"$":0},"garden":{"$":0},"gbiz":{"$":0},"gdn":{"$":0},"gea":{"$":0},"gent":{"$":0},"genting":{"$":0},"george":{"$":0},"ggee":{"$":0},"gift":{"$":0},"gifts":{"$":0},"gives":{"$":0},"giving":{"$":0},"glade":{"$":0},"glass":{"$":0},"gle":{"$":0},"global":{"$":0},"globo":{"$":0},"gmail":{"$":0},"gmbh":{"$":0},"gmo":{"$":0},"gmx":{"$":0},"godaddy":{"$":0},"gold":{"$":0},"goldpoint":{"$":0},"golf":{"$":0},"goo":{"$":0},"goodhands":{"$":0},"goodyear":{"$":0},"goog":{"$":0,"cloud":{"$":0}},"google":{"$":0},"gop":{"$":0},"got":{"$":0},"grainger":{"$":0},"graphics":{"$":0},"gratis":{"$":0},"green":{"$":0},"gripe":{"$":0},"grocery":{"$":0},"group":{"$":0},"guardian":{"$":0},"gucci":{"$":0},"guge":{"$":0},"guide":{"$":0},"guitars":{"$":0},"guru":{"$":0},"hair":{"$":0},"hamburg":{"$":0},"hangout":{"$":0},"haus":{"$":0},"hbo":{"$":0},"hdfc":{"$":0},"hdfcbank":{"$":0},"health":{"$":0},"healthcare":{"$":0},"help":{"$":0},"helsinki":{"$":0},"here":{"$":0},"hermes":{"$":0},"hgtv":{"$":0},"hiphop":{"$":0},"hisamitsu":{"$":0},"hitachi":{"$":0},"hiv":{"$":0},"hkt":{"$":0},"hockey":{"$":0},"holdings":{"$":0},"holiday":{"$":0},"homedepot":{"$":0},"homegoods":{"$":0},"homes":{"$":0},"homesense":{"$":0},"honda":{"$":0},"honeywell":{"$":0},"horse":{"$":0},"hospital":{"$":0},"host":{"$":0,"cloudaccess":{"$":0},"freesite":{"$":0}},"hosting":{"$":0,"opencraft":{"$":0}},"hot":{"$":0},"hoteles":{"$":0},"hotels":{"$":0},"hotmail":{"$":0},"house":{"$":0},"how":{"$":0},"hsbc":{"$":0},"hughes":{"$":0},"hyatt":{"$":0},"hyundai":{"$":0},"ibm":{"$":0},"icbc":{"$":0},"ice":{"$":0},"icu":{"$":0},"ieee":{"$":0},"ifm":{"$":0},"ikano":{"$":0},"imamat":{"$":0},"imdb":{"$":0},"immo":{"$":0},"immobilien":{"$":0},"industries":{"$":0},"infiniti":{"$":0},"ing":{"$":0},"ink":{"$":0},"institute":{"$":0},"insurance":{"$":0},"insure":{"$":0},"intel":{"$":0},"international":{"$":0},"intuit":{"$":0},"investments":{"$":0},"ipiranga":{"$":0},"irish":{"$":0},"iselect":{"$":0},"ismaili":{"$":0},"ist":{"$":0},"istanbul":{"$":0},"itau":{"$":0},"itv":{"$":0},"iveco":{"$":0},"iwc":{"$":0},"jaguar":{"$":0},"java":{"$":0},"jcb":{"$":0},"jcp":{"$":0},"jeep":{"$":0},"jetzt":{"$":0},"jewelry":{"$":0},"jio":{"$":0},"jlc":{"$":0},"jll":{"$":0},"jmp":{"$":0},"jnj":{"$":0},"joburg":{"$":0},"jot":{"$":0},"joy":{"$":0},"jpmorgan":{"$":0},"jprs":{"$":0},"juegos":{"$":0},"juniper":{"$":0},"kaufen":{"$":0},"kddi":{"$":0},"kerryhotels":{"$":0},"kerrylogistics":{"$":0},"kerryproperties":{"$":0},"kfh":{"$":0},"kia":{"$":0},"kim":{"$":0},"kinder":{"$":0},"kindle":{"$":0},"kitchen":{"$":0},"kiwi":{"$":0},"koeln":{"$":0},"komatsu":{"$":0},"kosher":{"$":0},"kpmg":{"$":0},"kpn":{"$":0},"krd":{"$":0,"co":{"$":0},"edu":{"$":0}},"kred":{"$":0},"kuokgroup":{"$":0},"kyoto":{"$":0},"lacaixa":{"$":0},"ladbrokes":{"$":0},"lamborghini":{"$":0},"lamer":{"$":0},"lancaster":{"$":0},"lancia":{"$":0},"lancome":{"$":0},"land":{"$":0,"static":{"$":0,"dev":{"$":0},"sites":{"$":0}}},"landrover":{"$":0},"lanxess":{"$":0},"lasalle":{"$":0},"lat":{"$":0},"latino":{"$":0},"latrobe":{"$":0},"law":{"$":0},"lawyer":{"$":0},"lds":{"$":0},"lease":{"$":0},"leclerc":{"$":0},"lefrak":{"$":0},"legal":{"$":0},"lego":{"$":0},"lexus":{"$":0},"lgbt":{"$":0},"liaison":{"$":0},"lidl":{"$":0},"life":{"$":0},"lifeinsurance":{"$":0},"lifestyle":{"$":0},"lighting":{"$":0},"like":{"$":0},"lilly":{"$":0},"limited":{"$":0},"limo":{"$":0},"lincoln":{"$":0},"linde":{"$":0},"link":{"$":0,"cyon":{"$":0},"mypep":{"$":0}},"lipsy":{"$":0},"live":{"$":0},"living":{"$":0},"lixil":{"$":0},"loan":{"$":0},"loans":{"$":0},"locker":{"$":0},"locus":{"$":0},"loft":{"$":0},"lol":{"$":0},"london":{"$":0},"lotte":{"$":0},"lotto":{"$":0},"love":{"$":0},"lpl":{"$":0},"lplfinancial":{"$":0},"ltd":{"$":0},"ltda":{"$":0},"lundbeck":{"$":0},"lupin":{"$":0},"luxe":{"$":0},"luxury":{"$":0},"macys":{"$":0},"madrid":{"$":0},"maif":{"$":0},"maison":{"$":0},"makeup":{"$":0},"man":{"$":0},"management":{"$":0,"router":{"$":0}},"mango":{"$":0},"map":{"$":0},"market":{"$":0},"marketing":{"$":0},"markets":{"$":0},"marriott":{"$":0},"marshalls":{"$":0},"maserati":{"$":0},"mattel":{"$":0},"mba":{"$":0},"mckinsey":{"$":0},"med":{"$":0},"media":{"$":0},"meet":{"$":0},"melbourne":{"$":0},"meme":{"$":0},"memorial":{"$":0},"men":{"$":0},"menu":{"$":0},"meo":{"$":0},"merckmsd":{"$":0},"metlife":{"$":0},"miami":{"$":0},"microsoft":{"$":0},"mini":{"$":0},"mint":{"$":0},"mit":{"$":0},"mitsubishi":{"$":0},"mlb":{"$":0},"mls":{"$":0},"mma":{"$":0},"mobile":{"$":0},"mobily":{"$":0},"moda":{"$":0},"moe":{"$":0},"moi":{"$":0},"mom":{"$":0},"monash":{"$":0},"money":{"$":0},"monster":{"$":0},"mopar":{"$":0},"mormon":{"$":0},"mortgage":{"$":0},"moscow":{"$":0},"moto":{"$":0},"motorcycles":{"$":0},"mov":{"$":0},"movie":{"$":0},"movistar":{"$":0},"msd":{"$":0},"mtn":{"$":0},"mtpc":{"$":0},"mtr":{"$":0},"mutual":{"$":0},"nab":{"$":0},"nadex":{"$":0},"nagoya":{"$":0},"nationwide":{"$":0},"natura":{"$":0},"navy":{"$":0},"nba":{"$":0},"nec":{"$":0},"netbank":{"$":0},"netflix":{"$":0},"network":{"$":0,"alces":{"*":{"$":0}}},"neustar":{"$":0},"new":{"$":0},"newholland":{"$":0},"news":{"$":0},"next":{"$":0},"nextdirect":{"$":0},"nexus":{"$":0},"nfl":{"$":0},"ngo":{"$":0},"nhk":{"$":0},"nico":{"$":0},"nike":{"$":0},"nikon":{"$":0},"ninja":{"$":0},"nissan":{"$":0},"nissay":{"$":0},"nokia":{"$":0},"northwesternmutual":{"$":0},"norton":{"$":0},"now":{"$":0},"nowruz":{"$":0},"nowtv":{"$":0},"nra":{"$":0},"nrw":{"$":0},"ntt":{"$":0},"nyc":{"$":0},"obi":{"$":0},"observer":{"$":0},"off":{"$":0},"office":{"$":0},"okinawa":{"$":0},"olayan":{"$":0},"olayangroup":{"$":0},"oldnavy":{"$":0},"ollo":{"$":0},"omega":{"$":0},"one":{"$":0,"homelink":{"$":0}},"ong":{"$":0},"onl":{"$":0},"online":{"$":0,"barsy":{"$":0}},"onyourside":{"$":0},"ooo":{"$":0},"open":{"$":0},"oracle":{"$":0},"orange":{"$":0},"organic":{"$":0},"origins":{"$":0},"osaka":{"$":0},"otsuka":{"$":0},"ott":{"$":0},"ovh":{"$":0,"nerdpol":{"$":0}},"page":{"$":0},"panasonic":{"$":0},"panerai":{"$":0},"paris":{"$":0},"pars":{"$":0},"partners":{"$":0},"parts":{"$":0},"party":{"$":0,"ybo":{"$":0}},"passagens":{"$":0},"pay":{"$":0},"pccw":{"$":0},"pet":{"$":0},"pfizer":{"$":0},"pharmacy":{"$":0},"phd":{"$":0},"philips":{"$":0},"phone":{"$":0},"photo":{"$":0},"photography":{"$":0},"photos":{"$":0},"physio":{"$":0},"piaget":{"$":0},"pics":{"$":0},"pictet":{"$":0},"pictures":{"1337":{"$":0},"$":0},"pid":{"$":0},"pin":{"$":0},"ping":{"$":0},"pink":{"$":0},"pioneer":{"$":0},"pizza":{"$":0},"place":{"$":0},"play":{"$":0},"playstation":{"$":0},"plumbing":{"$":0},"plus":{"$":0},"pnc":{"$":0},"pohl":{"$":0},"poker":{"$":0},"politie":{"$":0},"porn":{"$":0},"pramerica":{"$":0},"praxi":{"$":0},"press":{"$":0},"prime":{"$":0},"prod":{"$":0},"productions":{"$":0},"prof":{"$":0},"progressive":{"$":0},"promo":{"$":0},"properties":{"$":0},"property":{"$":0},"protection":{"$":0},"pru":{"$":0},"prudential":{"$":0},"pub":{"$":0},"pwc":{"$":0},"qpon":{"$":0},"quebec":{"$":0},"quest":{"$":0},"qvc":{"$":0},"racing":{"$":0},"radio":{"$":0},"raid":{"$":0},"read":{"$":0},"realestate":{"$":0},"realtor":{"$":0},"realty":{"$":0},"recipes":{"$":0},"red":{"$":0},"redstone":{"$":0},"redumbrella":{"$":0},"rehab":{"$":0},"reise":{"$":0},"reisen":{"$":0},"reit":{"$":0},"reliance":{"$":0},"ren":{"$":0},"rent":{"$":0},"rentals":{"$":0},"repair":{"$":0},"report":{"$":0},"republican":{"$":0},"rest":{"$":0},"restaurant":{"$":0},"review":{"$":0,"ybo":{"$":0}},"reviews":{"$":0},"rexroth":{"$":0},"rich":{"$":0},"richardli":{"$":0},"ricoh":{"$":0},"rightathome":{"$":0},"ril":{"$":0},"rio":{"$":0},"rip":{"$":0,"clan":{"$":0}},"rmit":{"$":0},"rocher":{"$":0},"rocks":{"$":0,"myddns":{"$":0},"lima-city":{"$":0},"webspace":{"$":0}},"rodeo":{"$":0},"rogers":{"$":0},"room":{"$":0},"rsvp":{"$":0},"rugby":{"$":0},"ruhr":{"$":0},"run":{"$":0},"rwe":{"$":0},"ryukyu":{"$":0},"saarland":{"$":0},"safe":{"$":0},"safety":{"$":0},"sakura":{"$":0},"sale":{"$":0},"salon":{"$":0},"samsclub":{"$":0},"samsung":{"$":0},"sandvik":{"$":0},"sandvikcoromant":{"$":0},"sanofi":{"$":0},"sap":{"$":0},"sapo":{"$":0},"sarl":{"$":0},"sas":{"$":0},"save":{"$":0},"saxo":{"$":0},"sbi":{"$":0},"sbs":{"$":0},"sca":{"$":0},"scb":{"$":0},"schaeffler":{"$":0},"schmidt":{"$":0},"scholarships":{"$":0},"school":{"$":0},"schule":{"$":0},"schwarz":{"$":0},"science":{"$":0,"ybo":{"$":0}},"scjohnson":{"$":0},"scor":{"$":0},"scot":{"$":0},"search":{"$":0},"seat":{"$":0},"secure":{"$":0},"security":{"$":0},"seek":{"$":0},"select":{"$":0},"sener":{"$":0},"services":{"$":0},"ses":{"$":0},"seven":{"$":0},"sew":{"$":0},"sex":{"$":0},"sexy":{"$":0},"sfr":{"$":0},"shangrila":{"$":0},"sharp":{"$":0},"shaw":{"$":0},"shell":{"$":0},"shia":{"$":0},"shiksha":{"$":0},"shoes":{"$":0},"shop":{"$":0},"shopping":{"$":0},"shouji":{"$":0},"show":{"$":0},"showtime":{"$":0},"shriram":{"$":0},"silk":{"$":0},"sina":{"$":0},"singles":{"$":0},"site":{"$":0,"cyon":{"$":0},"platformsh":{"*":{"$":0}},"byen":{"$":0}},"ski":{"$":0},"skin":{"$":0},"sky":{"$":0},"skype":{"$":0},"sling":{"$":0},"smart":{"$":0},"smile":{"$":0},"sncf":{"$":0},"soccer":{"$":0},"social":{"$":0},"softbank":{"$":0},"software":{"$":0},"sohu":{"$":0},"solar":{"$":0},"solutions":{"$":0},"song":{"$":0},"sony":{"$":0},"soy":{"$":0},"space":{"$":0,"stackspace":{"$":0},"uber":{"$":0},"xs4all":{"$":0}},"spiegel":{"$":0},"spot":{"$":0},"spreadbetting":{"$":0},"srl":{"$":0},"srt":{"$":0},"stada":{"$":0},"staples":{"$":0},"star":{"$":0},"starhub":{"$":0},"statebank":{"$":0},"statefarm":{"$":0},"statoil":{"$":0},"stc":{"$":0},"stcgroup":{"$":0},"stockholm":{"$":0},"storage":{"$":0},"store":{"$":0},"stream":{"$":0},"studio":{"$":0},"study":{"$":0},"style":{"$":0},"sucks":{"$":0},"supplies":{"$":0},"supply":{"$":0},"support":{"$":0,"barsy":{"$":0}},"surf":{"$":0},"surgery":{"$":0},"suzuki":{"$":0},"swatch":{"$":0},"swiftcover":{"$":0},"swiss":{"$":0},"sydney":{"$":0},"symantec":{"$":0},"systems":{"$":0,"knightpoint":{"$":0}},"tab":{"$":0},"taipei":{"$":0},"talk":{"$":0},"taobao":{"$":0},"target":{"$":0},"tatamotors":{"$":0},"tatar":{"$":0},"tattoo":{"$":0},"tax":{"$":0},"taxi":{"$":0},"tci":{"$":0},"tdk":{"$":0},"team":{"$":0},"tech":{"$":0},"technology":{"$":0},"telecity":{"$":0},"telefonica":{"$":0},"temasek":{"$":0},"tennis":{"$":0},"teva":{"$":0},"thd":{"$":0},"theater":{"$":0},"theatre":{"$":0},"tiaa":{"$":0},"tickets":{"$":0},"tienda":{"$":0},"tiffany":{"$":0},"tips":{"$":0},"tires":{"$":0},"tirol":{"$":0},"tjmaxx":{"$":0},"tjx":{"$":0},"tkmaxx":{"$":0},"tmall":{"$":0},"today":{"$":0},"tokyo":{"$":0},"tools":{"$":0},"top":{"$":0},"toray":{"$":0},"toshiba":{"$":0},"total":{"$":0},"tours":{"$":0},"town":{"$":0},"toyota":{"$":0},"toys":{"$":0},"trade":{"$":0,"ybo":{"$":0}},"trading":{"$":0},"training":{"$":0},"travelchannel":{"$":0},"travelers":{"$":0},"travelersinsurance":{"$":0},"trust":{"$":0},"trv":{"$":0},"tube":{"$":0},"tui":{"$":0},"tunes":{"$":0},"tushu":{"$":0},"tvs":{"$":0},"ubank":{"$":0},"ubs":{"$":0},"uconnect":{"$":0},"unicom":{"$":0},"university":{"$":0},"uno":{"$":0},"uol":{"$":0},"ups":{"$":0},"vacations":{"$":0},"vana":{"$":0},"vanguard":{"$":0},"vegas":{"$":0},"ventures":{"$":0},"verisign":{"$":0},"versicherung":{"$":0},"vet":{"$":0},"viajes":{"$":0},"video":{"$":0},"vig":{"$":0},"viking":{"$":0},"villas":{"$":0},"vin":{"$":0},"vip":{"$":0},"virgin":{"$":0},"visa":{"$":0},"vision":{"$":0},"vista":{"$":0},"vistaprint":{"$":0},"viva":{"$":0},"vivo":{"$":0},"vlaanderen":{"$":0},"vodka":{"$":0},"volkswagen":{"$":0},"volvo":{"$":0},"vote":{"$":0},"voting":{"$":0},"voto":{"$":0},"voyage":{"$":0},"vuelos":{"$":0},"wales":{"$":0},"walmart":{"$":0},"walter":{"$":0},"wang":{"$":0},"wanggou":{"$":0},"warman":{"$":0},"watch":{"$":0},"watches":{"$":0},"weather":{"$":0},"weatherchannel":{"$":0},"webcam":{"$":0},"weber":{"$":0},"website":{"$":0},"wed":{"$":0},"wedding":{"$":0},"weibo":{"$":0},"weir":{"$":0},"whoswho":{"$":0},"wien":{"$":0},"wiki":{"$":0},"williamhill":{"$":0},"win":{"$":0},"windows":{"$":0},"wine":{"$":0},"winners":{"$":0},"wme":{"$":0},"wolterskluwer":{"$":0},"woodside":{"$":0},"work":{"$":0},"works":{"$":0},"world":{"$":0},"wow":{"$":0},"wtc":{"$":0},"wtf":{"$":0},"xbox":{"$":0},"xerox":{"$":0},"xfinity":{"$":0},"xihuan":{"$":0},"xin":{"$":0},"xn--11b4c3d":{"$":0},"xn--1ck2e1b":{"$":0},"xn--1qqw23a":{"$":0},"xn--30rr7y":{"$":0},"xn--3bst00m":{"$":0},"xn--3ds443g":{"$":0},"xn--3oq18vl8pn36a":{"$":0},"xn--3pxu8k":{"$":0},"xn--42c2d9a":{"$":0},"xn--45q11c":{"$":0},"xn--4gbrim":{"$":0},"xn--55qw42g":{"$":0},"xn--55qx5d":{"$":0},"xn--5su34j936bgsg":{"$":0},"xn--5tzm5g":{"$":0},"xn--6frz82g":{"$":0},"xn--6qq986b3xl":{"$":0},"xn--80adxhks":{"$":0},"xn--80aqecdr1a":{"$":0},"xn--80asehdb":{"$":0},"xn--80aswg":{"$":0},"xn--8y0a063a":{"$":0},"xn--9dbq2a":{"$":0},"xn--9et52u":{"$":0},"xn--9krt00a":{"$":0},"xn--b4w605ferd":{"$":0},"xn--bck1b9a5dre4c":{"$":0},"xn--c1avg":{"$":0},"xn--c2br7g":{"$":0},"xn--cck2b3b":{"$":0},"xn--cg4bki":{"$":0},"xn--czr694b":{"$":0},"xn--czrs0t":{"$":0},"xn--czru2d":{"$":0},"xn--d1acj3b":{"$":0},"xn--eckvdtc9d":{"$":0},"xn--efvy88h":{"$":0},"xn--estv75g":{"$":0},"xn--fct429k":{"$":0},"xn--fhbei":{"$":0},"xn--fiq228c5hs":{"$":0},"xn--fiq64b":{"$":0},"xn--fjq720a":{"$":0},"xn--flw351e":{"$":0},"xn--fzys8d69uvgm":{"$":0},"xn--g2xx48c":{"$":0},"xn--gckr3f0f":{"$":0},"xn--gk3at1e":{"$":0},"xn--hxt814e":{"$":0},"xn--i1b6b1a6a2e":{"$":0},"xn--imr513n":{"$":0},"xn--io0a7i":{"$":0},"xn--j1aef":{"$":0},"xn--jlq61u9w7b":{"$":0},"xn--jvr189m":{"$":0},"xn--kcrx77d1x4a":{"$":0},"xn--kpu716f":{"$":0},"xn--kput3i":{"$":0},"xn--mgba3a3ejt":{"$":0},"xn--mgba7c0bbn0a":{"$":0},"xn--mgbaakc7dvf":{"$":0},"xn--mgbab2bd":{"$":0},"xn--mgbb9fbpob":{"$":0},"xn--mgbca7dzdo":{"$":0},"xn--mgbi4ecexp":{"$":0},"xn--mgbt3dhd":{"$":0},"xn--mk1bu44c":{"$":0},"xn--mxtq1m":{"$":0},"xn--ngbc5azd":{"$":0},"xn--ngbe9e0a":{"$":0},"xn--ngbrx":{"$":0},"xn--nqv7f":{"$":0},"xn--nqv7fs00ema":{"$":0},"xn--nyqy26a":{"$":0},"xn--p1acf":{"$":0},"xn--pbt977c":{"$":0},"xn--pssy2u":{"$":0},"xn--q9jyb4c":{"$":0},"xn--qcka1pmc":{"$":0},"xn--rhqv96g":{"$":0},"xn--rovu88b":{"$":0},"xn--ses554g":{"$":0},"xn--t60b56a":{"$":0},"xn--tckwe":{"$":0},"xn--tiq49xqyj":{"$":0},"xn--unup4y":{"$":0},"xn--vermgensberater-ctb":{"$":0},"xn--vermgensberatung-pwb":{"$":0},"xn--vhquv":{"$":0},"xn--vuq861b":{"$":0},"xn--w4r85el8fhu5dnra":{"$":0},"xn--w4rs40l":{"$":0},"xn--xhq521b":{"$":0},"xn--zfr164b":{"$":0},"xperia":{"$":0},"xyz":{"$":0,"blogsite":{"$":0},"fhapp":{"$":0}},"yachts":{"$":0},"yahoo":{"$":0},"yamaxun":{"$":0},"yandex":{"$":0},"yodobashi":{"$":0},"yoga":{"$":0},"yokohama":{"$":0},"you":{"$":0},"youtube":{"$":0},"yun":{"$":0},"zappos":{"$":0},"zara":{"$":0},"zero":{"$":0},"zip":{"$":0},"zippo":{"$":0},"zone":{"$":0,"triton":{"*":{"$":0}},"lima":{"$":0}},"zuerich":{"$":0}}}
+},{}],30:[function(require,module,exports){
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+'use strict';
+
+var punycode = require('punycode');
+var util = require('./util');
+
+exports.parse = urlParse;
+exports.resolve = urlResolve;
+exports.resolveObject = urlResolveObject;
+exports.format = urlFormat;
+
+exports.Url = Url;
+
+function Url() {
+ this.protocol = null;
+ this.slashes = null;
+ this.auth = null;
+ this.host = null;
+ this.port = null;
+ this.hostname = null;
+ this.hash = null;
+ this.search = null;
+ this.query = null;
+ this.pathname = null;
+ this.path = null;
+ this.href = null;
+}
+
+// Reference: RFC 3986, RFC 1808, RFC 2396
+
+// define these here so at least they only have to be
+// compiled once on the first module load.
+var protocolPattern = /^([a-z0-9.+-]+:)/i,
+ portPattern = /:[0-9]*$/,
+
+ // Special case for a simple path URL
+ simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,
+
+ // RFC 2396: characters reserved for delimiting URLs.
+ // We actually just auto-escape these.
+ delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
+
+ // RFC 2396: characters not allowed for various reasons.
+ unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
+
+ // Allowed by RFCs, but cause of XSS attacks. Always escape these.
+ autoEscape = ['\''].concat(unwise),
+ // Characters that are never ever allowed in a hostname.
+ // Note that any invalid chars are also handled, but these
+ // are the ones that are *expected* to be seen, so we fast-path
+ // them.
+ nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
+ hostEndingChars = ['/', '?', '#'],
+ hostnameMaxLen = 255,
+ hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/,
+ hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/,
+ // protocols that can allow "unsafe" and "unwise" chars.
+ unsafeProtocol = {
+ 'javascript': true,
+ 'javascript:': true
+ },
+ // protocols that never have a hostname.
+ hostlessProtocol = {
+ 'javascript': true,
+ 'javascript:': true
+ },
+ // protocols that always contain a // bit.
+ slashedProtocol = {
+ 'http': true,
+ 'https': true,
+ 'ftp': true,
+ 'gopher': true,
+ 'file': true,
+ 'http:': true,
+ 'https:': true,
+ 'ftp:': true,
+ 'gopher:': true,
+ 'file:': true
+ },
+ querystring = require('querystring');
+
+function urlParse(url, parseQueryString, slashesDenoteHost) {
+ if (url && util.isObject(url) && url instanceof Url) return url;
+
+ var u = new Url;
+ u.parse(url, parseQueryString, slashesDenoteHost);
+ return u;
+}
+
+Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
+ if (!util.isString(url)) {
+ throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
+ }
+
+ // Copy chrome, IE, opera backslash-handling behavior.
+ // Back slashes before the query string get converted to forward slashes
+ // See: https://code.google.com/p/chromium/issues/detail?id=25916
+ var queryIndex = url.indexOf('?'),
+ splitter =
+ (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#',
+ uSplit = url.split(splitter),
+ slashRegex = /\\/g;
+ uSplit[0] = uSplit[0].replace(slashRegex, '/');
+ url = uSplit.join(splitter);
+
+ var rest = url;
+
+ // trim before proceeding.
+ // This is to support parse stuff like " http://foo.com \n"
+ rest = rest.trim();
+
+ if (!slashesDenoteHost && url.split('#').length === 1) {
+ // Try fast path regexp
+ var simplePath = simplePathPattern.exec(rest);
+ if (simplePath) {
+ this.path = rest;
+ this.href = rest;
+ this.pathname = simplePath[1];
+ if (simplePath[2]) {
+ this.search = simplePath[2];
+ if (parseQueryString) {
+ this.query = querystring.parse(this.search.substr(1));
+ } else {
+ this.query = this.search.substr(1);
+ }
+ } else if (parseQueryString) {
+ this.search = '';
+ this.query = {};
+ }
+ return this;
+ }
+ }
+
+ var proto = protocolPattern.exec(rest);
+ if (proto) {
+ proto = proto[0];
+ var lowerProto = proto.toLowerCase();
+ this.protocol = lowerProto;
+ rest = rest.substr(proto.length);
+ }
+
+ // figure out if it's got a host
+ // user@server is *always* interpreted as a hostname, and url
+ // resolution will treat //foo/bar as host=foo,path=bar because that's
+ // how the browser resolves relative URLs.
+ if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
+ var slashes = rest.substr(0, 2) === '//';
+ if (slashes && !(proto && hostlessProtocol[proto])) {
+ rest = rest.substr(2);
+ this.slashes = true;
+ }
+ }
+
+ if (!hostlessProtocol[proto] &&
+ (slashes || (proto && !slashedProtocol[proto]))) {
+
+ // there's a hostname.
+ // the first instance of /, ?, ;, or # ends the host.
+ //
+ // If there is an @ in the hostname, then non-host chars *are* allowed
+ // to the left of the last @ sign, unless some host-ending character
+ // comes *before* the @-sign.
+ // URLs are obnoxious.
+ //
+ // ex:
+ // http://a@b@c/ => user:a@b host:c
+ // http://a@b?@c => user:a host:c path:/?@c
+
+ // v0.12 TODO(isaacs): This is not quite how Chrome does things.
+ // Review our test case against browsers more comprehensively.
+
+ // find the first instance of any hostEndingChars
+ var hostEnd = -1;
+ for (var i = 0; i < hostEndingChars.length; i++) {
+ var hec = rest.indexOf(hostEndingChars[i]);
+ if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
+ hostEnd = hec;
+ }
+
+ // at this point, either we have an explicit point where the
+ // auth portion cannot go past, or the last @ char is the decider.
+ var auth, atSign;
+ if (hostEnd === -1) {
+ // atSign can be anywhere.
+ atSign = rest.lastIndexOf('@');
+ } else {
+ // atSign must be in auth portion.
+ // http://a@b/c@d => host:b auth:a path:/c@d
+ atSign = rest.lastIndexOf('@', hostEnd);
+ }
+
+ // Now we have a portion which is definitely the auth.
+ // Pull that off.
+ if (atSign !== -1) {
+ auth = rest.slice(0, atSign);
+ rest = rest.slice(atSign + 1);
+ this.auth = decodeURIComponent(auth);
+ }
+
+ // the host is the remaining to the left of the first non-host char
+ hostEnd = -1;
+ for (var i = 0; i < nonHostChars.length; i++) {
+ var hec = rest.indexOf(nonHostChars[i]);
+ if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
+ hostEnd = hec;
+ }
+ // if we still have not hit it, then the entire thing is a host.
+ if (hostEnd === -1)
+ hostEnd = rest.length;
+
+ this.host = rest.slice(0, hostEnd);
+ rest = rest.slice(hostEnd);
+
+ // pull out port.
+ this.parseHost();
+
+ // we've indicated that there is a hostname,
+ // so even if it's empty, it has to be present.
+ this.hostname = this.hostname || '';
+
+ // if hostname begins with [ and ends with ]
+ // assume that it's an IPv6 address.
+ var ipv6Hostname = this.hostname[0] === '[' &&
+ this.hostname[this.hostname.length - 1] === ']';
+
+ // validate a little.
+ if (!ipv6Hostname) {
+ var hostparts = this.hostname.split(/\./);
+ for (var i = 0, l = hostparts.length; i < l; i++) {
+ var part = hostparts[i];
+ if (!part) continue;
+ if (!part.match(hostnamePartPattern)) {
+ var newpart = '';
+ for (var j = 0, k = part.length; j < k; j++) {
+ if (part.charCodeAt(j) > 127) {
+ // we replace non-ASCII char with a temporary placeholder
+ // we need this to make sure size of hostname is not
+ // broken by replacing non-ASCII by nothing
+ newpart += 'x';
+ } else {
+ newpart += part[j];
+ }
+ }
+ // we test again with ASCII char only
+ if (!newpart.match(hostnamePartPattern)) {
+ var validParts = hostparts.slice(0, i);
+ var notHost = hostparts.slice(i + 1);
+ var bit = part.match(hostnamePartStart);
+ if (bit) {
+ validParts.push(bit[1]);
+ notHost.unshift(bit[2]);
+ }
+ if (notHost.length) {
+ rest = '/' + notHost.join('.') + rest;
+ }
+ this.hostname = validParts.join('.');
+ break;
+ }
+ }
+ }
+ }
+
+ if (this.hostname.length > hostnameMaxLen) {
+ this.hostname = '';
+ } else {
+ // hostnames are always lower case.
+ this.hostname = this.hostname.toLowerCase();
+ }
+
+ if (!ipv6Hostname) {
+ // IDNA Support: Returns a punycoded representation of "domain".
+ // It only converts parts of the domain name that
+ // have non-ASCII characters, i.e. it doesn't matter if
+ // you call it with a domain that already is ASCII-only.
+ this.hostname = punycode.toASCII(this.hostname);
+ }
+
+ var p = this.port ? ':' + this.port : '';
+ var h = this.hostname || '';
+ this.host = h + p;
+ this.href += this.host;
+
+ // strip [ and ] from the hostname
+ // the host field still retains them, though
+ if (ipv6Hostname) {
+ this.hostname = this.hostname.substr(1, this.hostname.length - 2);
+ if (rest[0] !== '/') {
+ rest = '/' + rest;
+ }
+ }
+ }
+
+ // now rest is set to the post-host stuff.
+ // chop off any delim chars.
+ if (!unsafeProtocol[lowerProto]) {
+
+ // First, make 100% sure that any "autoEscape" chars get
+ // escaped, even if encodeURIComponent doesn't think they
+ // need to be.
+ for (var i = 0, l = autoEscape.length; i < l; i++) {
+ var ae = autoEscape[i];
+ if (rest.indexOf(ae) === -1)
+ continue;
+ var esc = encodeURIComponent(ae);
+ if (esc === ae) {
+ esc = escape(ae);
+ }
+ rest = rest.split(ae).join(esc);
+ }
+ }
+
+
+ // chop off from the tail first.
+ var hash = rest.indexOf('#');
+ if (hash !== -1) {
+ // got a fragment string.
+ this.hash = rest.substr(hash);
+ rest = rest.slice(0, hash);
+ }
+ var qm = rest.indexOf('?');
+ if (qm !== -1) {
+ this.search = rest.substr(qm);
+ this.query = rest.substr(qm + 1);
+ if (parseQueryString) {
+ this.query = querystring.parse(this.query);
+ }
+ rest = rest.slice(0, qm);
+ } else if (parseQueryString) {
+ // no query string, but parseQueryString still requested
+ this.search = '';
+ this.query = {};
+ }
+ if (rest) this.pathname = rest;
+ if (slashedProtocol[lowerProto] &&
+ this.hostname && !this.pathname) {
+ this.pathname = '/';
+ }
+
+ //to support http.request
+ if (this.pathname || this.search) {
+ var p = this.pathname || '';
+ var s = this.search || '';
+ this.path = p + s;
+ }
+
+ // finally, reconstruct the href based on what has been validated.
+ this.href = this.format();
+ return this;
+};
+
+// format a parsed object into a url string
+function urlFormat(obj) {
+ // ensure it's an object, and not a string url.
+ // If it's an obj, this is a no-op.
+ // this way, you can call url_format() on strings
+ // to clean up potentially wonky urls.
+ if (util.isString(obj)) obj = urlParse(obj);
+ if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
+ return obj.format();
+}
+
+Url.prototype.format = function() {
+ var auth = this.auth || '';
+ if (auth) {
+ auth = encodeURIComponent(auth);
+ auth = auth.replace(/%3A/i, ':');
+ auth += '@';
+ }
+
+ var protocol = this.protocol || '',
+ pathname = this.pathname || '',
+ hash = this.hash || '',
+ host = false,
+ query = '';
+
+ if (this.host) {
+ host = auth + this.host;
+ } else if (this.hostname) {
+ host = auth + (this.hostname.indexOf(':') === -1 ?
+ this.hostname :
+ '[' + this.hostname + ']');
+ if (this.port) {
+ host += ':' + this.port;
+ }
+ }
+
+ if (this.query &&
+ util.isObject(this.query) &&
+ Object.keys(this.query).length) {
+ query = querystring.stringify(this.query);
+ }
+
+ var search = this.search || (query && ('?' + query)) || '';
+
+ if (protocol && protocol.substr(-1) !== ':') protocol += ':';
+
+ // only the slashedProtocols get the //. Not mailto:, xmpp:, etc.
+ // unless they had them to begin with.
+ if (this.slashes ||
+ (!protocol || slashedProtocol[protocol]) && host !== false) {
+ host = '//' + (host || '');
+ if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
+ } else if (!host) {
+ host = '';
+ }
+
+ if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
+ if (search && search.charAt(0) !== '?') search = '?' + search;
+
+ pathname = pathname.replace(/[?#]/g, function(match) {
+ return encodeURIComponent(match);
+ });
+ search = search.replace('#', '%23');
+
+ return protocol + host + pathname + search + hash;
+};
+
+function urlResolve(source, relative) {
+ return urlParse(source, false, true).resolve(relative);
+}
+
+Url.prototype.resolve = function(relative) {
+ return this.resolveObject(urlParse(relative, false, true)).format();
+};
+
+function urlResolveObject(source, relative) {
+ if (!source) return relative;
+ return urlParse(source, false, true).resolveObject(relative);
+}
+
+Url.prototype.resolveObject = function(relative) {
+ if (util.isString(relative)) {
+ var rel = new Url();
+ rel.parse(relative, false, true);
+ relative = rel;
+ }
+
+ var result = new Url();
+ var tkeys = Object.keys(this);
+ for (var tk = 0; tk < tkeys.length; tk++) {
+ var tkey = tkeys[tk];
+ result[tkey] = this[tkey];
+ }
+
+ // hash is always overridden, no matter what.
+ // even href="" will remove it.
+ result.hash = relative.hash;
+
+ // if the relative url is empty, then there's nothing left to do here.
+ if (relative.href === '') {
+ result.href = result.format();
+ return result;
+ }
+
+ // hrefs like //foo/bar always cut to the protocol.
+ if (relative.slashes && !relative.protocol) {
+ // take everything except the protocol from relative
+ var rkeys = Object.keys(relative);
+ for (var rk = 0; rk < rkeys.length; rk++) {
+ var rkey = rkeys[rk];
+ if (rkey !== 'protocol')
+ result[rkey] = relative[rkey];
+ }
+
+ //urlParse appends trailing / to urls like http://www.example.com
+ if (slashedProtocol[result.protocol] &&
+ result.hostname && !result.pathname) {
+ result.path = result.pathname = '/';
+ }
+
+ result.href = result.format();
+ return result;
+ }
+
+ if (relative.protocol && relative.protocol !== result.protocol) {
+ // if it's a known url protocol, then changing
+ // the protocol does weird things
+ // first, if it's not file:, then we MUST have a host,
+ // and if there was a path
+ // to begin with, then we MUST have a path.
+ // if it is file:, then the host is dropped,
+ // because that's known to be hostless.
+ // anything else is assumed to be absolute.
+ if (!slashedProtocol[relative.protocol]) {
+ var keys = Object.keys(relative);
+ for (var v = 0; v < keys.length; v++) {
+ var k = keys[v];
+ result[k] = relative[k];
+ }
+ result.href = result.format();
+ return result;
+ }
+
+ result.protocol = relative.protocol;
+ if (!relative.host && !hostlessProtocol[relative.protocol]) {
+ var relPath = (relative.pathname || '').split('/');
+ while (relPath.length && !(relative.host = relPath.shift()));
+ if (!relative.host) relative.host = '';
+ if (!relative.hostname) relative.hostname = '';
+ if (relPath[0] !== '') relPath.unshift('');
+ if (relPath.length < 2) relPath.unshift('');
+ result.pathname = relPath.join('/');
+ } else {
+ result.pathname = relative.pathname;
+ }
+ result.search = relative.search;
+ result.query = relative.query;
+ result.host = relative.host || '';
+ result.auth = relative.auth;
+ result.hostname = relative.hostname || relative.host;
+ result.port = relative.port;
+ // to support http.request
+ if (result.pathname || result.search) {
+ var p = result.pathname || '';
+ var s = result.search || '';
+ result.path = p + s;
+ }
+ result.slashes = result.slashes || relative.slashes;
+ result.href = result.format();
+ return result;
+ }
+
+ var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
+ isRelAbs = (
+ relative.host ||
+ relative.pathname && relative.pathname.charAt(0) === '/'
+ ),
+ mustEndAbs = (isRelAbs || isSourceAbs ||
+ (result.host && relative.pathname)),
+ removeAllDots = mustEndAbs,
+ srcPath = result.pathname && result.pathname.split('/') || [],
+ relPath = relative.pathname && relative.pathname.split('/') || [],
+ psychotic = result.protocol && !slashedProtocol[result.protocol];
+
+ // if the url is a non-slashed url, then relative
+ // links like ../.. should be able
+ // to crawl up to the hostname, as well. This is strange.
+ // result.protocol has already been set by now.
+ // Later on, put the first path part into the host field.
+ if (psychotic) {
+ result.hostname = '';
+ result.port = null;
+ if (result.host) {
+ if (srcPath[0] === '') srcPath[0] = result.host;
+ else srcPath.unshift(result.host);
+ }
+ result.host = '';
+ if (relative.protocol) {
+ relative.hostname = null;
+ relative.port = null;
+ if (relative.host) {
+ if (relPath[0] === '') relPath[0] = relative.host;
+ else relPath.unshift(relative.host);
+ }
+ relative.host = null;
+ }
+ mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
+ }
+
+ if (isRelAbs) {
+ // it's absolute.
+ result.host = (relative.host || relative.host === '') ?
+ relative.host : result.host;
+ result.hostname = (relative.hostname || relative.hostname === '') ?
+ relative.hostname : result.hostname;
+ result.search = relative.search;
+ result.query = relative.query;
+ srcPath = relPath;
+ // fall through to the dot-handling below.
+ } else if (relPath.length) {
+ // it's relative
+ // throw away the existing file, and take the new path instead.
+ if (!srcPath) srcPath = [];
+ srcPath.pop();
+ srcPath = srcPath.concat(relPath);
+ result.search = relative.search;
+ result.query = relative.query;
+ } else if (!util.isNullOrUndefined(relative.search)) {
+ // just pull out the search.
+ // like href='?foo'.
+ // Put this after the other two cases because it simplifies the booleans
+ if (psychotic) {
+ result.hostname = result.host = srcPath.shift();
+ //occationaly the auth can get stuck only in host
+ //this especially happens in cases like
+ //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
+ var authInHost = result.host && result.host.indexOf('@') > 0 ?
+ result.host.split('@') : false;
+ if (authInHost) {
+ result.auth = authInHost.shift();
+ result.host = result.hostname = authInHost.shift();
+ }
+ }
+ result.search = relative.search;
+ result.query = relative.query;
+ //to support http.request
+ if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
+ result.path = (result.pathname ? result.pathname : '') +
+ (result.search ? result.search : '');
+ }
+ result.href = result.format();
+ return result;
+ }
+
+ if (!srcPath.length) {
+ // no path at all. easy.
+ // we've already handled the other stuff above.
+ result.pathname = null;
+ //to support http.request
+ if (result.search) {
+ result.path = '/' + result.search;
+ } else {
+ result.path = null;
+ }
+ result.href = result.format();
+ return result;
+ }
+
+ // if a url ENDs in . or .., then it must get a trailing slash.
+ // however, if it ends in anything else non-slashy,
+ // then it must NOT get a trailing slash.
+ var last = srcPath.slice(-1)[0];
+ var hasTrailingSlash = (
+ (result.host || relative.host || srcPath.length > 1) &&
+ (last === '.' || last === '..') || last === '');
+
+ // strip single dots, resolve double dots to parent dir
+ // if the path tries to go above the root, `up` ends up > 0
+ var up = 0;
+ for (var i = srcPath.length; i >= 0; i--) {
+ last = srcPath[i];
+ if (last === '.') {
+ srcPath.splice(i, 1);
+ } else if (last === '..') {
+ srcPath.splice(i, 1);
+ up++;
+ } else if (up) {
+ srcPath.splice(i, 1);
+ up--;
+ }
+ }
+
+ // if the path is allowed to go above the root, restore leading ..s
+ if (!mustEndAbs && !removeAllDots) {
+ for (; up--; up) {
+ srcPath.unshift('..');
+ }
+ }
+
+ if (mustEndAbs && srcPath[0] !== '' &&
+ (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
+ srcPath.unshift('');
+ }
+
+ if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
+ srcPath.push('');
+ }
+
+ var isAbsolute = srcPath[0] === '' ||
+ (srcPath[0] && srcPath[0].charAt(0) === '/');
+
+ // put the host back
+ if (psychotic) {
+ result.hostname = result.host = isAbsolute ? '' :
+ srcPath.length ? srcPath.shift() : '';
+ //occationaly the auth can get stuck only in host
+ //this especially happens in cases like
+ //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
+ var authInHost = result.host && result.host.indexOf('@') > 0 ?
+ result.host.split('@') : false;
+ if (authInHost) {
+ result.auth = authInHost.shift();
+ result.host = result.hostname = authInHost.shift();
+ }
+ }
+
+ mustEndAbs = mustEndAbs || (result.host && srcPath.length);
+
+ if (mustEndAbs && !isAbsolute) {
+ srcPath.unshift('');
+ }
+
+ if (!srcPath.length) {
+ result.pathname = null;
+ result.path = null;
+ } else {
+ result.pathname = srcPath.join('/');
+ }
+
+ //to support request.http
+ if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
+ result.path = (result.pathname ? result.pathname : '') +
+ (result.search ? result.search : '');
+ }
+ result.auth = relative.auth || result.auth;
+ result.slashes = result.slashes || relative.slashes;
+ result.href = result.format();
+ return result;
+};
+
+Url.prototype.parseHost = function() {
+ var host = this.host;
+ var port = portPattern.exec(host);
+ if (port) {
+ port = port[0];
+ if (port !== ':') {
+ this.port = port.substr(1);
+ }
+ host = host.substr(0, host.length - port.length);
+ }
+ if (host) this.hostname = host;
+};
+
+},{"./util":31,"punycode":13,"querystring":16}],31:[function(require,module,exports){
+'use strict';
+
+module.exports = {
+ isString: function(arg) {
+ return typeof(arg) === 'string';
+ },
+ isObject: function(arg) {
+ return typeof(arg) === 'object' && arg !== null;
+ },
+ isNull: function(arg) {
+ return arg === null;
+ },
+ isNullOrUndefined: function(arg) {
+ return arg == null;
+ }
+};
+
+},{}]},{},[1]);
diff --git a/debian/js/inject.dist.js b/debian/js/inject.dist.js
new file mode 100644
index 0000000..9119888
--- /dev/null
+++ b/debian/js/inject.dist.js
@@ -0,0 +1,417 @@
+(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
+(function() {
+ const FORM_MARKERS = ["login", "log-in", "log_in", "signin", "sign-in", "sign_in"];
+ const OPENID_FIELDS = {
+ selectors: ["input[name*=openid i]", "input[id*=openid i]", "input[class*=openid i]"],
+ types: ["text"]
+ };
+ const USERNAME_FIELDS = {
+ selectors: [
+ "input[name*=login i]",
+ "input[name*=user i]",
+ "input[name*=email i]",
+ "input[id*=login i]",
+ "input[id*=user i]",
+ "input[id*=email i]",
+ "input[class*=login i]",
+ "input[class*=user i]",
+ "input[class*=email i]",
+ "input[type=email i]",
+ "input[type=text i]",
+ "input[type=tel i]"
+ ],
+ types: ["email", "text", "tel"]
+ };
+ const PASSWORD_FIELDS = {
+ selectors: ["input[type=password i]"]
+ };
+ const INPUT_FIELDS = {
+ selectors: PASSWORD_FIELDS.selectors
+ .concat(USERNAME_FIELDS.selectors)
+ .concat(OPENID_FIELDS.selectors)
+ };
+ const SUBMIT_FIELDS = {
+ selectors: [
+ "[type=submit i]",
+ "button[name*=login i]",
+ "button[name*=log-in i]",
+ "button[name*=log_in i]",
+ "button[name*=signin i]",
+ "button[name*=sign-in i]",
+ "button[name*=sign_in i]",
+ "button[id*=login i]",
+ "button[id*=log-in i]",
+ "button[id*=log_in i]",
+ "button[id*=signin i]",
+ "button[id*=sign-in i]",
+ "button[id*=sign_in i]",
+ "button[class*=login i]",
+ "button[class*=log-in i]",
+ "button[class*=log_in i]",
+ "button[class*=signin i]",
+ "button[class*=sign-in i]",
+ "button[class*=sign_in i]",
+ "input[type=button i][name*=login i]",
+ "input[type=button i][name*=log-in i]",
+ "input[type=button i][name*=log_in i]",
+ "input[type=button i][name*=signin i]",
+ "input[type=button i][name*=sign-in i]",
+ "input[type=button i][name*=sign_in i]",
+ "input[type=button i][id*=login i]",
+ "input[type=button i][id*=log-in i]",
+ "input[type=button i][id*=log_in i]",
+ "input[type=button i][id*=signin i]",
+ "input[type=button i][id*=sign-in i]",
+ "input[type=button i][id*=sign_in i]",
+ "input[type=button i][class*=login i]",
+ "input[type=button i][class*=log-in i]",
+ "input[type=button i][class*=log_in i]",
+ "input[type=button i][class*=signin i]",
+ "input[type=button i][class*=sign-in i]",
+ "input[type=button i][class*=sign_in i]"
+ ]
+ };
+
+ /**
+ * Fill password
+ *
+ * @since 3.0.0
+ *
+ * @param object request Form fill request
+ * @return object result of filling a form
+ */
+ function fillLogin(request) {
+ var result = {
+ filledFields: [],
+ foreignFill: undefined
+ };
+
+ // get the login form
+ let loginForm = undefined;
+ if (request.fields.includes("openid")) {
+ // this is an attempt to fill a form containing only openid field
+ loginForm = form(OPENID_FIELDS);
+ } else {
+ // this is an attempt to fill a regular login form
+ loginForm = form(INPUT_FIELDS);
+ }
+
+ // don't attempt to fill non-secret forms unless non-secret filling is allowed
+ if (!request.allowNoSecret && !find(PASSWORD_FIELDS, loginForm)) {
+ return result;
+ }
+
+ // ensure the origin is the same, or ask the user for permissions to continue
+ if (window.location.origin !== request.origin) {
+ if (!request.allowForeign || request.foreignFills[window.location.origin] === false) {
+ return result;
+ }
+ var message =
+ "You have requested to fill login credentials into an embedded document from a " +
+ "different origin than the main document in this tab. Do you wish to proceed?\n\n" +
+ `Tab origin: ${request.origin}\n` +
+ `Embedded origin: ${window.location.origin}`;
+ if (request.foreignFills[window.location.origin] !== true) {
+ result.foreignOrigin = window.location.origin;
+ result.foreignFill = confirm(message);
+ if (!result.foreignFill) {
+ return result;
+ }
+ }
+ }
+
+ // fill login field
+ if (
+ request.fields.includes("login") &&
+ update(USERNAME_FIELDS, request.login.fields.login, loginForm)
+ ) {
+ result.filledFields.push("login");
+ }
+
+ // fill secret field
+ if (
+ request.fields.includes("secret") &&
+ update(PASSWORD_FIELDS, request.login.fields.secret, loginForm)
+ ) {
+ result.filledFields.push("secret");
+ }
+
+ // fill openid field
+ if (
+ request.fields.includes("openid") &&
+ update(OPENID_FIELDS, request.login.fields.openid, loginForm)
+ ) {
+ result.filledFields.push("openid");
+ }
+
+ // finished filling things successfully
+ return result;
+ }
+
+ /**
+ * Focus submit button, and maybe click on it (based on user settings)
+ *
+ * @since 3.0.0
+ *
+ * @param object request Form fill request
+ * @return object result of focusing or submitting a form
+ */
+ function focusOrSubmit(request) {
+ var result = {
+ needPressEnter: false
+ };
+
+ // get the login form
+ let loginForm = undefined;
+ if (request.filledFields.includes("openid")) {
+ // this is an attempt to focus or submit a form containing only openid field
+ loginForm = form(OPENID_FIELDS);
+ } else {
+ // this is an attempt to focus or submit a regular login form
+ loginForm = form(INPUT_FIELDS);
+ }
+
+ // ensure the origin is the same or allowed
+ if (window.location.origin !== request.origin) {
+ if (!request.allowForeign || request.foreignFills[window.location.origin] === false) {
+ return;
+ }
+ }
+
+ // check for multiple password fields in the login form
+ var password_inputs = queryAllVisible(document, PASSWORD_FIELDS, loginForm);
+ if (password_inputs.length > 1) {
+ // There is likely a field asking for OTP code, so do not submit form just yet
+ password_inputs[1].select();
+ } else {
+ // try to locate the submit button
+ var submit = find(SUBMIT_FIELDS, loginForm);
+
+ // Try to submit the form, or focus on the submit button (based on user settings)
+ if (submit) {
+ if (request.autoSubmit) {
+ submit.click();
+ } else {
+ submit.focus();
+ }
+ } else {
+ // There is no submit button.
+ if (request.autoSubmit) {
+ // signal background script that we want it to press Enter for us
+ result.needPressEnter = true;
+ }
+ // We need to keep focus somewhere within the form, so that Enter hopefully submits the form.
+ for (let selectors of [OPENID_FIELDS, PASSWORD_FIELDS, USERNAME_FIELDS]) {
+ let field = find(selectors, loginForm);
+ if (field) {
+ field.focus();
+ break;
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Query all visible elements
+ *
+ * @since 3.0.0
+ *
+ * @param DOMElement parent Parent element to query
+ * @param object field Field to search for
+ * @param DOMElement form Search only within this form
+ * @return array List of search results
+ */
+ function queryAllVisible(parent, field, form) {
+ const result = [];
+ for (let i = 0; i < field.selectors.length; i++) {
+ let elems = parent.querySelectorAll(field.selectors[i]);
+ for (let j = 0; j < elems.length; j++) {
+ let elem = elems[j];
+ // Select only elements from specified form
+ if (form && form != elem.form) {
+ continue;
+ }
+ // Ignore disabled fields
+ if (elem.disabled) {
+ continue;
+ }
+ // Elem or its parent has a style 'display: none',
+ // or it is just too narrow to be a real field (a trap for spammers?).
+ if (elem.offsetWidth < 30 || elem.offsetHeight < 10) {
+ continue;
+ }
+ // We may have a whitelist of acceptable field types. If so, skip elements of a different type.
+ if (field.types && field.types.indexOf(elem.type.toLowerCase()) < 0) {
+ continue;
+ }
+ // Elem takes space on the screen, but it or its parent is hidden with a visibility style.
+ let style = window.getComputedStyle(elem);
+ if (style.visibility == "hidden") {
+ continue;
+ }
+ // Elem is outside of the boundaries of the visible viewport.
+ let rect = elem.getBoundingClientRect();
+ if (
+ rect.x + rect.width < 0 ||
+ rect.y + rect.height < 0 ||
+ (rect.x > window.innerWidth || rect.y > window.innerHeight)
+ ) {
+ continue;
+ }
+ // Elem is hidden by its or or its parent's opacity rules
+ const OPACITY_LIMIT = 0.1;
+ let opacity = 1;
+ for (
+ let testElem = elem;
+ opacity >= OPACITY_LIMIT && testElem && testElem.nodeType === Node.ELEMENT_NODE;
+ testElem = testElem.parentNode
+ ) {
+ let style = window.getComputedStyle(testElem);
+ if (style.opacity) {
+ opacity *= parseFloat(style.opacity);
+ }
+ }
+ if (opacity < OPACITY_LIMIT) {
+ continue;
+ }
+ // This element is visible, will use it.
+ result.push(elem);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Query first visible element
+ *
+ * @since 3.0.0
+ *
+ * @param DOMElement parent Parent element to query
+ * @param object field Field to search for
+ * @param DOMElement form Search only within this form
+ * @return array First search result
+ */
+ function queryFirstVisible(parent, field, form) {
+ var elems = queryAllVisible(parent, field, form);
+ return elems.length > 0 ? elems[0] : undefined;
+ }
+
+ /**
+ * Detect the login form
+ *
+ * @since 3.0.0
+ *
+ * @param array selectors Selectors to use to find the right form
+ * @return The login form
+ */
+ function form(selectors) {
+ const elems = queryAllVisible(document, selectors, undefined);
+ const forms = [];
+ for (let elem of elems) {
+ const form = elem.form;
+ if (form && forms.indexOf(form) < 0) {
+ forms.push(form);
+ }
+ }
+
+ // Try to filter only forms that have some identifying marker
+ const markedForms = [];
+ for (let form of forms) {
+ const props = ["id", "name", "class", "action"];
+ for (let marker of FORM_MARKERS) {
+ for (let prop of props) {
+ let propValue = form.getAttribute(prop) || "";
+ if (propValue.toLowerCase().indexOf(marker) > -1) {
+ markedForms.push(form);
+ }
+ }
+ }
+ }
+
+ // Try to filter only forms that have a password field
+ const formsWithPassword = [];
+ for (let form of markedForms) {
+ if (find(PASSWORD_FIELDS, form)) {
+ formsWithPassword.push(form);
+ }
+ }
+
+ // Give up and return the first available form, if any
+ if (formsWithPassword.length > 0) {
+ return formsWithPassword[0];
+ }
+ if (markedForms.length > 0) {
+ return markedForms[0];
+ }
+ if (forms.length > 0) {
+ return forms[0];
+ }
+ return undefined;
+ }
+
+ /**
+ * Find a form field
+ *
+ * @since 3.0.0
+ *
+ * @param object field Field to search for
+ * @param DOMElement form Form to search in
+ * @return DOMElement First matching form field
+ */
+ function find(field, form) {
+ return queryFirstVisible(document, field, form);
+ }
+
+ /**
+ * Update a form field value
+ *
+ * @since 3.0.0
+ *
+ * @param object field Field to update
+ * @param string value Value to set
+ * @param DOMElement form Form for which to set the given field
+ * @return bool Whether the update succeeded
+ */
+ function update(field, value, form) {
+ if (!value.length) {
+ return false;
+ }
+
+ // Focus the input element first
+ var el = find(field, form);
+ if (!el) {
+ return false;
+ }
+ var eventNames = ["click", "focus"];
+ eventNames.forEach(function(eventName) {
+ el.dispatchEvent(new Event(eventName, { bubbles: true }));
+ });
+
+ // Focus may have triggered unvealing a true input, find it again
+ el = find(field, form);
+ if (!el) {
+ return false;
+ }
+
+ // Now set the value and unfocus
+ el.setAttribute("value", value);
+ el.value = value;
+ var eventNames = ["keypress", "keydown", "keyup", "input", "blur", "change"];
+ eventNames.forEach(function(eventName) {
+ el.dispatchEvent(new Event(eventName, { bubbles: true }));
+ });
+ return true;
+ }
+
+ // set window object
+ window.browserpass = {
+ fillLogin: fillLogin,
+ focusOrSubmit: focusOrSubmit
+ };
+})();
+
+},{}]},{},[1]);
+;undefined
diff --git a/debian/js/options.dist.js b/debian/js/options.dist.js
new file mode 100644
index 0000000..1783526
--- /dev/null
+++ b/debian/js/options.dist.js
@@ -0,0 +1,2138 @@
+(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
+/** Wrap an API that uses callbacks with Promises
+ * This expects the pattern function withCallback(arg1, arg2, ... argN, callback)
+ * @author Keith Henry <keith.henry@evolutionjobs.co.uk>
+ * @license MIT */
+(function () {
+ 'use strict';
+
+ /** Wrap a function with a callback with a Promise.
+ * @param {function} f The function to wrap, should be pattern: withCallback(arg1, arg2, ... argN, callback).
+ * @param {function} parseCB Optional function to parse multiple callback parameters into a single object.
+ * @returns {Promise} Promise that resolves when the callback fires. */
+ function promisify(f, parseCB) {
+ return (...args) => {
+ let safeArgs = args;
+ let callback;
+ // The Chrome API functions all use arguments, so we can't use f.length to check
+
+ // If there is a last arg
+ if (args && args.length > 0) {
+
+ // ... and the last arg is a function
+ const last = args[args.length - 1];
+ if (typeof last === 'function') {
+ // Trim the last callback arg if it's been passed
+ safeArgs = args.slice(0, args.length - 1);
+ callback = last;
+ }
+ }
+
+ // Return a promise
+ return new Promise((resolve, reject) => {
+ try {
+ // Try to run the original function, with the trimmed args list
+ f(...safeArgs, (...cbArgs) => {
+
+ // If a callback was passed at the end of the original arguments
+ if (callback) {
+ // Don't allow a bug in the callback to stop the promise resolving
+ try { callback(...cbArgs); }
+ catch (cbErr) { reject(cbErr); }
+ }
+
+ // Chrome extensions always fire the callback, but populate chrome.runtime.lastError with exception details
+ if (chrome.runtime.lastError)
+ // Return as an error for the awaited catch block
+ reject(new Error(chrome.runtime.lastError.message || `Error thrown by API ${chrome.runtime.lastError}`));
+ else {
+ if (parseCB) {
+ const cbObj = parseCB(...cbArgs);
+ resolve(cbObj);
+ }
+ else if (!cbArgs || cbArgs.length === 0)
+ resolve();
+ else if (cbArgs.length === 1)
+ resolve(cbArgs[0]);
+ else
+ resolve(cbArgs);
+ }
+ });
+ }
+ catch (err) { reject(err); }
+ });
+ }
+ }
+
+ /** Promisify all the known functions in the map
+ * @param {object} api The Chrome native API to extend
+ * @param {Array} apiMap Collection of sub-API and functions to promisify */
+ function applyMap(api, apiMap) {
+ if (!api)
+ // Not supported by current permissions
+ return;
+
+ for (let funcDef of apiMap) {
+ let funcName;
+ if (typeof funcDef === 'string')
+ funcName = funcDef;
+ else {
+ funcName = funcDef.n;
+ }
+
+ if (!api.hasOwnProperty(funcName))
+ // Member not in API
+ continue;
+
+ const m = api[funcName];
+ if (typeof m === 'function')
+ // This is a function, wrap in a promise
+ api[funcName] = promisify(m.bind(api), funcDef.cb);
+ else
+ // Sub-API, recurse this func with the mapped props
+ applyMap(m, funcDef.props);
+ }
+ }
+
+ /** Apply promise-maps to the Chrome native API.
+ * @param {object} apiMaps The API to apply. */
+ function applyMaps(apiMaps) {
+ for (let apiName in apiMaps) {
+ const callbackApi = chrome[apiName];
+ if (!callbackApi)
+ // Not supported by current permissions
+ continue;
+
+ const apiMap = apiMaps[apiName];
+ applyMap(callbackApi, apiMap);
+ }
+ }
+
+ // accessibilityFeatures https://developer.chrome.com/extensions/accessibilityFeatures
+ const knownA11ySetting = ['get', 'set', 'clear'];
+
+ // ContentSetting https://developer.chrome.com/extensions/contentSettings#type-ContentSetting
+ const knownInContentSetting = ['clear', 'get', 'set', 'getResourceIdentifiers'];
+
+ // StorageArea https://developer.chrome.com/extensions/storage#type-StorageArea
+ const knownInStorageArea = ['get', 'getBytesInUse', 'set', 'remove', 'clear'];
+
+ /** Map of API functions that follow the callback pattern that we can 'promisify' */
+ applyMaps({
+ accessibilityFeatures: [ // Todo: this should extend AccessibilityFeaturesSetting.prototype instead
+ { n: 'spokenFeedback', props: knownA11ySetting },
+ { n: 'largeCursor', props: knownA11ySetting },
+ { n: 'stickyKeys', props: knownA11ySetting },
+ { n: 'highContrast', props: knownA11ySetting },
+ { n: 'screenMagnifier', props: knownA11ySetting },
+ { n: 'autoclick', props: knownA11ySetting },
+ { n: 'virtualKeyboard', props: knownA11ySetting },
+ { n: 'animationPolicy', props: knownA11ySetting }],
+ alarms: ['get', 'getAll', 'clear', 'clearAll'],
+ bookmarks: [
+ 'get', 'getChildren', 'getRecent', 'getTree', 'getSubTree',
+ 'search', 'create', 'move', 'update', 'remove', 'removeTree'],
+ browser: ['openTab'],
+ browserAction: [
+ 'getTitle', 'setIcon', 'getPopup', 'getBadgeText', 'getBadgeBackgroundColor'],
+ browsingData: [
+ 'settings', 'remove', 'removeAppcache', 'removeCache',
+ 'removeCookies', 'removeDownloads', 'removeFileSystems',
+ 'removeFormData', 'removeHistory', 'removeIndexedDB',
+ 'removeLocalStorage', 'removePluginData', 'removePasswords',
+ 'removeWebSQL'],
+ commands: ['getAll'],
+ contentSettings: [ // Todo: this should extend ContentSetting.prototype instead
+ { n: 'cookies', props: knownInContentSetting },
+ { n: 'images', props: knownInContentSetting },
+ { n: 'javascript', props: knownInContentSetting },
+ { n: 'location', props: knownInContentSetting },
+ { n: 'plugins', props: knownInContentSetting },
+ { n: 'popups', props: knownInContentSetting },
+ { n: 'notifications', props: knownInContentSetting },
+ { n: 'fullscreen', props: knownInContentSetting },
+ { n: 'mouselock', props: knownInContentSetting },
+ { n: 'microphone', props: knownInContentSetting },
+ { n: 'camera', props: knownInContentSetting },
+ { n: 'unsandboxedPlugins', props: knownInContentSetting },
+ { n: 'automaticDownloads', props: knownInContentSetting }],
+ contextMenus: ['create', 'update', 'remove', 'removeAll'],
+ cookies: ['get', 'getAll', 'set', 'remove', 'getAllCookieStores'],
+ debugger: ['attach', 'detach', 'sendCommand', 'getTargets'],
+ desktopCapture: ['chooseDesktopMedia'],
+ // TODO: devtools.*
+ documentScan: ['scan'],
+ downloads: [
+ 'download', 'search', 'pause', 'resume', 'cancel',
+ 'getFileIcon', 'erase', 'removeFile', 'acceptDanger'],
+ enterprise: [{ n: 'platformKeys', props: ['getToken', 'getCertificates', 'importCertificate', 'removeCertificate'] }],
+ extension: ['isAllowedIncognitoAccess', 'isAllowedFileSchemeAccess'], // mostly deprecated in favour of runtime
+ fileBrowserHandler: ['selectFile'],
+ fileSystemProvider: ['mount', 'unmount', 'getAll', 'get', 'notify'],
+ fontSettings: [
+ 'setDefaultFontSize', 'getFont', 'getDefaultFontSize', 'getMinimumFontSize',
+ 'setMinimumFontSize', 'getDefaultFixedFontSize', 'clearDefaultFontSize',
+ 'setDefaultFixedFontSize', 'clearFont', 'setFont', 'clearMinimumFontSize',
+ 'getFontList', 'clearDefaultFixedFontSize'],
+ gcm: ['register', 'unregister', 'send'],
+ history: ['search', 'getVisits', 'addUrl', 'deleteUrl', 'deleteRange', 'deleteAll'],
+ i18n: ['getAcceptLanguages', 'detectLanguage'],
+ identity: [
+ 'getAuthToken', 'getProfileUserInfo', 'removeCachedAuthToken', 'launchWebAuthFlow'],
+ idle: ['queryState'],
+ input: [{
+ n: 'ime', props: [
+ 'setMenuItems', 'commitText', 'setCandidates', 'setComposition', 'updateMenuItems',
+ 'setCandidateWindowProperties', 'clearComposition', 'setCursorPosition', 'sendKeyEvents',
+ 'deleteSurroundingText']
+ }],
+ management: [
+ 'setEnabled', 'getPermissionWarningsById', 'get', 'getAll',
+ 'getPermissionWarningsByManifest', 'launchApp', 'uninstall', 'getSelf',
+ 'uninstallSelf', 'createAppShortcut', 'setLaunchType', 'generateAppForLink'],
+ networking: [{ n: 'config', props: ['setNetworkFilter', 'finishAuthentication'] }],
+ notifications: ['create', 'update', 'clear', 'getAll', 'getPermissionLevel'],
+ pageAction: ['getTitle', 'setIcon', 'getPopup'],
+ pageCapture: ['saveAsMHTML'],
+ permissions: ['getAll', 'contains', 'request', 'remove'],
+ platformKeys: ['selectClientCertificates', 'verifyTLSServerCertificate',
+ { n: "getKeyPair", cb: (publicKey, privateKey) => { return { publicKey, privateKey }; } }],
+ runtime: [
+ 'getBackgroundPage', 'openOptionsPage', 'setUninstallURL',
+ 'restartAfterDelay', 'sendMessage',
+ 'sendNativeMessage', 'getPlatformInfo', 'getPackageDirectoryEntry',
+ { n: "requestUpdateCheck", cb: (status, details) => { return { status, details }; } }],
+ scriptBadge: ['getPopup'],
+ sessions: ['getRecentlyClosed', 'getDevices', 'restore'],
+ storage: [ // Todo: this should extend StorageArea.prototype instead
+ { n: 'sync', props: knownInStorageArea },
+ { n: 'local', props: knownInStorageArea },
+ { n: 'managed', props: knownInStorageArea }],
+ socket: [
+ 'create', 'connect', 'bind', 'read', 'write', 'recvFrom', 'sendTo',
+ 'listen', 'accept', 'setKeepAlive', 'setNoDelay', 'getInfo', 'getNetworkList'],
+ sockets: [
+ { n: 'tcp', props: [
+ 'create','update','setPaused','setKeepAlive','setNoDelay','connect',
+ 'disconnect','secure','send','close','getInfo','getSockets'] },
+ { n: 'tcpServer', props: [
+ 'create','update','setPaused','listen','disconnect','close','getInfo','getSockets'] },
+ { n: 'udp', props: [
+ 'create','update','setPaused','bind','send','close','getInfo',
+ 'getSockets','joinGroup','leaveGroup','setMulticastTimeToLive',
+ 'setMulticastLoopbackMode','getJoinedGroups','setBroadcast'] }],
+ system: [
+ { n: 'cpu', props: ['getInfo'] },
+ { n: 'memory', props: ['getInfo'] },
+ { n: 'storage', props: ['getInfo', 'ejectDevice', 'getAvailableCapacity'] }],
+ tabCapture: ['capture', 'getCapturedTabs'],
+ tabs: [
+ 'get', 'getCurrent', 'sendMessage', 'create', 'duplicate',
+ 'query', 'highlight', 'update', 'move', 'reload', 'remove',
+ 'detectLanguage', 'captureVisibleTab', 'executeScript',
+ 'insertCSS', 'setZoom', 'getZoom', 'setZoomSettings',
+ 'getZoomSettings', 'discard'],
+ topSites: ['get'],
+ tts: ['isSpeaking', 'getVoices', 'speak'],
+ types: ['set', 'get', 'clear'],
+ vpnProvider: ['createConfig', 'destroyConfig', 'setParameters', 'sendPacket', 'notifyConnectionStateChanged'],
+ wallpaper: ['setWallpaper'],
+ webNavigation: ['getFrame', 'getAllFrames', 'handlerBehaviorChanged'],
+ windows: ['get', 'getCurrent', 'getLastFocused', 'getAll', 'create', 'update', 'remove']
+ });
+})();
+
+},{}],2:[function(require,module,exports){
+(function (global,setImmediate){
+;(function() {
+"use strict"
+function Vnode(tag, key, attrs0, children, text, dom) {
+ return {tag: tag, key: key, attrs: attrs0, children: children, text: text, dom: dom, domSize: undefined, state: undefined, _state: undefined, events: undefined, instance: undefined, skip: false}
+}
+Vnode.normalize = function(node) {
+ if (Array.isArray(node)) return Vnode("[", undefined, undefined, Vnode.normalizeChildren(node), undefined, undefined)
+ if (node != null && typeof node !== "object") return Vnode("#", undefined, undefined, node === false ? "" : node, undefined, undefined)
+ return node
+}
+Vnode.normalizeChildren = function normalizeChildren(children) {
+ for (var i = 0; i < children.length; i++) {
+ children[i] = Vnode.normalize(children[i])
+ }
+ return children
+}
+var selectorParser = /(?:(^|#|\.)([^#\.\[\]]+))|(\[(.+?)(?:\s*=\s*("|'|)((?:\\["'\]]|.)*?)\5)?\])/g
+var selectorCache = {}
+var hasOwn = {}.hasOwnProperty
+function isEmpty(object) {
+ for (var key in object) if (hasOwn.call(object, key)) return false
+ return true
+}
+function compileSelector(selector) {
+ var match, tag = "div", classes = [], attrs = {}
+ while (match = selectorParser.exec(selector)) {
+ var type = match[1], value = match[2]
+ if (type === "" && value !== "") tag = value
+ else if (type === "#") attrs.id = value
+ else if (type === ".") classes.push(value)
+ else if (match[3][0] === "[") {
+ var attrValue = match[6]
+ if (attrValue) attrValue = attrValue.replace(/\\(["'])/g, "$1").replace(/\\\\/g, "\\")
+ if (match[4] === "class") classes.push(attrValue)
+ else attrs[match[4]] = attrValue === "" ? attrValue : attrValue || true
+ }
+ }
+ if (classes.length > 0) attrs.className = classes.join(" ")
+ return selectorCache[selector] = {tag: tag, attrs: attrs}
+}
+function execSelector(state, attrs, children) {
+ var hasAttrs = false, childList, text
+ var className = attrs.className || attrs.class
+ if (!isEmpty(state.attrs) && !isEmpty(attrs)) {
+ var newAttrs = {}
+ for(var key in attrs) {
+ if (hasOwn.call(attrs, key)) {
+ newAttrs[key] = attrs[key]
+ }
+ }
+ attrs = newAttrs
+ }
+ for (var key in state.attrs) {
+ if (hasOwn.call(state.attrs, key)) {
+ attrs[key] = state.attrs[key]
+ }
+ }
+ if (className !== undefined) {
+ if (attrs.class !== undefined) {
+ attrs.class = undefined
+ attrs.className = className
+ }
+ if (state.attrs.className != null) {
+ attrs.className = state.attrs.className + " " + className
+ }
+ }
+ for (var key in attrs) {
+ if (hasOwn.call(attrs, key) && key !== "key") {
+ hasAttrs = true
+ break
+ }
+ }
+ if (Array.isArray(children) && children.length === 1 && children[0] != null && children[0].tag === "#") {
+ text = children[0].children
+ } else {
+ childList = children
+ }
+ return Vnode(state.tag, attrs.key, hasAttrs ? attrs : undefined, childList, text)
+}
+function hyperscript(selector) {
+ // Because sloppy mode sucks
+ var attrs = arguments[1], start = 2, children
+ if (selector == null || typeof selector !== "string" && typeof selector !== "function" && typeof selector.view !== "function") {
+ throw Error("The selector must be either a string or a component.");
+ }
+ if (typeof selector === "string") {
+ var cached = selectorCache[selector] || compileSelector(selector)
+ }
+ if (attrs == null) {
+ attrs = {}
+ } else if (typeof attrs !== "object" || attrs.tag != null || Array.isArray(attrs)) {
+ attrs = {}
+ start = 1
+ }
+ if (arguments.length === start + 1) {
+ children = arguments[start]
+ if (!Array.isArray(children)) children = [children]
+ } else {
+ children = []
+ while (start < arguments.length) children.push(arguments[start++])
+ }
+ var normalized = Vnode.normalizeChildren(children)
+ if (typeof selector === "string") {
+ return execSelector(cached, attrs, normalized)
+ } else {
+ return Vnode(selector, attrs.key, attrs, normalized)
+ }
+}
+hyperscript.trust = function(html) {
+ if (html == null) html = ""
+ return Vnode("<", undefined, undefined, html, undefined, undefined)
+}
+hyperscript.fragment = function(attrs1, children) {
+ return Vnode("[", attrs1.key, attrs1, Vnode.normalizeChildren(children), undefined, undefined)
+}
+var m = hyperscript
+/** @constructor */
+var PromisePolyfill = function(executor) {
+ if (!(this instanceof PromisePolyfill)) throw new Error("Promise must be called with `new`")
+ if (typeof executor !== "function") throw new TypeError("executor must be a function")
+ var self = this, resolvers = [], rejectors = [], resolveCurrent = handler(resolvers, true), rejectCurrent = handler(rejectors, false)
+ var instance = self._instance = {resolvers: resolvers, rejectors: rejectors}
+ var callAsync = typeof setImmediate === "function" ? setImmediate : setTimeout
+ function handler(list, shouldAbsorb) {
+ return function execute(value) {
+ var then
+ try {
+ if (shouldAbsorb && value != null && (typeof value === "object" || typeof value === "function") && typeof (then = value.then) === "function") {
+ if (value === self) throw new TypeError("Promise can't be resolved w/ itself")
+ executeOnce(then.bind(value))
+ }
+ else {
+ callAsync(function() {
+ if (!shouldAbsorb && list.length === 0) console.error("Possible unhandled promise rejection:", value)
+ for (var i = 0; i < list.length; i++) list[i](value)
+ resolvers.length = 0, rejectors.length = 0
+ instance.state = shouldAbsorb
+ instance.retry = function() {execute(value)}
+ })
+ }
+ }
+ catch (e) {
+ rejectCurrent(e)
+ }
+ }
+ }
+ function executeOnce(then) {
+ var runs = 0
+ function run(fn) {
+ return function(value) {
+ if (runs++ > 0) return
+ fn(value)
+ }
+ }
+ var onerror = run(rejectCurrent)
+ try {then(run(resolveCurrent), onerror)} catch (e) {onerror(e)}
+ }
+ executeOnce(executor)
+}
+PromisePolyfill.prototype.then = function(onFulfilled, onRejection) {
+ var self = this, instance = self._instance
+ function handle(callback, list, next, state) {
+ list.push(function(value) {
+ if (typeof callback !== "function") next(value)
+ else try {resolveNext(callback(value))} catch (e) {if (rejectNext) rejectNext(e)}
+ })
+ if (typeof instance.retry === "function" && state === instance.state) instance.retry()
+ }
+ var resolveNext, rejectNext
+ var promise = new PromisePolyfill(function(resolve, reject) {resolveNext = resolve, rejectNext = reject})
+ handle(onFulfilled, instance.resolvers, resolveNext, true), handle(onRejection, instance.rejectors, rejectNext, false)
+ return promise
+}
+PromisePolyfill.prototype.catch = function(onRejection) {
+ return this.then(null, onRejection)
+}
+PromisePolyfill.resolve = function(value) {
+ if (value instanceof PromisePolyfill) return value
+ return new PromisePolyfill(function(resolve) {resolve(value)})
+}
+PromisePolyfill.reject = function(value) {
+ return new PromisePolyfill(function(resolve, reject) {reject(value)})
+}
+PromisePolyfill.all = function(list) {
+ return new PromisePolyfill(function(resolve, reject) {
+ var total = list.length, count = 0, values = []
+ if (list.length === 0) resolve([])
+ else for (var i = 0; i < list.length; i++) {
+ (function(i) {
+ function consume(value) {
+ count++
+ values[i] = value
+ if (count === total) resolve(values)
+ }
+ if (list[i] != null && (typeof list[i] === "object" || typeof list[i] === "function") && typeof list[i].then === "function") {
+ list[i].then(consume, reject)
+ }
+ else consume(list[i])
+ })(i)
+ }
+ })
+}
+PromisePolyfill.race = function(list) {
+ return new PromisePolyfill(function(resolve, reject) {
+ for (var i = 0; i < list.length; i++) {
+ list[i].then(resolve, reject)
+ }
+ })
+}
+if (typeof window !== "undefined") {
+ if (typeof window.Promise === "undefined") window.Promise = PromisePolyfill
+ var PromisePolyfill = window.Promise
+} else if (typeof global !== "undefined") {
+ if (typeof global.Promise === "undefined") global.Promise = PromisePolyfill
+ var PromisePolyfill = global.Promise
+} else {
+}
+var buildQueryString = function(object) {
+ if (Object.prototype.toString.call(object) !== "[object Object]") return ""
+ var args = []
+ for (var key0 in object) {
+ destructure(key0, object[key0])
+ }
+ return args.join("&")
+ function destructure(key0, value) {
+ if (Array.isArray(value)) {
+ for (var i = 0; i < value.length; i++) {
+ destructure(key0 + "[" + i + "]", value[i])
+ }
+ }
+ else if (Object.prototype.toString.call(value) === "[object Object]") {
+ for (var i in value) {
+ destructure(key0 + "[" + i + "]", value[i])
+ }
+ }
+ else args.push(encodeURIComponent(key0) + (value != null && value !== "" ? "=" + encodeURIComponent(value) : ""))
+ }
+}
+var FILE_PROTOCOL_REGEX = new RegExp("^file://", "i")
+var _8 = function($window, Promise) {
+ var callbackCount = 0
+ var oncompletion
+ function setCompletionCallback(callback) {oncompletion = callback}
+ function finalizer() {
+ var count = 0
+ function complete() {if (--count === 0 && typeof oncompletion === "function") oncompletion()}
+ return function finalize(promise0) {
+ var then0 = promise0.then
+ promise0.then = function() {
+ count++
+ var next = then0.apply(promise0, arguments)
+ next.then(complete, function(e) {
+ complete()
+ if (count === 0) throw e
+ })
+ return finalize(next)
+ }
+ return promise0
+ }
+ }
+ function normalize(args, extra) {
+ if (typeof args === "string") {
+ var url = args
+ args = extra || {}
+ if (args.url == null) args.url = url
+ }
+ return args
+ }
+ function request(args, extra) {
+ var finalize = finalizer()
+ args = normalize(args, extra)
+ var promise0 = new Promise(function(resolve, reject) {
+ if (args.method == null) args.method = "GET"
+ args.method = args.method.toUpperCase()
+ var useBody = (args.method === "GET" || args.method === "TRACE") ? false : (typeof args.useBody === "boolean" ? args.useBody : true)
+ if (typeof args.serialize !== "function") args.serialize = typeof FormData !== "undefined" && args.data instanceof FormData ? function(value) {return value} : JSON.stringify
+ if (typeof args.deserialize !== "function") args.deserialize = deserialize
+ if (typeof args.extract !== "function") args.extract = extract
+ args.url = interpolate(args.url, args.data)
+ if (useBody) args.data = args.serialize(args.data)
+ else args.url = assemble(args.url, args.data)
+ var xhr = new $window.XMLHttpRequest(),
+ aborted = false,
+ _abort = xhr.abort
+ xhr.abort = function abort() {
+ aborted = true
+ _abort.call(xhr)
+ }
+ xhr.open(args.method, args.url, typeof args.async === "boolean" ? args.async : true, typeof args.user === "string" ? args.user : undefined, typeof args.password === "string" ? args.password : undefined)
+ if (args.serialize === JSON.stringify && useBody && !(args.headers && args.headers.hasOwnProperty("Content-Type"))) {
+ xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8")
+ }
+ if (args.deserialize === deserialize && !(args.headers && args.headers.hasOwnProperty("Accept"))) {
+ xhr.setRequestHeader("Accept", "application/json, text/*")
+ }
+ if (args.withCredentials) xhr.withCredentials = args.withCredentials
+ for (var key in args.headers) if ({}.hasOwnProperty.call(args.headers, key)) {
+ xhr.setRequestHeader(key, args.headers[key])
+ }
+ if (typeof args.config === "function") xhr = args.config(xhr, args) || xhr
+ xhr.onreadystatechange = function() {
+ // Don't throw errors on xhr.abort().
+ if(aborted) return
+ if (xhr.readyState === 4) {
+ try {
+ var response = (args.extract !== extract) ? args.extract(xhr, args) : args.deserialize(args.extract(xhr, args))
+ if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304 || FILE_PROTOCOL_REGEX.test(args.url)) {
+ resolve(cast(args.type, response))
+ }
+ else {
+ var error = new Error(xhr.responseText)
+ for (var key in response) error[key] = response[key]
+ reject(error)
+ }
+ }
+ catch (e) {
+ reject(e)
+ }
+ }
+ }
+ if (useBody && (args.data != null)) xhr.send(args.data)
+ else xhr.send()
+ })
+ return args.background === true ? promise0 : finalize(promise0)
+ }
+ function jsonp(args, extra) {
+ var finalize = finalizer()
+ args = normalize(args, extra)
+ var promise0 = new Promise(function(resolve, reject) {
+ var callbackName = args.callbackName || "_mithril_" + Math.round(Math.random() * 1e16) + "_" + callbackCount++
+ var script = $window.document.createElement("script")
+ $window[callbackName] = function(data) {
+ script.parentNode.removeChild(script)
+ resolve(cast(args.type, data))
+ delete $window[callbackName]
+ }
+ script.onerror = function() {
+ script.parentNode.removeChild(script)
+ reject(new Error("JSONP request failed"))
+ delete $window[callbackName]
+ }
+ if (args.data == null) args.data = {}
+ args.url = interpolate(args.url, args.data)
+ args.data[args.callbackKey || "callback"] = callbackName
+ script.src = assemble(args.url, args.data)
+ $window.document.documentElement.appendChild(script)
+ })
+ return args.background === true? promise0 : finalize(promise0)
+ }
+ function interpolate(url, data) {
+ if (data == null) return url
+ var tokens = url.match(/:[^\/]+/gi) || []
+ for (var i = 0; i < tokens.length; i++) {
+ var key = tokens[i].slice(1)
+ if (data[key] != null) {
+ url = url.replace(tokens[i], data[key])
+ }
+ }
+ return url
+ }
+ function assemble(url, data) {
+ var querystring = buildQueryString(data)
+ if (querystring !== "") {
+ var prefix = url.indexOf("?") < 0 ? "?" : "&"
+ url += prefix + querystring
+ }
+ return url
+ }
+ function deserialize(data) {
+ try {return data !== "" ? JSON.parse(data) : null}
+ catch (e) {throw new Error(data)}
+ }
+ function extract(xhr) {return xhr.responseText}
+ function cast(type0, data) {
+ if (typeof type0 === "function") {
+ if (Array.isArray(data)) {
+ for (var i = 0; i < data.length; i++) {
+ data[i] = new type0(data[i])
+ }
+ }
+ else return new type0(data)
+ }
+ return data
+ }
+ return {request: request, jsonp: jsonp, setCompletionCallback: setCompletionCallback}
+}
+var requestService = _8(window, PromisePolyfill)
+var coreRenderer = function($window) {
+ var $doc = $window.document
+ var $emptyFragment = $doc.createDocumentFragment()
+ var nameSpace = {
+ svg: "http://www.w3.org/2000/svg",
+ math: "http://www.w3.org/1998/Math/MathML"
+ }
+ var onevent
+ function setEventCallback(callback) {return onevent = callback}
+ function getNameSpace(vnode) {
+ return vnode.attrs && vnode.attrs.xmlns || nameSpace[vnode.tag]
+ }
+ //create
+ function createNodes(parent, vnodes, start, end, hooks, nextSibling, ns) {
+ for (var i = start; i < end; i++) {
+ var vnode = vnodes[i]
+ if (vnode != null) {
+ createNode(parent, vnode, hooks, ns, nextSibling)
+ }
+ }
+ }
+ function createNode(parent, vnode, hooks, ns, nextSibling) {
+ var tag = vnode.tag
+ if (typeof tag === "string") {
+ vnode.state = {}
+ if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks)
+ switch (tag) {
+ case "#": return createText(parent, vnode, nextSibling)
+ case "<": return createHTML(parent, vnode, nextSibling)
+ case "[": return createFragment(parent, vnode, hooks, ns, nextSibling)
+ default: return createElement(parent, vnode, hooks, ns, nextSibling)
+ }
+ }
+ else return createComponent(parent, vnode, hooks, ns, nextSibling)
+ }
+ function createText(parent, vnode, nextSibling) {
+ vnode.dom = $doc.createTextNode(vnode.children)
+ insertNode(parent, vnode.dom, nextSibling)
+ return vnode.dom
+ }
+ function createHTML(parent, vnode, nextSibling) {
+ var match1 = vnode.children.match(/^\s*?<(\w+)/im) || []
+ var parent1 = {caption: "table", thead: "table", tbody: "table", tfoot: "table", tr: "tbody", th: "tr", td: "tr", colgroup: "table", col: "colgroup"}[match1[1]] || "div"
+ var temp = $doc.createElement(parent1)
+ temp.innerHTML = vnode.children
+ vnode.dom = temp.firstChild
+ vnode.domSize = temp.childNodes.length
+ var fragment = $doc.createDocumentFragment()
+ var child
+ while (child = temp.firstChild) {
+ fragment.appendChild(child)
+ }
+ insertNode(parent, fragment, nextSibling)
+ return fragment
+ }
+ function createFragment(parent, vnode, hooks, ns, nextSibling) {
+ var fragment = $doc.createDocumentFragment()
+ if (vnode.children != null) {
+ var children = vnode.children
+ createNodes(fragment, children, 0, children.length, hooks, null, ns)
+ }
+ vnode.dom = fragment.firstChild
+ vnode.domSize = fragment.childNodes.length
+ insertNode(parent, fragment, nextSibling)
+ return fragment
+ }
+ function createElement(parent, vnode, hooks, ns, nextSibling) {
+ var tag = vnode.tag
+ var attrs2 = vnode.attrs
+ var is = attrs2 && attrs2.is
+ ns = getNameSpace(vnode) || ns
+ var element = ns ?
+ is ? $doc.createElementNS(ns, tag, {is: is}) : $doc.createElementNS(ns, tag) :
+ is ? $doc.createElement(tag, {is: is}) : $doc.createElement(tag)
+ vnode.dom = element
+ if (attrs2 != null) {
+ setAttrs(vnode, attrs2, ns)
+ }
+ insertNode(parent, element, nextSibling)
+ if (vnode.attrs != null && vnode.attrs.contenteditable != null) {
+ setContentEditable(vnode)
+ }
+ else {
+ if (vnode.text != null) {
+ if (vnode.text !== "") element.textContent = vnode.text
+ else vnode.children = [Vnode("#", undefined, undefined, vnode.text, undefined, undefined)]
+ }
+ if (vnode.children != null) {
+ var children = vnode.children
+ createNodes(element, children, 0, children.length, hooks, null, ns)
+ setLateAttrs(vnode)
+ }
+ }
+ return element
+ }
+ function initComponent(vnode, hooks) {
+ var sentinel
+ if (typeof vnode.tag.view === "function") {
+ vnode.state = Object.create(vnode.tag)
+ sentinel = vnode.state.view
+ if (sentinel.$$reentrantLock$$ != null) return $emptyFragment
+ sentinel.$$reentrantLock$$ = true
+ } else {
+ vnode.state = void 0
+ sentinel = vnode.tag
+ if (sentinel.$$reentrantLock$$ != null) return $emptyFragment
+ sentinel.$$reentrantLock$$ = true
+ vnode.state = (vnode.tag.prototype != null && typeof vnode.tag.prototype.view === "function") ? new vnode.tag(vnode) : vnode.tag(vnode)
+ }
+ vnode._state = vnode.state
+ if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks)
+ initLifecycle(vnode._state, vnode, hooks)
+ vnode.instance = Vnode.normalize(vnode._state.view.call(vnode.state, vnode))
+ if (vnode.instance === vnode) throw Error("A view cannot return the vnode it received as argument")
+ sentinel.$$reentrantLock$$ = null
+ }
+ function createComponent(parent, vnode, hooks, ns, nextSibling) {
+ initComponent(vnode, hooks)
+ if (vnode.instance != null) {
+ var element = createNode(parent, vnode.instance, hooks, ns, nextSibling)
+ vnode.dom = vnode.instance.dom
+ vnode.domSize = vnode.dom != null ? vnode.instance.domSize : 0
+ insertNode(parent, element, nextSibling)
+ return element
+ }
+ else {
+ vnode.domSize = 0
+ return $emptyFragment
+ }
+ }
+ //update
+ function updateNodes(parent, old, vnodes, recycling, hooks, nextSibling, ns) {
+ if (old === vnodes || old == null && vnodes == null) return
+ else if (old == null) createNodes(parent, vnodes, 0, vnodes.length, hooks, nextSibling, ns)
+ else if (vnodes == null) removeNodes(old, 0, old.length, vnodes)
+ else {
+ if (old.length === vnodes.length) {
+ var isUnkeyed = false
+ for (var i = 0; i < vnodes.length; i++) {
+ if (vnodes[i] != null && old[i] != null) {
+ isUnkeyed = vnodes[i].key == null && old[i].key == null
+ break
+ }
+ }
+ if (isUnkeyed) {
+ for (var i = 0; i < old.length; i++) {
+ if (old[i] === vnodes[i]) continue
+ else if (old[i] == null && vnodes[i] != null) createNode(parent, vnodes[i], hooks, ns, getNextSibling(old, i + 1, nextSibling))
+ else if (vnodes[i] == null) removeNodes(old, i, i + 1, vnodes)
+ else updateNode(parent, old[i], vnodes[i], hooks, getNextSibling(old, i + 1, nextSibling), recycling, ns)
+ }
+ return
+ }
+ }
+ recycling = recycling || isRecyclable(old, vnodes)
+ if (recycling) {
+ var pool = old.pool
+ old = old.concat(old.pool)
+ }
+ var oldStart = 0, start = 0, oldEnd = old.length - 1, end = vnodes.length - 1, map
+ while (oldEnd >= oldStart && end >= start) {
+ var o = old[oldStart], v = vnodes[start]
+ if (o === v && !recycling) oldStart++, start++
+ else if (o == null) oldStart++
+ else if (v == null) start++
+ else if (o.key === v.key) {
+ var shouldRecycle = (pool != null && oldStart >= old.length - pool.length) || ((pool == null) && recycling)
+ oldStart++, start++
+ updateNode(parent, o, v, hooks, getNextSibling(old, oldStart, nextSibling), shouldRecycle, ns)
+ if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling)
+ }
+ else {
+ var o = old[oldEnd]
+ if (o === v && !recycling) oldEnd--, start++
+ else if (o == null) oldEnd--
+ else if (v == null) start++
+ else if (o.key === v.key) {
+ var shouldRecycle = (pool != null && oldEnd >= old.length - pool.length) || ((pool == null) && recycling)
+ updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), shouldRecycle, ns)
+ if (recycling || start < end) insertNode(parent, toFragment(o), getNextSibling(old, oldStart, nextSibling))
+ oldEnd--, start++
+ }
+ else break
+ }
+ }
+ while (oldEnd >= oldStart && end >= start) {
+ var o = old[oldEnd], v = vnodes[end]
+ if (o === v && !recycling) oldEnd--, end--
+ else if (o == null) oldEnd--
+ else if (v == null) end--
+ else if (o.key === v.key) {
+ var shouldRecycle = (pool != null && oldEnd >= old.length - pool.length) || ((pool == null) && recycling)
+ updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), shouldRecycle, ns)
+ if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling)
+ if (o.dom != null) nextSibling = o.dom
+ oldEnd--, end--
+ }
+ else {
+ if (!map) map = getKeyMap(old, oldEnd)
+ if (v != null) {
+ var oldIndex = map[v.key]
+ if (oldIndex != null) {
+ var movable = old[oldIndex]
+ var shouldRecycle = (pool != null && oldIndex >= old.length - pool.length) || ((pool == null) && recycling)
+ updateNode(parent, movable, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns)
+ insertNode(parent, toFragment(movable), nextSibling)
+ old[oldIndex].skip = true
+ if (movable.dom != null) nextSibling = movable.dom
+ }
+ else {
+ var dom = createNode(parent, v, hooks, ns, nextSibling)
+ nextSibling = dom
+ }
+ }
+ end--
+ }
+ if (end < start) break
+ }
+ createNodes(parent, vnodes, start, end + 1, hooks, nextSibling, ns)
+ removeNodes(old, oldStart, oldEnd + 1, vnodes)
+ }
+ }
+ function updateNode(parent, old, vnode, hooks, nextSibling, recycling, ns) {
+ var oldTag = old.tag, tag = vnode.tag
+ if (oldTag === tag) {
+ vnode.state = old.state
+ vnode._state = old._state
+ vnode.events = old.events
+ if (!recycling && shouldNotUpdate(vnode, old)) return
+ if (typeof oldTag === "string") {
+ if (vnode.attrs != null) {
+ if (recycling) {
+ vnode.state = {}
+ initLifecycle(vnode.attrs, vnode, hooks)
+ }
+ else updateLifecycle(vnode.attrs, vnode, hooks)
+ }
+ switch (oldTag) {
+ case "#": updateText(old, vnode); break
+ case "<": updateHTML(parent, old, vnode, nextSibling); break
+ case "[": updateFragment(parent, old, vnode, recycling, hooks, nextSibling, ns); break
+ default: updateElement(old, vnode, recycling, hooks, ns)
+ }
+ }
+ else updateComponent(parent, old, vnode, hooks, nextSibling, recycling, ns)
+ }
+ else {
+ removeNode(old, null)
+ createNode(parent, vnode, hooks, ns, nextSibling)
+ }
+ }
+ function updateText(old, vnode) {
+ if (old.children.toString() !== vnode.children.toString()) {
+ old.dom.nodeValue = vnode.children
+ }
+ vnode.dom = old.dom
+ }
+ function updateHTML(parent, old, vnode, nextSibling) {
+ if (old.children !== vnode.children) {
+ toFragment(old)
+ createHTML(parent, vnode, nextSibling)
+ }
+ else vnode.dom = old.dom, vnode.domSize = old.domSize
+ }
+ function updateFragment(parent, old, vnode, recycling, hooks, nextSibling, ns) {
+ updateNodes(parent, old.children, vnode.children, recycling, hooks, nextSibling, ns)
+ var domSize = 0, children = vnode.children
+ vnode.dom = null
+ if (children != null) {
+ for (var i = 0; i < children.length; i++) {
+ var child = children[i]
+ if (child != null && child.dom != null) {
+ if (vnode.dom == null) vnode.dom = child.dom
+ domSize += child.domSize || 1
+ }
+ }
+ if (domSize !== 1) vnode.domSize = domSize
+ }
+ }
+ function updateElement(old, vnode, recycling, hooks, ns) {
+ var element = vnode.dom = old.dom
+ ns = getNameSpace(vnode) || ns
+ if (vnode.tag === "textarea") {
+ if (vnode.attrs == null) vnode.attrs = {}
+ if (vnode.text != null) {
+ vnode.attrs.value = vnode.text //FIXME handle0 multiple children
+ vnode.text = undefined
+ }
+ }
+ updateAttrs(vnode, old.attrs, vnode.attrs, ns)
+ if (vnode.attrs != null && vnode.attrs.contenteditable != null) {
+ setContentEditable(vnode)
+ }
+ else if (old.text != null && vnode.text != null && vnode.text !== "") {
+ if (old.text.toString() !== vnode.text.toString()) old.dom.firstChild.nodeValue = vnode.text
+ }
+ else {
+ if (old.text != null) old.children = [Vnode("#", undefined, undefined, old.text, undefined, old.dom.firstChild)]
+ if (vnode.text != null) vnode.children = [Vnode("#", undefined, undefined, vnode.text, undefined, undefined)]
+ updateNodes(element, old.children, vnode.children, recycling, hooks, null, ns)
+ }
+ }
+ function updateComponent(parent, old, vnode, hooks, nextSibling, recycling, ns) {
+ if (recycling) {
+ initComponent(vnode, hooks)
+ } else {
+ vnode.instance = Vnode.normalize(vnode._state.view.call(vnode.state, vnode))
+ if (vnode.instance === vnode) throw Error("A view cannot return the vnode it received as argument")
+ if (vnode.attrs != null) updateLifecycle(vnode.attrs, vnode, hooks)
+ updateLifecycle(vnode._state, vnode, hooks)
+ }
+ if (vnode.instance != null) {
+ if (old.instance == null) createNode(parent, vnode.instance, hooks, ns, nextSibling)
+ else updateNode(parent, old.instance, vnode.instance, hooks, nextSibling, recycling, ns)
+ vnode.dom = vnode.instance.dom
+ vnode.domSize = vnode.instance.domSize
+ }
+ else if (old.instance != null) {
+ removeNode(old.instance, null)
+ vnode.dom = undefined
+ vnode.domSize = 0
+ }
+ else {
+ vnode.dom = old.dom
+ vnode.domSize = old.domSize
+ }
+ }
+ function isRecyclable(old, vnodes) {
+ if (old.pool != null && Math.abs(old.pool.length - vnodes.length) <= Math.abs(old.length - vnodes.length)) {
+ var oldChildrenLength = old[0] && old[0].children && old[0].children.length || 0
+ var poolChildrenLength = old.pool[0] && old.pool[0].children && old.pool[0].children.length || 0
+ var vnodesChildrenLength = vnodes[0] && vnodes[0].children && vnodes[0].children.length || 0
+ if (Math.abs(poolChildrenLength - vnodesChildrenLength) <= Math.abs(oldChildrenLength - vnodesChildrenLength)) {
+ return true
+ }
+ }
+ return false
+ }
+ function getKeyMap(vnodes, end) {
+ var map = {}, i = 0
+ for (var i = 0; i < end; i++) {
+ var vnode = vnodes[i]
+ if (vnode != null) {
+ var key2 = vnode.key
+ if (key2 != null) map[key2] = i
+ }
+ }
+ return map
+ }
+ function toFragment(vnode) {
+ var count0 = vnode.domSize
+ if (count0 != null || vnode.dom == null) {
+ var fragment = $doc.createDocumentFragment()
+ if (count0 > 0) {
+ var dom = vnode.dom
+ while (--count0) fragment.appendChild(dom.nextSibling)
+ fragment.insertBefore(dom, fragment.firstChild)
+ }
+ return fragment
+ }
+ else return vnode.dom
+ }
+ function getNextSibling(vnodes, i, nextSibling) {
+ for (; i < vnodes.length; i++) {
+ if (vnodes[i] != null && vnodes[i].dom != null) return vnodes[i].dom
+ }
+ return nextSibling
+ }
+ function insertNode(parent, dom, nextSibling) {
+ if (nextSibling && nextSibling.parentNode) parent.insertBefore(dom, nextSibling)
+ else parent.appendChild(dom)
+ }
+ function setContentEditable(vnode) {
+ var children = vnode.children
+ if (children != null && children.length === 1 && children[0].tag === "<") {
+ var content = children[0].children
+ if (vnode.dom.innerHTML !== content) vnode.dom.innerHTML = content
+ }
+ else if (vnode.text != null || children != null && children.length !== 0) throw new Error("Child node of a contenteditable must be trusted")
+ }
+ //remove
+ function removeNodes(vnodes, start, end, context) {
+ for (var i = start; i < end; i++) {
+ var vnode = vnodes[i]
+ if (vnode != null) {
+ if (vnode.skip) vnode.skip = false
+ else removeNode(vnode, context)
+ }
+ }
+ }
+ function removeNode(vnode, context) {
+ var expected = 1, called = 0
+ if (vnode.attrs && typeof vnode.attrs.onbeforeremove === "function") {
+ var result = vnode.attrs.onbeforeremove.call(vnode.state, vnode)
+ if (result != null && typeof result.then === "function") {
+ expected++
+ result.then(continuation, continuation)
+ }
+ }
+ if (typeof vnode.tag !== "string" && typeof vnode._state.onbeforeremove === "function") {
+ var result = vnode._state.onbeforeremove.call(vnode.state, vnode)
+ if (result != null && typeof result.then === "function") {
+ expected++
+ result.then(continuation, continuation)
+ }
+ }
+ continuation()
+ function continuation() {
+ if (++called === expected) {
+ onremove(vnode)
+ if (vnode.dom) {
+ var count0 = vnode.domSize || 1
+ if (count0 > 1) {
+ var dom = vnode.dom
+ while (--count0) {
+ removeNodeFromDOM(dom.nextSibling)
+ }
+ }
+ removeNodeFromDOM(vnode.dom)
+ if (context != null && vnode.domSize == null && !hasIntegrationMethods(vnode.attrs) && typeof vnode.tag === "string") { //TODO test custom elements
+ if (!context.pool) context.pool = [vnode]
+ else context.pool.push(vnode)
+ }
+ }
+ }
+ }
+ }
+ function removeNodeFromDOM(node) {
+ var parent = node.parentNode
+ if (parent != null) parent.removeChild(node)
+ }
+ function onremove(vnode) {
+ if (vnode.attrs && typeof vnode.attrs.onremove === "function") vnode.attrs.onremove.call(vnode.state, vnode)
+ if (typeof vnode.tag !== "string") {
+ if (typeof vnode._state.onremove === "function") vnode._state.onremove.call(vnode.state, vnode)
+ if (vnode.instance != null) onremove(vnode.instance)
+ } else {
+ var children = vnode.children
+ if (Array.isArray(children)) {
+ for (var i = 0; i < children.length; i++) {
+ var child = children[i]
+ if (child != null) onremove(child)
+ }
+ }
+ }
+ }
+ //attrs2
+ function setAttrs(vnode, attrs2, ns) {
+ for (var key2 in attrs2) {
+ setAttr(vnode, key2, null, attrs2[key2], ns)
+ }
+ }
+ function setAttr(vnode, key2, old, value, ns) {
+ var element = vnode.dom
+ if (key2 === "key" || key2 === "is" || (old === value && !isFormAttribute(vnode, key2)) && typeof value !== "object" || typeof value === "undefined" || isLifecycleMethod(key2)) return
+ var nsLastIndex = key2.indexOf(":")
+ if (nsLastIndex > -1 && key2.substr(0, nsLastIndex) === "xlink") {
+ element.setAttributeNS("http://www.w3.org/1999/xlink", key2.slice(nsLastIndex + 1), value)
+ }
+ else if (key2[0] === "o" && key2[1] === "n" && typeof value === "function") updateEvent(vnode, key2, value)
+ else if (key2 === "style") updateStyle(element, old, value)
+ else if (key2 in element && !isAttribute(key2) && ns === undefined && !isCustomElement(vnode)) {
+ if (key2 === "value") {
+ var normalized0 = "" + value // eslint-disable-line no-implicit-coercion
+ //setting input[value] to same value by typing on focused element moves cursor to end in Chrome
+ if ((vnode.tag === "input" || vnode.tag === "textarea") && vnode.dom.value === normalized0 && vnode.dom === $doc.activeElement) return
+ //setting select[value] to same value while having select open blinks select dropdown in Chrome
+ if (vnode.tag === "select") {
+ if (value === null) {
+ if (vnode.dom.selectedIndex === -1 && vnode.dom === $doc.activeElement) return
+ } else {
+ if (old !== null && vnode.dom.value === normalized0 && vnode.dom === $doc.activeElement) return
+ }
+ }
+ //setting option[value] to same value while having select open blinks select dropdown in Chrome
+ if (vnode.tag === "option" && old != null && vnode.dom.value === normalized0) return
+ }
+ // If you assign an input type1 that is not supported by IE 11 with an assignment expression, an error0 will occur.
+ if (vnode.tag === "input" && key2 === "type") {
+ element.setAttribute(key2, value)
+ return
+ }
+ element[key2] = value
+ }
+ else {
+ if (typeof value === "boolean") {
+ if (value) element.setAttribute(key2, "")
+ else element.removeAttribute(key2)
+ }
+ else element.setAttribute(key2 === "className" ? "class" : key2, value)
+ }
+ }
+ function setLateAttrs(vnode) {
+ var attrs2 = vnode.attrs
+ if (vnode.tag === "select" && attrs2 != null) {
+ if ("value" in attrs2) setAttr(vnode, "value", null, attrs2.value, undefined)
+ if ("selectedIndex" in attrs2) setAttr(vnode, "selectedIndex", null, attrs2.selectedIndex, undefined)
+ }
+ }
+ function updateAttrs(vnode, old, attrs2, ns) {
+ if (attrs2 != null) {
+ for (var key2 in attrs2) {
+ setAttr(vnode, key2, old && old[key2], attrs2[key2], ns)
+ }
+ }
+ if (old != null) {
+ for (var key2 in old) {
+ if (attrs2 == null || !(key2 in attrs2)) {
+ if (key2 === "className") key2 = "class"
+ if (key2[0] === "o" && key2[1] === "n" && !isLifecycleMethod(key2)) updateEvent(vnode, key2, undefined)
+ else if (key2 !== "key") vnode.dom.removeAttribute(key2)
+ }
+ }
+ }
+ }
+ function isFormAttribute(vnode, attr) {
+ return attr === "value" || attr === "checked" || attr === "selectedIndex" || attr === "selected" && vnode.dom === $doc.activeElement
+ }
+ function isLifecycleMethod(attr) {
+ return attr === "oninit" || attr === "oncreate" || attr === "onupdate" || attr === "onremove" || attr === "onbeforeremove" || attr === "onbeforeupdate"
+ }
+ function isAttribute(attr) {
+ return attr === "href" || attr === "list" || attr === "form" || attr === "width" || attr === "height"// || attr === "type"
+ }
+ function isCustomElement(vnode){
+ return vnode.attrs.is || vnode.tag.indexOf("-") > -1
+ }
+ function hasIntegrationMethods(source) {
+ return source != null && (source.oncreate || source.onupdate || source.onbeforeremove || source.onremove)
+ }
+ //style
+ function updateStyle(element, old, style) {
+ if (old === style) element.style.cssText = "", old = null
+ if (style == null) element.style.cssText = ""
+ else if (typeof style === "string") element.style.cssText = style
+ else {
+ if (typeof old === "string") element.style.cssText = ""
+ for (var key2 in style) {
+ element.style[key2] = style[key2]
+ }
+ if (old != null && typeof old !== "string") {
+ for (var key2 in old) {
+ if (!(key2 in style)) element.style[key2] = ""
+ }
+ }
+ }
+ }
+ //event
+ function updateEvent(vnode, key2, value) {
+ var element = vnode.dom
+ var callback = typeof onevent !== "function" ? value : function(e) {
+ var result = value.call(element, e)
+ onevent.call(element, e)
+ return result
+ }
+ if (key2 in element) element[key2] = typeof value === "function" ? callback : null
+ else {
+ var eventName = key2.slice(2)
+ if (vnode.events === undefined) vnode.events = {}
+ if (vnode.events[key2] === callback) return
+ if (vnode.events[key2] != null) element.removeEventListener(eventName, vnode.events[key2], false)
+ if (typeof value === "function") {
+ vnode.events[key2] = callback
+ element.addEventListener(eventName, vnode.events[key2], false)
+ }
+ }
+ }
+ //lifecycle
+ function initLifecycle(source, vnode, hooks) {
+ if (typeof source.oninit === "function") source.oninit.call(vnode.state, vnode)
+ if (typeof source.oncreate === "function") hooks.push(source.oncreate.bind(vnode.state, vnode))
+ }
+ function updateLifecycle(source, vnode, hooks) {
+ if (typeof source.onupdate === "function") hooks.push(source.onupdate.bind(vnode.state, vnode))
+ }
+ function shouldNotUpdate(vnode, old) {
+ var forceVnodeUpdate, forceComponentUpdate
+ if (vnode.attrs != null && typeof vnode.attrs.onbeforeupdate === "function") forceVnodeUpdate = vnode.attrs.onbeforeupdate.call(vnode.state, vnode, old)
+ if (typeof vnode.tag !== "string" && typeof vnode._state.onbeforeupdate === "function") forceComponentUpdate = vnode._state.onbeforeupdate.call(vnode.state, vnode, old)
+ if (!(forceVnodeUpdate === undefined && forceComponentUpdate === undefined) && !forceVnodeUpdate && !forceComponentUpdate) {
+ vnode.dom = old.dom
+ vnode.domSize = old.domSize
+ vnode.instance = old.instance
+ return true
+ }
+ return false
+ }
+ function render(dom, vnodes) {
+ if (!dom) throw new Error("Ensure the DOM element being passed to m.route/m.mount/m.render is not undefined.")
+ var hooks = []
+ var active = $doc.activeElement
+ var namespace = dom.namespaceURI
+ // First time0 rendering into a node clears it out
+ if (dom.vnodes == null) dom.textContent = ""
+ if (!Array.isArray(vnodes)) vnodes = [vnodes]
+ updateNodes(dom, dom.vnodes, Vnode.normalizeChildren(vnodes), false, hooks, null, namespace === "http://www.w3.org/1999/xhtml" ? undefined : namespace)
+ dom.vnodes = vnodes
+ // document.activeElement can return null in IE https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement
+ if (active != null && $doc.activeElement !== active) active.focus()
+ for (var i = 0; i < hooks.length; i++) hooks[i]()
+ }
+ return {render: render, setEventCallback: setEventCallback}
+}
+function throttle(callback) {
+ //60fps translates to 16.6ms, round it down since setTimeout requires int
+ var time = 16
+ var last = 0, pending = null
+ var timeout = typeof requestAnimationFrame === "function" ? requestAnimationFrame : setTimeout
+ return function() {
+ var now = Date.now()
+ if (last === 0 || now - last >= time) {
+ last = now
+ callback()
+ }
+ else if (pending === null) {
+ pending = timeout(function() {
+ pending = null
+ callback()
+ last = Date.now()
+ }, time - (now - last))
+ }
+ }
+}
+var _11 = function($window) {
+ var renderService = coreRenderer($window)
+ renderService.setEventCallback(function(e) {
+ if (e.redraw === false) e.redraw = undefined
+ else redraw()
+ })
+ var callbacks = []
+ function subscribe(key1, callback) {
+ unsubscribe(key1)
+ callbacks.push(key1, throttle(callback))
+ }
+ function unsubscribe(key1) {
+ var index = callbacks.indexOf(key1)
+ if (index > -1) callbacks.splice(index, 2)
+ }
+ function redraw() {
+ for (var i = 1; i < callbacks.length; i += 2) {
+ callbacks[i]()
+ }
+ }
+ return {subscribe: subscribe, unsubscribe: unsubscribe, redraw: redraw, render: renderService.render}
+}
+var redrawService = _11(window)
+requestService.setCompletionCallback(redrawService.redraw)
+var _16 = function(redrawService0) {
+ return function(root, component) {
+ if (component === null) {
+ redrawService0.render(root, [])
+ redrawService0.unsubscribe(root)
+ return
+ }
+
+ if (component.view == null && typeof component !== "function") throw new Error("m.mount(element, component) expects a component, not a vnode")
+
+ var run0 = function() {
+ redrawService0.render(root, Vnode(component))
+ }
+ redrawService0.subscribe(root, run0)
+ redrawService0.redraw()
+ }
+}
+m.mount = _16(redrawService)
+var Promise = PromisePolyfill
+var parseQueryString = function(string) {
+ if (string === "" || string == null) return {}
+ if (string.charAt(0) === "?") string = string.slice(1)
+ var entries = string.split("&"), data0 = {}, counters = {}
+ for (var i = 0; i < entries.length; i++) {
+ var entry = entries[i].split("=")
+ var key5 = decodeURIComponent(entry[0])
+ var value = entry.length === 2 ? decodeURIComponent(entry[1]) : ""
+ if (value === "true") value = true
+ else if (value === "false") value = false
+ var levels = key5.split(/\]\[?|\[/)
+ var cursor = data0
+ if (key5.indexOf("[") > -1) levels.pop()
+ for (var j = 0; j < levels.length; j++) {
+ var level = levels[j], nextLevel = levels[j + 1]
+ var isNumber = nextLevel == "" || !isNaN(parseInt(nextLevel, 10))
+ var isValue = j === levels.length - 1
+ if (level === "") {
+ var key5 = levels.slice(0, j).join()
+ if (counters[key5] == null) counters[key5] = 0
+ level = counters[key5]++
+ }
+ if (cursor[level] == null) {
+ cursor[level] = isValue ? value : isNumber ? [] : {}
+ }
+ cursor = cursor[level]
+ }
+ }
+ return data0
+}
+var coreRouter = function($window) {
+ var supportsPushState = typeof $window.history.pushState === "function"
+ var callAsync0 = typeof setImmediate === "function" ? setImmediate : setTimeout
+ function normalize1(fragment0) {
+ var data = $window.location[fragment0].replace(/(?:%[a-f89][a-f0-9])+/gim, decodeURIComponent)
+ if (fragment0 === "pathname" && data[0] !== "/") data = "/" + data
+ return data
+ }
+ var asyncId
+ function debounceAsync(callback0) {
+ return function() {
+ if (asyncId != null) return
+ asyncId = callAsync0(function() {
+ asyncId = null
+ callback0()
+ })
+ }
+ }
+ function parsePath(path, queryData, hashData) {
+ var queryIndex = path.indexOf("?")
+ var hashIndex = path.indexOf("#")
+ var pathEnd = queryIndex > -1 ? queryIndex : hashIndex > -1 ? hashIndex : path.length
+ if (queryIndex > -1) {
+ var queryEnd = hashIndex > -1 ? hashIndex : path.length
+ var queryParams = parseQueryString(path.slice(queryIndex + 1, queryEnd))
+ for (var key4 in queryParams) queryData[key4] = queryParams[key4]
+ }
+ if (hashIndex > -1) {
+ var hashParams = parseQueryString(path.slice(hashIndex + 1))
+ for (var key4 in hashParams) hashData[key4] = hashParams[key4]
+ }
+ return path.slice(0, pathEnd)
+ }
+ var router = {prefix: "#!"}
+ router.getPath = function() {
+ var type2 = router.prefix.charAt(0)
+ switch (type2) {
+ case "#": return normalize1("hash").slice(router.prefix.length)
+ case "?": return normalize1("search").slice(router.prefix.length) + normalize1("hash")
+ default: return normalize1("pathname").slice(router.prefix.length) + normalize1("search") + normalize1("hash")
+ }
+ }
+ router.setPath = function(path, data, options) {
+ var queryData = {}, hashData = {}
+ path = parsePath(path, queryData, hashData)
+ if (data != null) {
+ for (var key4 in data) queryData[key4] = data[key4]
+ path = path.replace(/:([^\/]+)/g, function(match2, token) {
+ delete queryData[token]
+ return data[token]
+ })
+ }
+ var query = buildQueryString(queryData)
+ if (query) path += "?" + query
+ var hash = buildQueryString(hashData)
+ if (hash) path += "#" + hash
+ if (supportsPushState) {
+ var state = options ? options.state : null
+ var title = options ? options.title : null
+ $window.onpopstate()
+ if (options && options.replace) $window.history.replaceState(state, title, router.prefix + path)
+ else $window.history.pushState(state, title, router.prefix + path)
+ }
+ else $window.location.href = router.prefix + path
+ }
+ router.defineRoutes = function(routes, resolve, reject) {
+ function resolveRoute() {
+ var path = router.getPath()
+ var params = {}
+ var pathname = parsePath(path, params, params)
+ var state = $window.history.state
+ if (state != null) {
+ for (var k in state) params[k] = state[k]
+ }
+ for (var route0 in routes) {
+ var matcher = new RegExp("^" + route0.replace(/:[^\/]+?\.{3}/g, "(.*?)").replace(/:[^\/]+/g, "([^\\/]+)") + "\/?$")
+ if (matcher.test(pathname)) {
+ pathname.replace(matcher, function() {
+ var keys = route0.match(/:[^\/]+/g) || []
+ var values = [].slice.call(arguments, 1, -2)
+ for (var i = 0; i < keys.length; i++) {
+ params[keys[i].replace(/:|\./g, "")] = decodeURIComponent(values[i])
+ }
+ resolve(routes[route0], params, path, route0)
+ })
+ return
+ }
+ }
+ reject(path, params)
+ }
+ if (supportsPushState) $window.onpopstate = debounceAsync(resolveRoute)
+ else if (router.prefix.charAt(0) === "#") $window.onhashchange = resolveRoute
+ resolveRoute()
+ }
+ return router
+}
+var _20 = function($window, redrawService0) {
+ var routeService = coreRouter($window)
+ var identity = function(v) {return v}
+ var render1, component, attrs3, currentPath, lastUpdate
+ var route = function(root, defaultRoute, routes) {
+ if (root == null) throw new Error("Ensure the DOM element that was passed to `m.route` is not undefined")
+ var run1 = function() {
+ if (render1 != null) redrawService0.render(root, render1(Vnode(component, attrs3.key, attrs3)))
+ }
+ var bail = function(path) {
+ if (path !== defaultRoute) routeService.setPath(defaultRoute, null, {replace: true})
+ else throw new Error("Could not resolve default route " + defaultRoute)
+ }
+ routeService.defineRoutes(routes, function(payload, params, path) {
+ var update = lastUpdate = function(routeResolver, comp) {
+ if (update !== lastUpdate) return
+ component = comp != null && (typeof comp.view === "function" || typeof comp === "function")? comp : "div"
+ attrs3 = params, currentPath = path, lastUpdate = null
+ render1 = (routeResolver.render || identity).bind(routeResolver)
+ run1()
+ }
+ if (payload.view || typeof payload === "function") update({}, payload)
+ else {
+ if (payload.onmatch) {
+ Promise.resolve(payload.onmatch(params, path)).then(function(resolved) {
+ update(payload, resolved)
+ }, bail)
+ }
+ else update(payload, "div")
+ }
+ }, bail)
+ redrawService0.subscribe(root, run1)
+ }
+ route.set = function(path, data, options) {
+ if (lastUpdate != null) {
+ options = options || {}
+ options.replace = true
+ }
+ lastUpdate = null
+ routeService.setPath(path, data, options)
+ }
+ route.get = function() {return currentPath}
+ route.prefix = function(prefix0) {routeService.prefix = prefix0}
+ route.link = function(vnode1) {
+ vnode1.dom.setAttribute("href", routeService.prefix + vnode1.attrs.href)
+ vnode1.dom.onclick = function(e) {
+ if (e.ctrlKey || e.metaKey || e.shiftKey || e.which === 2) return
+ e.preventDefault()
+ e.redraw = false
+ var href = this.getAttribute("href")
+ if (href.indexOf(routeService.prefix) === 0) href = href.slice(routeService.prefix.length)
+ route.set(href, undefined, undefined)
+ }
+ }
+ route.param = function(key3) {
+ if(typeof attrs3 !== "undefined" && typeof key3 !== "undefined") return attrs3[key3]
+ return attrs3
+ }
+ return route
+}
+m.route = _20(window, redrawService)
+m.withAttr = function(attrName, callback1, context) {
+ return function(e) {
+ callback1.call(context || this, attrName in e.currentTarget ? e.currentTarget[attrName] : e.currentTarget.getAttribute(attrName))
+ }
+}
+var _28 = coreRenderer(window)
+m.render = _28.render
+m.redraw = redrawService.redraw
+m.request = requestService.request
+m.jsonp = requestService.jsonp
+m.parseQueryString = parseQueryString
+m.buildQueryString = buildQueryString
+m.version = "1.1.6"
+m.vnode = Vnode
+if (typeof module !== "undefined") module["exports"] = m
+else window.m = m
+}());
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("timers").setImmediate)
+},{"timers":4}],3:[function(require,module,exports){
+// shim for using process in browser
+var process = module.exports = {};
+
+// cached from whatever global is present so that test runners that stub it
+// don't break things. But we need to wrap it in a try catch in case it is
+// wrapped in strict mode code which doesn't define any globals. It's inside a
+// function because try/catches deoptimize in certain engines.
+
+var cachedSetTimeout;
+var cachedClearTimeout;
+
+function defaultSetTimout() {
+ throw new Error('setTimeout has not been defined');
+}
+function defaultClearTimeout () {
+ throw new Error('clearTimeout has not been defined');
+}
+(function () {
+ try {
+ if (typeof setTimeout === 'function') {
+ cachedSetTimeout = setTimeout;
+ } else {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ } catch (e) {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ try {
+ if (typeof clearTimeout === 'function') {
+ cachedClearTimeout = clearTimeout;
+ } else {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+ } catch (e) {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+} ())
+function runTimeout(fun) {
+ if (cachedSetTimeout === setTimeout) {
+ //normal enviroments in sane situations
+ return setTimeout(fun, 0);
+ }
+ // if setTimeout wasn't available but was latter defined
+ if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
+ cachedSetTimeout = setTimeout;
+ return setTimeout(fun, 0);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedSetTimeout(fun, 0);
+ } catch(e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedSetTimeout.call(null, fun, 0);
+ } catch(e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
+ return cachedSetTimeout.call(this, fun, 0);
+ }
+ }
+
+
+}
+function runClearTimeout(marker) {
+ if (cachedClearTimeout === clearTimeout) {
+ //normal enviroments in sane situations
+ return clearTimeout(marker);
+ }
+ // if clearTimeout wasn't available but was latter defined
+ if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
+ cachedClearTimeout = clearTimeout;
+ return clearTimeout(marker);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedClearTimeout(marker);
+ } catch (e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedClearTimeout.call(null, marker);
+ } catch (e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
+ // Some versions of I.E. have different rules for clearTimeout vs setTimeout
+ return cachedClearTimeout.call(this, marker);
+ }
+ }
+
+
+
+}
+var queue = [];
+var draining = false;
+var currentQueue;
+var queueIndex = -1;
+
+function cleanUpNextTick() {
+ if (!draining || !currentQueue) {
+ return;
+ }
+ draining = false;
+ if (currentQueue.length) {
+ queue = currentQueue.concat(queue);
+ } else {
+ queueIndex = -1;
+ }
+ if (queue.length) {
+ drainQueue();
+ }
+}
+
+function drainQueue() {
+ if (draining) {
+ return;
+ }
+ var timeout = runTimeout(cleanUpNextTick);
+ draining = true;
+
+ var len = queue.length;
+ while(len) {
+ currentQueue = queue;
+ queue = [];
+ while (++queueIndex < len) {
+ if (currentQueue) {
+ currentQueue[queueIndex].run();
+ }
+ }
+ queueIndex = -1;
+ len = queue.length;
+ }
+ currentQueue = null;
+ draining = false;
+ runClearTimeout(timeout);
+}
+
+process.nextTick = function (fun) {
+ var args = new Array(arguments.length - 1);
+ if (arguments.length > 1) {
+ for (var i = 1; i < arguments.length; i++) {
+ args[i - 1] = arguments[i];
+ }
+ }
+ queue.push(new Item(fun, args));
+ if (queue.length === 1 && !draining) {
+ runTimeout(drainQueue);
+ }
+};
+
+// v8 likes predictible objects
+function Item(fun, array) {
+ this.fun = fun;
+ this.array = array;
+}
+Item.prototype.run = function () {
+ this.fun.apply(null, this.array);
+};
+process.title = 'browser';
+process.browser = true;
+process.env = {};
+process.argv = [];
+process.version = ''; // empty string to avoid regexp issues
+process.versions = {};
+
+function noop() {}
+
+process.on = noop;
+process.addListener = noop;
+process.once = noop;
+process.off = noop;
+process.removeListener = noop;
+process.removeAllListeners = noop;
+process.emit = noop;
+process.prependListener = noop;
+process.prependOnceListener = noop;
+
+process.listeners = function (name) { return [] }
+
+process.binding = function (name) {
+ throw new Error('process.binding is not supported');
+};
+
+process.cwd = function () { return '/' };
+process.chdir = function (dir) {
+ throw new Error('process.chdir is not supported');
+};
+process.umask = function() { return 0; };
+
+},{}],4:[function(require,module,exports){
+(function (setImmediate,clearImmediate){
+var nextTick = require('process/browser.js').nextTick;
+var apply = Function.prototype.apply;
+var slice = Array.prototype.slice;
+var immediateIds = {};
+var nextImmediateId = 0;
+
+// DOM APIs, for completeness
+
+exports.setTimeout = function() {
+ return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout);
+};
+exports.setInterval = function() {
+ return new Timeout(apply.call(setInterval, window, arguments), clearInterval);
+};
+exports.clearTimeout =
+exports.clearInterval = function(timeout) { timeout.close(); };
+
+function Timeout(id, clearFn) {
+ this._id = id;
+ this._clearFn = clearFn;
+}
+Timeout.prototype.unref = Timeout.prototype.ref = function() {};
+Timeout.prototype.close = function() {
+ this._clearFn.call(window, this._id);
+};
+
+// Does not start the time, just sets up the members needed.
+exports.enroll = function(item, msecs) {
+ clearTimeout(item._idleTimeoutId);
+ item._idleTimeout = msecs;
+};
+
+exports.unenroll = function(item) {
+ clearTimeout(item._idleTimeoutId);
+ item._idleTimeout = -1;
+};
+
+exports._unrefActive = exports.active = function(item) {
+ clearTimeout(item._idleTimeoutId);
+
+ var msecs = item._idleTimeout;
+ if (msecs >= 0) {
+ item._idleTimeoutId = setTimeout(function onTimeout() {
+ if (item._onTimeout)
+ item._onTimeout();
+ }, msecs);
+ }
+};
+
+// That's not how node.js implements it but the exposed api is the same.
+exports.setImmediate = typeof setImmediate === "function" ? setImmediate : function(fn) {
+ var id = nextImmediateId++;
+ var args = arguments.length < 2 ? false : slice.call(arguments, 1);
+
+ immediateIds[id] = true;
+
+ nextTick(function onNextTick() {
+ if (immediateIds[id]) {
+ // fn.call() is faster so we optimize for the common use-case
+ // @see http://jsperf.com/call-apply-segu
+ if (args) {
+ fn.apply(null, args);
+ } else {
+ fn.call(null);
+ }
+ // Prevent ids from leaking
+ exports.clearImmediate(id);
+ }
+ });
+
+ return id;
+};
+
+exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate : function(id) {
+ delete immediateIds[id];
+};
+}).call(this,require("timers").setImmediate,require("timers").clearImmediate)
+},{"process/browser.js":3,"timers":4}],5:[function(require,module,exports){
+module.exports = Interface;
+
+const m = require("mithril");
+
+/**
+ * Options main interface
+ *
+ * @since 3.0.0
+ *
+ * @param object settings Settings object
+ * @param function saveSettings Function to save settings
+ * @param function clearUsageData Function to clear usage data
+ * @return void
+ */
+function Interface(settings, saveSettings, clearUsageData) {
+ // public methods
+ this.attach = attach;
+ this.view = view;
+
+ // fields
+ this.settings = settings;
+ this.saveSettings = saveSettings;
+ this.saveEnabled = false;
+ this.clearUsageData = clearUsageData;
+}
+
+/**
+ * Attach the interface on the given element
+ *
+ * @since 3.0.0
+ *
+ * @param DOMElement element Target element
+ * @return void
+ */
+function attach(element) {
+ m.mount(element, this);
+}
+
+/**
+ * Generates vnodes for render
+ *
+ * @since 3.0.0
+ *
+ * @param function ctl Controller
+ * @param object params Runtime params
+ * @return []Vnode
+ */
+function view(ctl, params) {
+ var nodes = [];
+ nodes.push(m("h3", "Basic settings"));
+ nodes.push(
+ createCheckbox.call(
+ this,
+ "autoSubmit",
+ "Automatically submit forms after filling (not recommended)"
+ )
+ );
+ nodes.push(createInput.call(this, "username", "Default username", "john.smith"));
+ nodes.push(createInput.call(this, "gpgPath", "Custom gpg binary", "/path/to/gpg"));
+
+ nodes.push(m("h3", "Custom store locations"));
+ nodes.push(
+ m("div", { class: "notice" }, "(this overrides default store and $PASSWORD_STORE_DIR)")
+ );
+ for (var storeId in this.settings.stores) {
+ nodes.push(createCustomStore.call(this, storeId));
+ }
+ nodes.push(
+ m(
+ "a.add-store",
+ {
+ onclick: () => {
+ addEmptyStore(this.settings.stores);
+ this.saveEnabled = true;
+ }
+ },
+ "Add store"
+ )
+ );
+
+ if (typeof this.error !== "undefined") {
+ nodes.push(m("div.error", this.error.message));
+ }
+ if (this.settings.hasOwnProperty("hostError")) {
+ let hostError = this.settings.hostError;
+ nodes.push(m("div.error", hostError.params.message));
+ }
+
+ nodes.push(
+ m(
+ "button.save",
+ {
+ disabled: !this.saveEnabled,
+ onclick: async () => {
+ try {
+ this.settings = await this.saveSettings(this.settings);
+ this.error = undefined;
+ } catch (e) {
+ this.error = e;
+ }
+ this.saveEnabled = false;
+ m.redraw();
+ }
+ },
+ "Save"
+ )
+ );
+
+ nodes.push(
+ m(
+ "button.clearUsageData",
+ {
+ onclick: async () => {
+ try {
+ await this.clearUsageData();
+ this.error = undefined;
+ } catch (e) {
+ this.error = e;
+ }
+ m.redraw();
+ }
+ },
+ "Clear usage data"
+ )
+ );
+ return nodes;
+}
+
+/**
+ * Generates vnode for a input setting
+ *
+ * @since 3.0.0
+ *
+ * @param string key Settings key
+ * @param string title Settings title
+ * @param string placeholder Settings placeholder
+ * @return Vnode
+ */
+function createInput(key, title, placeholder) {
+ return m("div.option", { class: key }, [
+ m("label", [
+ title,
+ m("input[type=text]", {
+ value: this.settings[key],
+ placeholder: placeholder,
+ onchange: e => {
+ this.settings[key] = e.target.value;
+ this.saveEnabled = true;
+ }
+ })
+ ])
+ ]);
+}
+
+/**
+ * Generates vnode for a checkbox setting
+ *
+ * @since 3.0.0
+ *
+ * @param string key Settings key
+ * @param string title Label for the checkbox
+ * @return Vnode
+ */
+function createCheckbox(key, title) {
+ return m("div.option", { class: key }, [
+ m("label", [
+ m("input[type=checkbox]", {
+ title: title,
+ checked: this.settings[key],
+ onchange: e => {
+ this.settings[key] = e.target.checked;
+ this.saveEnabled = true;
+ }
+ }),
+ title
+ ])
+ ]);
+}
+
+/**
+ * Generates vnode for a custom store configuration
+ *
+ * @since 3.0.0
+ *
+ * @param string storeId Store ID
+ * @return Vnode
+ */
+function createCustomStore(storeId) {
+ let store = this.settings.stores[storeId];
+
+ return m("div.option.custom-store", { class: "store-" + store.name }, [
+ m("input[type=text].name", {
+ title: "The name for this password store",
+ value: store.name,
+ placeholder: "name",
+ onchange: e => {
+ store.name = e.target.value;
+ this.saveEnabled = true;
+ }
+ }),
+ m("input[type=text].path", {
+ title: "The full path to this password store",
+ value: store.path,
+ placeholder: "/path/to/store",
+ onchange: e => {
+ store.path = e.target.value;
+ this.saveEnabled = true;
+ }
+ }),
+ m("input[type=text].bgColor", {
+ title: "Badge background color",
+ value: store.bgColor,
+ placeholder: "#626262",
+ onchange: e => {
+ store.bgColor = e.target.value;
+ this.saveEnabled = true;
+ }
+ }),
+ m("input[type=text].color", {
+ title: "Badge text color",
+ value: store.color,
+ placeholder: "#c4c4c4",
+ onchange: e => {
+ store.color = e.target.value;
+ this.saveEnabled = true;
+ }
+ }),
+ m(
+ "a.remove",
+ {
+ title: "Remove this password store",
+ onclick: () => {
+ delete this.settings.stores[storeId];
+ this.saveEnabled = true;
+ }
+ },
+ "[X]"
+ )
+ ]);
+}
+
+/**
+ * Generates new store ID
+ *
+ * @since 3.0.0
+ *
+ * @return string new store ID
+ */
+function newId() {
+ return Math.random()
+ .toString(36)
+ .substr(2, 9);
+}
+
+/**
+ * Generates a new empty store
+ *
+ * @since 3.0.0
+ *
+ * @param []object stores List of stores to add a new store to
+ * @return void
+ */
+function addEmptyStore(stores) {
+ let store = { id: newId(), name: "", path: "" };
+ stores[store.id] = store;
+}
+
+},{"mithril":2}],6:[function(require,module,exports){
+//------------------------------------- Initialisation --------------------------------------//
+"use strict";
+
+require("chrome-extension-async");
+const Interface = require("./interface");
+
+run();
+
+//----------------------------------- Function definitions ----------------------------------//
+
+/**
+ * Handle an error
+ *
+ * @since 3.0.0
+ *
+ * @param Error error Error object
+ * @param string type Error type
+ */
+function handleError(error, type = "error") {
+ if (type == "error") {
+ console.log(error);
+ }
+ var errorNode = document.createElement("div");
+ errorNode.setAttribute("class", "part " + type);
+ errorNode.textContent = error.toString();
+ document.body.innerHTML = "";
+ document.body.appendChild(errorNode);
+}
+
+/**
+ * Get settings
+ *
+ * @since 3.0.9
+ *
+ * @return object Settings object
+ */
+async function getSettings() {
+ var response = await chrome.runtime.sendMessage({ action: "getSettings" });
+ if (response.status != "ok") {
+ throw new Error(response.message);
+ }
+
+ // 'default' store must not be displayed or later attempted to be saved
+ delete response.settings.stores.default;
+
+ return response.settings;
+}
+
+/**
+ * Save settings
+ *
+ * @since 3.0.0
+ *
+ * @param object settings Settings object
+ * @return object Settings object
+ */
+async function saveSettings(settings) {
+ var response = await chrome.runtime.sendMessage({
+ action: "saveSettings",
+ settings: settings
+ });
+ if (response.status != "ok") {
+ throw new Error(response.message);
+ }
+
+ // reload settings
+ return await getSettings();
+}
+
+/**
+ * Clear usage data
+ *
+ * @since 3.0.10
+ *
+ * @return void
+ */
+async function clearUsageData() {
+ var response = await chrome.runtime.sendMessage({ action: "clearUsageData" });
+ if (response.status != "ok") {
+ throw new Error(response.message);
+ }
+}
+
+/**
+ * Run the main options logic
+ *
+ * @since 3.0.0
+ *
+ * @return void
+ */
+async function run() {
+ try {
+ var options = new Interface(await getSettings(), saveSettings, clearUsageData);
+ options.attach(document.body);
+ } catch (e) {
+ handleError(e);
+ }
+}
+
+},{"./interface":5,"chrome-extension-async":1}]},{},[6]);
diff --git a/debian/js/popup.dist.js b/debian/js/popup.dist.js
new file mode 100644
index 0000000..ba75344
--- /dev/null
+++ b/debian/js/popup.dist.js
@@ -0,0 +1,12243 @@
+(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
+//------------------------------------- Initialisation --------------------------------------//
+"use strict";
+
+const FuzzySort = require("fuzzysort");
+const TldJS = require("tldjs");
+const sha1 = require("sha1");
+
+module.exports = {
+ pathToDomain,
+ prepareLogins,
+ filterSortLogins
+};
+
+//----------------------------------- Function definitions ----------------------------------//
+
+/**
+ * Get the deepest available domain component of a path
+ *
+ * @since 3.0.0
+ *
+ * @param string path Path to parse
+ * @param string currentHost Current hostname for the active tab
+ * @return string|null Extracted domain
+ */
+function pathToDomain(path, currentHost) {
+ var parts = path.split(/\//).reverse();
+ for (var key in parts) {
+ if (parts[key].indexOf("@") >= 0) {
+ continue;
+ }
+ var t = TldJS.parse(parts[key]);
+ if (
+ t.isValid &&
+ ((t.tldExists && t.domain !== null) ||
+ t.hostname === currentHost ||
+ currentHost.endsWith(`.${t.hostname}`))
+ ) {
+ return t.hostname;
+ }
+ }
+
+ return null;
+}
+
+/**
+ * Prepare list of logins based on provided files
+ *
+ * @since 3.1.0
+ *
+ * @param string array List of password files
+ * @param string object Settings object
+ * @return array List of logins
+ */
+function prepareLogins(files, settings) {
+ const logins = [];
+ let index = 0;
+
+ for (let storeId in files) {
+ for (let key in files[storeId]) {
+ // set login fields
+ const login = {
+ index: index++,
+ store: settings.stores[storeId],
+ login: files[storeId][key].replace(/\.gpg$/i, ""),
+ allowFill: true
+ };
+ login.domain = pathToDomain(storeId + "/" + login.login, settings.host);
+ login.inCurrentDomain =
+ settings.host == login.domain || settings.host.endsWith("." + login.domain);
+ login.recent =
+ settings.recent[sha1(settings.host + sha1(login.store.id + sha1(login.login)))];
+ if (!login.recent) {
+ login.recent = {
+ when: 0,
+ count: 0
+ };
+ }
+
+ logins.push(login);
+ }
+ }
+
+ return logins;
+}
+
+/**
+ * Filter and sort logins
+ *
+ * @since 3.1.0
+ *
+ * @param string array List of logins
+ * @param string object Settings object
+ * @return array Filtered and sorted list of logins
+ */
+function filterSortLogins(logins, searchQuery, currentDomainOnly) {
+ var fuzzyFirstWord = searchQuery.substr(0, 1) !== " ";
+ searchQuery = searchQuery.trim();
+
+ // get candidate list
+ var candidates = logins.map(candidate => {
+ let lastSlashIndex = candidate.login.lastIndexOf("/") + 1;
+ return Object.assign(candidate, {
+ path: candidate.login.substr(0, lastSlashIndex),
+ display: candidate.login.substr(lastSlashIndex)
+ });
+ });
+
+ var mostRecent = null;
+ if (currentDomainOnly) {
+ var recent = candidates.filter(function(login) {
+ if (login.recent.count > 0) {
+ // find most recently used login
+ if (!mostRecent || login.recent.when > mostRecent.recent.when) {
+ mostRecent = login;
+ }
+ return true;
+ }
+ return false;
+ });
+ var remainingInCurrentDomain = candidates.filter(
+ login => login.inCurrentDomain && !login.recent.count
+ );
+ candidates = recent.concat(remainingInCurrentDomain);
+ }
+
+ candidates.sort((a, b) => {
+ // show most recent first
+ if (a === mostRecent) {
+ return -1;
+ }
+ if (b === mostRecent) {
+ return 1;
+ }
+
+ // sort by frequency
+ var countDiff = b.recent.count - a.recent.count;
+ if (countDiff) {
+ return countDiff;
+ }
+
+ // sort by specificity, only if filtering for one domain
+ if (currentDomainOnly) {
+ var domainLevelsDiff =
+ (b.login.match(/\./g) || []).length - (a.login.match(/\./g) || []).length;
+ if (domainLevelsDiff) {
+ return domainLevelsDiff;
+ }
+ }
+
+ // sort alphabetically
+ return a.login.localeCompare(b.login);
+ });
+
+ if (searchQuery.length) {
+ let filter = searchQuery.split(/\s+/);
+ let fuzzyFilter = fuzzyFirstWord ? filter[0] : "";
+ let substringFilters = filter.slice(fuzzyFirstWord ? 1 : 0).map(w => w.toLowerCase());
+
+ // First reduce the list by running the substring search
+ substringFilters.forEach(function(word) {
+ candidates = candidates.filter(c => c.login.toLowerCase().indexOf(word) >= 0);
+ });
+
+ // Then run the fuzzy filter
+ let fuzzyResults = {};
+ if (fuzzyFilter) {
+ candidates = FuzzySort.go(fuzzyFilter, candidates, {
+ keys: ["login", "store.name"],
+ allowTypo: false
+ }).map(result => {
+ fuzzyResults[result.obj.login] = result;
+ return result.obj;
+ });
+ }
+
+ // Finally highlight all matches
+ candidates = candidates.map(c => highlightMatches(c, fuzzyResults, substringFilters));
+ }
+
+ // Prefix root entries with slash to let them have some visible path
+ candidates.forEach(c => {
+ c.path = c.path || "/";
+ });
+
+ return candidates;
+}
+
+//----------------------------------- Private functions ----------------------------------//
+
+/**
+ * Highlight filter matches
+ *
+ * @since 3.0.0
+ *
+ * @param object entry password entry
+ * @param object fuzzyResults positions of fuzzy filter matches
+ * @param array substringFilters list of substring filters applied
+ * @return object entry with highlighted matches
+ */
+function highlightMatches(entry, fuzzyResults, substringFilters) {
+ // Add all positions of the fuzzy search to the array
+ let matches = (fuzzyResults[entry.login] && fuzzyResults[entry.login][0]
+ ? fuzzyResults[entry.login][0].indexes
+ : []
+ ).slice();
+
+ // Add all positions of substring searches to the array
+ let login = entry.login.toLowerCase();
+ for (let word of substringFilters) {
+ let startIndex = login.indexOf(word);
+ for (let i = 0; i < word.length; i++) {
+ matches.push(startIndex + i);
+ }
+ }
+
+ // Prepare the final array of matches before
+ matches = sortUnique(matches, (a, b) => a - b);
+
+ const OPEN = "<em>";
+ const CLOSE = "</em>";
+ let highlighted = "";
+ var matchesIndex = 0;
+ var opened = false;
+ for (var i = 0; i < entry.login.length; ++i) {
+ var char = entry.login[i];
+
+ if (i == entry.path.length) {
+ if (opened) {
+ highlighted += CLOSE;
+ }
+ var path = highlighted;
+ highlighted = "";
+ if (opened) {
+ highlighted += OPEN;
+ }
+ }
+
+ if (matches[matchesIndex] === i) {
+ matchesIndex++;
+ if (!opened) {
+ opened = true;
+ highlighted += OPEN;
+ }
+ } else {
+ if (opened) {
+ opened = false;
+ highlighted += CLOSE;
+ }
+ }
+ highlighted += char;
+ }
+ if (opened) {
+ opened = false;
+ highlighted += CLOSE;
+ }
+ let display = highlighted;
+
+ return Object.assign(entry, {
+ path: path,
+ display: display
+ });
+}
+
+/**
+ * Sort and remove duplicates
+ *
+ * @since 3.0.0
+ *
+ * @param array array items to sort
+ * @param function comparator sort comparator
+ * @return array sorted items without duplicates
+ */
+function sortUnique(array, comparator) {
+ return array
+ .sort(comparator)
+ .filter((elem, index, arr) => index == !arr.length || arr[index - 1] != elem);
+}
+
+},{"fuzzysort":7,"sha1":16,"tldjs":18}],2:[function(require,module,exports){
+'use strict'
+
+exports.byteLength = byteLength
+exports.toByteArray = toByteArray
+exports.fromByteArray = fromByteArray
+
+var lookup = []
+var revLookup = []
+var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
+
+var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
+for (var i = 0, len = code.length; i < len; ++i) {
+ lookup[i] = code[i]
+ revLookup[code.charCodeAt(i)] = i
+}
+
+// Support decoding URL-safe base64 strings, as Node.js does.
+// See: https://en.wikipedia.org/wiki/Base64#URL_applications
+revLookup['-'.charCodeAt(0)] = 62
+revLookup['_'.charCodeAt(0)] = 63
+
+function getLens (b64) {
+ var len = b64.length
+
+ if (len % 4 > 0) {
+ throw new Error('Invalid string. Length must be a multiple of 4')
+ }
+
+ // Trim off extra bytes after placeholder bytes are found
+ // See: https://github.com/beatgammit/base64-js/issues/42
+ var validLen = b64.indexOf('=')
+ if (validLen === -1) validLen = len
+
+ var placeHoldersLen = validLen === len
+ ? 0
+ : 4 - (validLen % 4)
+
+ return [validLen, placeHoldersLen]
+}
+
+// base64 is 4/3 + up to two characters of the original data
+function byteLength (b64) {
+ var lens = getLens(b64)
+ var validLen = lens[0]
+ var placeHoldersLen = lens[1]
+ return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
+}
+
+function _byteLength (b64, validLen, placeHoldersLen) {
+ return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
+}
+
+function toByteArray (b64) {
+ var tmp
+ var lens = getLens(b64)
+ var validLen = lens[0]
+ var placeHoldersLen = lens[1]
+
+ var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))
+
+ var curByte = 0
+
+ // if there are placeholders, only get up to the last complete 4 chars
+ var len = placeHoldersLen > 0
+ ? validLen - 4
+ : validLen
+
+ for (var i = 0; i < len; i += 4) {
+ tmp =
+ (revLookup[b64.charCodeAt(i)] << 18) |
+ (revLookup[b64.charCodeAt(i + 1)] << 12) |
+ (revLookup[b64.charCodeAt(i + 2)] << 6) |
+ revLookup[b64.charCodeAt(i + 3)]
+ arr[curByte++] = (tmp >> 16) & 0xFF
+ arr[curByte++] = (tmp >> 8) & 0xFF
+ arr[curByte++] = tmp & 0xFF
+ }
+
+ if (placeHoldersLen === 2) {
+ tmp =
+ (revLookup[b64.charCodeAt(i)] << 2) |
+ (revLookup[b64.charCodeAt(i + 1)] >> 4)
+ arr[curByte++] = tmp & 0xFF
+ }
+
+ if (placeHoldersLen === 1) {
+ tmp =
+ (revLookup[b64.charCodeAt(i)] << 10) |
+ (revLookup[b64.charCodeAt(i + 1)] << 4) |
+ (revLookup[b64.charCodeAt(i + 2)] >> 2)
+ arr[curByte++] = (tmp >> 8) & 0xFF
+ arr[curByte++] = tmp & 0xFF
+ }
+
+ return arr
+}
+
+function tripletToBase64 (num) {
+ return lookup[num >> 18 & 0x3F] +
+ lookup[num >> 12 & 0x3F] +
+ lookup[num >> 6 & 0x3F] +
+ lookup[num & 0x3F]
+}
+
+function encodeChunk (uint8, start, end) {
+ var tmp
+ var output = []
+ for (var i = start; i < end; i += 3) {
+ tmp =
+ ((uint8[i] << 16) & 0xFF0000) +
+ ((uint8[i + 1] << 8) & 0xFF00) +
+ (uint8[i + 2] & 0xFF)
+ output.push(tripletToBase64(tmp))
+ }
+ return output.join('')
+}
+
+function fromByteArray (uint8) {
+ var tmp
+ var len = uint8.length
+ var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
+ var parts = []
+ var maxChunkLength = 16383 // must be multiple of 3
+
+ // go through the array every three bytes, we'll deal with trailing stuff later
+ for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
+ parts.push(encodeChunk(
+ uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)
+ ))
+ }
+
+ // pad the end with zeros, but make sure to not forget the extra bytes
+ if (extraBytes === 1) {
+ tmp = uint8[len - 1]
+ parts.push(
+ lookup[tmp >> 2] +
+ lookup[(tmp << 4) & 0x3F] +
+ '=='
+ )
+ } else if (extraBytes === 2) {
+ tmp = (uint8[len - 2] << 8) + uint8[len - 1]
+ parts.push(
+ lookup[tmp >> 10] +
+ lookup[(tmp >> 4) & 0x3F] +
+ lookup[(tmp << 2) & 0x3F] +
+ '='
+ )
+ }
+
+ return parts.join('')
+}
+
+},{}],3:[function(require,module,exports){
+/*!
+ * The buffer module from node.js, for the browser.
+ *
+ * @author Feross Aboukhadijeh <https://feross.org>
+ * @license MIT
+ */
+/* eslint-disable no-proto */
+
+'use strict'
+
+var base64 = require('base64-js')
+var ieee754 = require('ieee754')
+
+exports.Buffer = Buffer
+exports.SlowBuffer = SlowBuffer
+exports.INSPECT_MAX_BYTES = 50
+
+var K_MAX_LENGTH = 0x7fffffff
+exports.kMaxLength = K_MAX_LENGTH
+
+/**
+ * If `Buffer.TYPED_ARRAY_SUPPORT`:
+ * === true Use Uint8Array implementation (fastest)
+ * === false Print warning and recommend using `buffer` v4.x which has an Object
+ * implementation (most compatible, even IE6)
+ *
+ * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
+ * Opera 11.6+, iOS 4.2+.
+ *
+ * We report that the browser does not support typed arrays if the are not subclassable
+ * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array`
+ * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support
+ * for __proto__ and has a buggy typed array implementation.
+ */
+Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport()
+
+if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' &&
+ typeof console.error === 'function') {
+ console.error(
+ 'This browser lacks typed array (Uint8Array) support which is required by ' +
+ '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.'
+ )
+}
+
+function typedArraySupport () {
+ // Can typed array instances can be augmented?
+ try {
+ var arr = new Uint8Array(1)
+ arr.__proto__ = { __proto__: Uint8Array.prototype, foo: function () { return 42 } }
+ return arr.foo() === 42
+ } catch (e) {
+ return false
+ }
+}
+
+Object.defineProperty(Buffer.prototype, 'parent', {
+ enumerable: true,
+ get: function () {
+ if (!Buffer.isBuffer(this)) return undefined
+ return this.buffer
+ }
+})
+
+Object.defineProperty(Buffer.prototype, 'offset', {
+ enumerable: true,
+ get: function () {
+ if (!Buffer.isBuffer(this)) return undefined
+ return this.byteOffset
+ }
+})
+
+function createBuffer (length) {
+ if (length > K_MAX_LENGTH) {
+ throw new RangeError('The value "' + length + '" is invalid for option "size"')
+ }
+ // Return an augmented `Uint8Array` instance
+ var buf = new Uint8Array(length)
+ buf.__proto__ = Buffer.prototype
+ return buf
+}
+
+/**
+ * The Buffer constructor returns instances of `Uint8Array` that have their
+ * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
+ * `Uint8Array`, so the returned instances will have all the node `Buffer` methods
+ * and the `Uint8Array` methods. Square bracket notation works as expected -- it
+ * returns a single octet.
+ *
+ * The `Uint8Array` prototype remains unmodified.
+ */
+
+function Buffer (arg, encodingOrOffset, length) {
+ // Common case.
+ if (typeof arg === 'number') {
+ if (typeof encodingOrOffset === 'string') {
+ throw new TypeError(
+ 'The "string" argument must be of type string. Received type number'
+ )
+ }
+ return allocUnsafe(arg)
+ }
+ return from(arg, encodingOrOffset, length)
+}
+
+// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97
+if (typeof Symbol !== 'undefined' && Symbol.species != null &&
+ Buffer[Symbol.species] === Buffer) {
+ Object.defineProperty(Buffer, Symbol.species, {
+ value: null,
+ configurable: true,
+ enumerable: false,
+ writable: false
+ })
+}
+
+Buffer.poolSize = 8192 // not used by this implementation
+
+function from (value, encodingOrOffset, length) {
+ if (typeof value === 'string') {
+ return fromString(value, encodingOrOffset)
+ }
+
+ if (ArrayBuffer.isView(value)) {
+ return fromArrayLike(value)
+ }
+
+ if (value == null) {
+ throw TypeError(
+ 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' +
+ 'or Array-like Object. Received type ' + (typeof value)
+ )
+ }
+
+ if (isInstance(value, ArrayBuffer) ||
+ (value && isInstance(value.buffer, ArrayBuffer))) {
+ return fromArrayBuffer(value, encodingOrOffset, length)
+ }
+
+ if (typeof value === 'number') {
+ throw new TypeError(
+ 'The "value" argument must not be of type number. Received type number'
+ )
+ }
+
+ var valueOf = value.valueOf && value.valueOf()
+ if (valueOf != null && valueOf !== value) {
+ return Buffer.from(valueOf, encodingOrOffset, length)
+ }
+
+ var b = fromObject(value)
+ if (b) return b
+
+ if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null &&
+ typeof value[Symbol.toPrimitive] === 'function') {
+ return Buffer.from(
+ value[Symbol.toPrimitive]('string'), encodingOrOffset, length
+ )
+ }
+
+ throw new TypeError(
+ 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' +
+ 'or Array-like Object. Received type ' + (typeof value)
+ )
+}
+
+/**
+ * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError
+ * if value is a number.
+ * Buffer.from(str[, encoding])
+ * Buffer.from(array)
+ * Buffer.from(buffer)
+ * Buffer.from(arrayBuffer[, byteOffset[, length]])
+ **/
+Buffer.from = function (value, encodingOrOffset, length) {
+ return from(value, encodingOrOffset, length)
+}
+
+// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug:
+// https://github.com/feross/buffer/pull/148
+Buffer.prototype.__proto__ = Uint8Array.prototype
+Buffer.__proto__ = Uint8Array
+
+function assertSize (size) {
+ if (typeof size !== 'number') {
+ throw new TypeError('"size" argument must be of type number')
+ } else if (size < 0) {
+ throw new RangeError('The value "' + size + '" is invalid for option "size"')
+ }
+}
+
+function alloc (size, fill, encoding) {
+ assertSize(size)
+ if (size <= 0) {
+ return createBuffer(size)
+ }
+ if (fill !== undefined) {
+ // Only pay attention to encoding if it's a string. This
+ // prevents accidentally sending in a number that would
+ // be interpretted as a start offset.
+ return typeof encoding === 'string'
+ ? createBuffer(size).fill(fill, encoding)
+ : createBuffer(size).fill(fill)
+ }
+ return createBuffer(size)
+}
+
+/**
+ * Creates a new filled Buffer instance.
+ * alloc(size[, fill[, encoding]])
+ **/
+Buffer.alloc = function (size, fill, encoding) {
+ return alloc(size, fill, encoding)
+}
+
+function allocUnsafe (size) {
+ assertSize(size)
+ return createBuffer(size < 0 ? 0 : checked(size) | 0)
+}
+
+/**
+ * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
+ * */
+Buffer.allocUnsafe = function (size) {
+ return allocUnsafe(size)
+}
+/**
+ * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
+ */
+Buffer.allocUnsafeSlow = function (size) {
+ return allocUnsafe(size)
+}
+
+function fromString (string, encoding) {
+ if (typeof encoding !== 'string' || encoding === '') {
+ encoding = 'utf8'
+ }
+
+ if (!Buffer.isEncoding(encoding)) {
+ throw new TypeError('Unknown encoding: ' + encoding)
+ }
+
+ var length = byteLength(string, encoding) | 0
+ var buf = createBuffer(length)
+
+ var actual = buf.write(string, encoding)
+
+ if (actual !== length) {
+ // Writing a hex string, for example, that contains invalid characters will
+ // cause everything after the first invalid character to be ignored. (e.g.
+ // 'abxxcd' will be treated as 'ab')
+ buf = buf.slice(0, actual)
+ }
+
+ return buf
+}
+
+function fromArrayLike (array) {
+ var length = array.length < 0 ? 0 : checked(array.length) | 0
+ var buf = createBuffer(length)
+ for (var i = 0; i < length; i += 1) {
+ buf[i] = array[i] & 255
+ }
+ return buf
+}
+
+function fromArrayBuffer (array, byteOffset, length) {
+ if (byteOffset < 0 || array.byteLength < byteOffset) {
+ throw new RangeError('"offset" is outside of buffer bounds')
+ }
+
+ if (array.byteLength < byteOffset + (length || 0)) {
+ throw new RangeError('"length" is outside of buffer bounds')
+ }
+
+ var buf
+ if (byteOffset === undefined && length === undefined) {
+ buf = new Uint8Array(array)
+ } else if (length === undefined) {
+ buf = new Uint8Array(array, byteOffset)
+ } else {
+ buf = new Uint8Array(array, byteOffset, length)
+ }
+
+ // Return an augmented `Uint8Array` instance
+ buf.__proto__ = Buffer.prototype
+ return buf
+}
+
+function fromObject (obj) {
+ if (Buffer.isBuffer(obj)) {
+ var len = checked(obj.length) | 0
+ var buf = createBuffer(len)
+
+ if (buf.length === 0) {
+ return buf
+ }
+
+ obj.copy(buf, 0, 0, len)
+ return buf
+ }
+
+ if (obj.length !== undefined) {
+ if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) {
+ return createBuffer(0)
+ }
+ return fromArrayLike(obj)
+ }
+
+ if (obj.type === 'Buffer' && Array.isArray(obj.data)) {
+ return fromArrayLike(obj.data)
+ }
+}
+
+function checked (length) {
+ // Note: cannot use `length < K_MAX_LENGTH` here because that fails when
+ // length is NaN (which is otherwise coerced to zero.)
+ if (length >= K_MAX_LENGTH) {
+ throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
+ 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes')
+ }
+ return length | 0
+}
+
+function SlowBuffer (length) {
+ if (+length != length) { // eslint-disable-line eqeqeq
+ length = 0
+ }
+ return Buffer.alloc(+length)
+}
+
+Buffer.isBuffer = function isBuffer (b) {
+ return b != null && b._isBuffer === true &&
+ b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false
+}
+
+Buffer.compare = function compare (a, b) {
+ if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength)
+ if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength)
+ if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
+ throw new TypeError(
+ 'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array'
+ )
+ }
+
+ if (a === b) return 0
+
+ var x = a.length
+ var y = b.length
+
+ for (var i = 0, len = Math.min(x, y); i < len; ++i) {
+ if (a[i] !== b[i]) {
+ x = a[i]
+ y = b[i]
+ break
+ }
+ }
+
+ if (x < y) return -1
+ if (y < x) return 1
+ return 0
+}
+
+Buffer.isEncoding = function isEncoding (encoding) {
+ switch (String(encoding).toLowerCase()) {
+ case 'hex':
+ case 'utf8':
+ case 'utf-8':
+ case 'ascii':
+ case 'latin1':
+ case 'binary':
+ case 'base64':
+ case 'ucs2':
+ case 'ucs-2':
+ case 'utf16le':
+ case 'utf-16le':
+ return true
+ default:
+ return false
+ }
+}
+
+Buffer.concat = function concat (list, length) {
+ if (!Array.isArray(list)) {
+ throw new TypeError('"list" argument must be an Array of Buffers')
+ }
+
+ if (list.length === 0) {
+ return Buffer.alloc(0)
+ }
+
+ var i
+ if (length === undefined) {
+ length = 0
+ for (i = 0; i < list.length; ++i) {
+ length += list[i].length
+ }
+ }
+
+ var buffer = Buffer.allocUnsafe(length)
+ var pos = 0
+ for (i = 0; i < list.length; ++i) {
+ var buf = list[i]
+ if (isInstance(buf, Uint8Array)) {
+ buf = Buffer.from(buf)
+ }
+ if (!Buffer.isBuffer(buf)) {
+ throw new TypeError('"list" argument must be an Array of Buffers')
+ }
+ buf.copy(buffer, pos)
+ pos += buf.length
+ }
+ return buffer
+}
+
+function byteLength (string, encoding) {
+ if (Buffer.isBuffer(string)) {
+ return string.length
+ }
+ if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) {
+ return string.byteLength
+ }
+ if (typeof string !== 'string') {
+ throw new TypeError(
+ 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' +
+ 'Received type ' + typeof string
+ )
+ }
+
+ var len = string.length
+ var mustMatch = (arguments.length > 2 && arguments[2] === true)
+ if (!mustMatch && len === 0) return 0
+
+ // Use a for loop to avoid recursion
+ var loweredCase = false
+ for (;;) {
+ switch (encoding) {
+ case 'ascii':
+ case 'latin1':
+ case 'binary':
+ return len
+ case 'utf8':
+ case 'utf-8':
+ return utf8ToBytes(string).length
+ case 'ucs2':
+ case 'ucs-2':
+ case 'utf16le':
+ case 'utf-16le':
+ return len * 2
+ case 'hex':
+ return len >>> 1
+ case 'base64':
+ return base64ToBytes(string).length
+ default:
+ if (loweredCase) {
+ return mustMatch ? -1 : utf8ToBytes(string).length // assume utf8
+ }
+ encoding = ('' + encoding).toLowerCase()
+ loweredCase = true
+ }
+ }
+}
+Buffer.byteLength = byteLength
+
+function slowToString (encoding, start, end) {
+ var loweredCase = false
+
+ // No need to verify that "this.length <= MAX_UINT32" since it's a read-only
+ // property of a typed array.
+
+ // This behaves neither like String nor Uint8Array in that we set start/end
+ // to their upper/lower bounds if the value passed is out of range.
+ // undefined is handled specially as per ECMA-262 6th Edition,
+ // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.
+ if (start === undefined || start < 0) {
+ start = 0
+ }
+ // Return early if start > this.length. Done here to prevent potential uint32
+ // coercion fail below.
+ if (start > this.length) {
+ return ''
+ }
+
+ if (end === undefined || end > this.length) {
+ end = this.length
+ }
+
+ if (end <= 0) {
+ return ''
+ }
+
+ // Force coersion to uint32. This will also coerce falsey/NaN values to 0.
+ end >>>= 0
+ start >>>= 0
+
+ if (end <= start) {
+ return ''
+ }
+
+ if (!encoding) encoding = 'utf8'
+
+ while (true) {
+ switch (encoding) {
+ case 'hex':
+ return hexSlice(this, start, end)
+
+ case 'utf8':
+ case 'utf-8':
+ return utf8Slice(this, start, end)
+
+ case 'ascii':
+ return asciiSlice(this, start, end)
+
+ case 'latin1':
+ case 'binary':
+ return latin1Slice(this, start, end)
+
+ case 'base64':
+ return base64Slice(this, start, end)
+
+ case 'ucs2':
+ case 'ucs-2':
+ case 'utf16le':
+ case 'utf-16le':
+ return utf16leSlice(this, start, end)
+
+ default:
+ if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
+ encoding = (encoding + '').toLowerCase()
+ loweredCase = true
+ }
+ }
+}
+
+// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package)
+// to detect a Buffer instance. It's not possible to use `instanceof Buffer`
+// reliably in a browserify context because there could be multiple different
+// copies of the 'buffer' package in use. This method works even for Buffer
+// instances that were created from another copy of the `buffer` package.
+// See: https://github.com/feross/buffer/issues/154
+Buffer.prototype._isBuffer = true
+
+function swap (b, n, m) {
+ var i = b[n]
+ b[n] = b[m]
+ b[m] = i
+}
+
+Buffer.prototype.swap16 = function swap16 () {
+ var len = this.length
+ if (len % 2 !== 0) {
+ throw new RangeError('Buffer size must be a multiple of 16-bits')
+ }
+ for (var i = 0; i < len; i += 2) {
+ swap(this, i, i + 1)
+ }
+ return this
+}
+
+Buffer.prototype.swap32 = function swap32 () {
+ var len = this.length
+ if (len % 4 !== 0) {
+ throw new RangeError('Buffer size must be a multiple of 32-bits')
+ }
+ for (var i = 0; i < len; i += 4) {
+ swap(this, i, i + 3)
+ swap(this, i + 1, i + 2)
+ }
+ return this
+}
+
+Buffer.prototype.swap64 = function swap64 () {
+ var len = this.length
+ if (len % 8 !== 0) {
+ throw new RangeError('Buffer size must be a multiple of 64-bits')
+ }
+ for (var i = 0; i < len; i += 8) {
+ swap(this, i, i + 7)
+ swap(this, i + 1, i + 6)
+ swap(this, i + 2, i + 5)
+ swap(this, i + 3, i + 4)
+ }
+ return this
+}
+
+Buffer.prototype.toString = function toString () {
+ var length = this.length
+ if (length === 0) return ''
+ if (arguments.length === 0) return utf8Slice(this, 0, length)
+ return slowToString.apply(this, arguments)
+}
+
+Buffer.prototype.toLocaleString = Buffer.prototype.toString
+
+Buffer.prototype.equals = function equals (b) {
+ if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
+ if (this === b) return true
+ return Buffer.compare(this, b) === 0
+}
+
+Buffer.prototype.inspect = function inspect () {
+ var str = ''
+ var max = exports.INSPECT_MAX_BYTES
+ str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim()
+ if (this.length > max) str += ' ... '
+ return '<Buffer ' + str + '>'
+}
+
+Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) {
+ if (isInstance(target, Uint8Array)) {
+ target = Buffer.from(target, target.offset, target.byteLength)
+ }
+ if (!Buffer.isBuffer(target)) {
+ throw new TypeError(
+ 'The "target" argument must be one of type Buffer or Uint8Array. ' +
+ 'Received type ' + (typeof target)
+ )
+ }
+
+ if (start === undefined) {
+ start = 0
+ }
+ if (end === undefined) {
+ end = target ? target.length : 0
+ }
+ if (thisStart === undefined) {
+ thisStart = 0
+ }
+ if (thisEnd === undefined) {
+ thisEnd = this.length
+ }
+
+ if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) {
+ throw new RangeError('out of range index')
+ }
+
+ if (thisStart >= thisEnd && start >= end) {
+ return 0
+ }
+ if (thisStart >= thisEnd) {
+ return -1
+ }
+ if (start >= end) {
+ return 1
+ }
+
+ start >>>= 0
+ end >>>= 0
+ thisStart >>>= 0
+ thisEnd >>>= 0
+
+ if (this === target) return 0
+
+ var x = thisEnd - thisStart
+ var y = end - start
+ var len = Math.min(x, y)
+
+ var thisCopy = this.slice(thisStart, thisEnd)
+ var targetCopy = target.slice(start, end)
+
+ for (var i = 0; i < len; ++i) {
+ if (thisCopy[i] !== targetCopy[i]) {
+ x = thisCopy[i]
+ y = targetCopy[i]
+ break
+ }
+ }
+
+ if (x < y) return -1
+ if (y < x) return 1
+ return 0
+}
+
+// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,
+// OR the last index of `val` in `buffer` at offset <= `byteOffset`.
+//
+// Arguments:
+// - buffer - a Buffer to search
+// - val - a string, Buffer, or number
+// - byteOffset - an index into `buffer`; will be clamped to an int32
+// - encoding - an optional encoding, relevant is val is a string
+// - dir - true for indexOf, false for lastIndexOf
+function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) {
+ // Empty buffer means no match
+ if (buffer.length === 0) return -1
+
+ // Normalize byteOffset
+ if (typeof byteOffset === 'string') {
+ encoding = byteOffset
+ byteOffset = 0
+ } else if (byteOffset > 0x7fffffff) {
+ byteOffset = 0x7fffffff
+ } else if (byteOffset < -0x80000000) {
+ byteOffset = -0x80000000
+ }
+ byteOffset = +byteOffset // Coerce to Number.
+ if (numberIsNaN(byteOffset)) {
+ // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer
+ byteOffset = dir ? 0 : (buffer.length - 1)
+ }
+
+ // Normalize byteOffset: negative offsets start from the end of the buffer
+ if (byteOffset < 0) byteOffset = buffer.length + byteOffset
+ if (byteOffset >= buffer.length) {
+ if (dir) return -1
+ else byteOffset = buffer.length - 1
+ } else if (byteOffset < 0) {
+ if (dir) byteOffset = 0
+ else return -1
+ }
+
+ // Normalize val
+ if (typeof val === 'string') {
+ val = Buffer.from(val, encoding)
+ }
+
+ // Finally, search either indexOf (if dir is true) or lastIndexOf
+ if (Buffer.isBuffer(val)) {
+ // Special case: looking for empty string/buffer always fails
+ if (val.length === 0) {
+ return -1
+ }
+ return arrayIndexOf(buffer, val, byteOffset, encoding, dir)
+ } else if (typeof val === 'number') {
+ val = val & 0xFF // Search for a byte value [0-255]
+ if (typeof Uint8Array.prototype.indexOf === 'function') {
+ if (dir) {
+ return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset)
+ } else {
+ return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset)
+ }
+ }
+ return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir)
+ }
+
+ throw new TypeError('val must be string, number or Buffer')
+}
+
+function arrayIndexOf (arr, val, byteOffset, encoding, dir) {
+ var indexSize = 1
+ var arrLength = arr.length
+ var valLength = val.length
+
+ if (encoding !== undefined) {
+ encoding = String(encoding).toLowerCase()
+ if (encoding === 'ucs2' || encoding === 'ucs-2' ||
+ encoding === 'utf16le' || encoding === 'utf-16le') {
+ if (arr.length < 2 || val.length < 2) {
+ return -1
+ }
+ indexSize = 2
+ arrLength /= 2
+ valLength /= 2
+ byteOffset /= 2
+ }
+ }
+
+ function read (buf, i) {
+ if (indexSize === 1) {
+ return buf[i]
+ } else {
+ return buf.readUInt16BE(i * indexSize)
+ }
+ }
+
+ var i
+ if (dir) {
+ var foundIndex = -1
+ for (i = byteOffset; i < arrLength; i++) {
+ if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {
+ if (foundIndex === -1) foundIndex = i
+ if (i - foundIndex + 1 === valLength) return foundIndex * indexSize
+ } else {
+ if (foundIndex !== -1) i -= i - foundIndex
+ foundIndex = -1
+ }
+ }
+ } else {
+ if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength
+ for (i = byteOffset; i >= 0; i--) {
+ var found = true
+ for (var j = 0; j < valLength; j++) {
+ if (read(arr, i + j) !== read(val, j)) {
+ found = false
+ break
+ }
+ }
+ if (found) return i
+ }
+ }
+
+ return -1
+}
+
+Buffer.prototype.includes = function includes (val, byteOffset, encoding) {
+ return this.indexOf(val, byteOffset, encoding) !== -1
+}
+
+Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) {
+ return bidirectionalIndexOf(this, val, byteOffset, encoding, true)
+}
+
+Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) {
+ return bidirectionalIndexOf(this, val, byteOffset, encoding, false)
+}
+
+function hexWrite (buf, string, offset, length) {
+ offset = Number(offset) || 0
+ var remaining = buf.length - offset
+ if (!length) {
+ length = remaining
+ } else {
+ length = Number(length)
+ if (length > remaining) {
+ length = remaining
+ }
+ }
+
+ var strLen = string.length
+
+ if (length > strLen / 2) {
+ length = strLen / 2
+ }
+ for (var i = 0; i < length; ++i) {
+ var parsed = parseInt(string.substr(i * 2, 2), 16)
+ if (numberIsNaN(parsed)) return i
+ buf[offset + i] = parsed
+ }
+ return i
+}
+
+function utf8Write (buf, string, offset, length) {
+ return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
+}
+
+function asciiWrite (buf, string, offset, length) {
+ return blitBuffer(asciiToBytes(string), buf, offset, length)
+}
+
+function latin1Write (buf, string, offset, length) {
+ return asciiWrite(buf, string, offset, length)
+}
+
+function base64Write (buf, string, offset, length) {
+ return blitBuffer(base64ToBytes(string), buf, offset, length)
+}
+
+function ucs2Write (buf, string, offset, length) {
+ return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
+}
+
+Buffer.prototype.write = function write (string, offset, length, encoding) {
+ // Buffer#write(string)
+ if (offset === undefined) {
+ encoding = 'utf8'
+ length = this.length
+ offset = 0
+ // Buffer#write(string, encoding)
+ } else if (length === undefined && typeof offset === 'string') {
+ encoding = offset
+ length = this.length
+ offset = 0
+ // Buffer#write(string, offset[, length][, encoding])
+ } else if (isFinite(offset)) {
+ offset = offset >>> 0
+ if (isFinite(length)) {
+ length = length >>> 0
+ if (encoding === undefined) encoding = 'utf8'
+ } else {
+ encoding = length
+ length = undefined
+ }
+ } else {
+ throw new Error(
+ 'Buffer.write(string, encoding, offset[, length]) is no longer supported'
+ )
+ }
+
+ var remaining = this.length - offset
+ if (length === undefined || length > remaining) length = remaining
+
+ if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
+ throw new RangeError('Attempt to write outside buffer bounds')
+ }
+
+ if (!encoding) encoding = 'utf8'
+
+ var loweredCase = false
+ for (;;) {
+ switch (encoding) {
+ case 'hex':
+ return hexWrite(this, string, offset, length)
+
+ case 'utf8':
+ case 'utf-8':
+ return utf8Write(this, string, offset, length)
+
+ case 'ascii':
+ return asciiWrite(this, string, offset, length)
+
+ case 'latin1':
+ case 'binary':
+ return latin1Write(this, string, offset, length)
+
+ case 'base64':
+ // Warning: maxLength not taken into account in base64Write
+ return base64Write(this, string, offset, length)
+
+ case 'ucs2':
+ case 'ucs-2':
+ case 'utf16le':
+ case 'utf-16le':
+ return ucs2Write(this, string, offset, length)
+
+ default:
+ if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
+ encoding = ('' + encoding).toLowerCase()
+ loweredCase = true
+ }
+ }
+}
+
+Buffer.prototype.toJSON = function toJSON () {
+ return {
+ type: 'Buffer',
+ data: Array.prototype.slice.call(this._arr || this, 0)
+ }
+}
+
+function base64Slice (buf, start, end) {
+ if (start === 0 && end === buf.length) {
+ return base64.fromByteArray(buf)
+ } else {
+ return base64.fromByteArray(buf.slice(start, end))
+ }
+}
+
+function utf8Slice (buf, start, end) {
+ end = Math.min(buf.length, end)
+ var res = []
+
+ var i = start
+ while (i < end) {
+ var firstByte = buf[i]
+ var codePoint = null
+ var bytesPerSequence = (firstByte > 0xEF) ? 4
+ : (firstByte > 0xDF) ? 3
+ : (firstByte > 0xBF) ? 2
+ : 1
+
+ if (i + bytesPerSequence <= end) {
+ var secondByte, thirdByte, fourthByte, tempCodePoint
+
+ switch (bytesPerSequence) {
+ case 1:
+ if (firstByte < 0x80) {
+ codePoint = firstByte
+ }
+ break
+ case 2:
+ secondByte = buf[i + 1]
+ if ((secondByte & 0xC0) === 0x80) {
+ tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
+ if (tempCodePoint > 0x7F) {
+ codePoint = tempCodePoint
+ }
+ }
+ break
+ case 3:
+ secondByte = buf[i + 1]
+ thirdByte = buf[i + 2]
+ if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
+ tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
+ if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
+ codePoint = tempCodePoint
+ }
+ }
+ break
+ case 4:
+ secondByte = buf[i + 1]
+ thirdByte = buf[i + 2]
+ fourthByte = buf[i + 3]
+ if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
+ tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
+ if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
+ codePoint = tempCodePoint
+ }
+ }
+ }
+ }
+
+ if (codePoint === null) {
+ // we did not generate a valid codePoint so insert a
+ // replacement char (U+FFFD) and advance only 1 byte
+ codePoint = 0xFFFD
+ bytesPerSequence = 1
+ } else if (codePoint > 0xFFFF) {
+ // encode to utf16 (surrogate pair dance)
+ codePoint -= 0x10000
+ res.push(codePoint >>> 10 & 0x3FF | 0xD800)
+ codePoint = 0xDC00 | codePoint & 0x3FF
+ }
+
+ res.push(codePoint)
+ i += bytesPerSequence
+ }
+
+ return decodeCodePointsArray(res)
+}
+
+// Based on http://stackoverflow.com/a/22747272/680742, the browser with
+// the lowest limit is Chrome, with 0x10000 args.
+// We go 1 magnitude less, for safety
+var MAX_ARGUMENTS_LENGTH = 0x1000
+
+function decodeCodePointsArray (codePoints) {
+ var len = codePoints.length
+ if (len <= MAX_ARGUMENTS_LENGTH) {
+ return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
+ }
+
+ // Decode in chunks to avoid "call stack size exceeded".
+ var res = ''
+ var i = 0
+ while (i < len) {
+ res += String.fromCharCode.apply(
+ String,
+ codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
+ )
+ }
+ return res
+}
+
+function asciiSlice (buf, start, end) {
+ var ret = ''
+ end = Math.min(buf.length, end)
+
+ for (var i = start; i < end; ++i) {
+ ret += String.fromCharCode(buf[i] & 0x7F)
+ }
+ return ret
+}
+
+function latin1Slice (buf, start, end) {
+ var ret = ''
+ end = Math.min(buf.length, end)
+
+ for (var i = start; i < end; ++i) {
+ ret += String.fromCharCode(buf[i])
+ }
+ return ret
+}
+
+function hexSlice (buf, start, end) {
+ var len = buf.length
+
+ if (!start || start < 0) start = 0
+ if (!end || end < 0 || end > len) end = len
+
+ var out = ''
+ for (var i = start; i < end; ++i) {
+ out += toHex(buf[i])
+ }
+ return out
+}
+
+function utf16leSlice (buf, start, end) {
+ var bytes = buf.slice(start, end)
+ var res = ''
+ for (var i = 0; i < bytes.length; i += 2) {
+ res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256))
+ }
+ return res
+}
+
+Buffer.prototype.slice = function slice (start, end) {
+ var len = this.length
+ start = ~~start
+ end = end === undefined ? len : ~~end
+
+ if (start < 0) {
+ start += len
+ if (start < 0) start = 0
+ } else if (start > len) {
+ start = len
+ }
+
+ if (end < 0) {
+ end += len
+ if (end < 0) end = 0
+ } else if (end > len) {
+ end = len
+ }
+
+ if (end < start) end = start
+
+ var newBuf = this.subarray(start, end)
+ // Return an augmented `Uint8Array` instance
+ newBuf.__proto__ = Buffer.prototype
+ return newBuf
+}
+
+/*
+ * Need to make sure that buffer isn't trying to write out of bounds.
+ */
+function checkOffset (offset, ext, length) {
+ if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
+ if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
+}
+
+Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
+ offset = offset >>> 0
+ byteLength = byteLength >>> 0
+ if (!noAssert) checkOffset(offset, byteLength, this.length)
+
+ var val = this[offset]
+ var mul = 1
+ var i = 0
+ while (++i < byteLength && (mul *= 0x100)) {
+ val += this[offset + i] * mul
+ }
+
+ return val
+}
+
+Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
+ offset = offset >>> 0
+ byteLength = byteLength >>> 0
+ if (!noAssert) {
+ checkOffset(offset, byteLength, this.length)
+ }
+
+ var val = this[offset + --byteLength]
+ var mul = 1
+ while (byteLength > 0 && (mul *= 0x100)) {
+ val += this[offset + --byteLength] * mul
+ }
+
+ return val
+}
+
+Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 1, this.length)
+ return this[offset]
+}
+
+Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 2, this.length)
+ return this[offset] | (this[offset + 1] << 8)
+}
+
+Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 2, this.length)
+ return (this[offset] << 8) | this[offset + 1]
+}
+
+Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 4, this.length)
+
+ return ((this[offset]) |
+ (this[offset + 1] << 8) |
+ (this[offset + 2] << 16)) +
+ (this[offset + 3] * 0x1000000)
+}
+
+Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 4, this.length)
+
+ return (this[offset] * 0x1000000) +
+ ((this[offset + 1] << 16) |
+ (this[offset + 2] << 8) |
+ this[offset + 3])
+}
+
+Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
+ offset = offset >>> 0
+ byteLength = byteLength >>> 0
+ if (!noAssert) checkOffset(offset, byteLength, this.length)
+
+ var val = this[offset]
+ var mul = 1
+ var i = 0
+ while (++i < byteLength && (mul *= 0x100)) {
+ val += this[offset + i] * mul
+ }
+ mul *= 0x80
+
+ if (val >= mul) val -= Math.pow(2, 8 * byteLength)
+
+ return val
+}
+
+Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
+ offset = offset >>> 0
+ byteLength = byteLength >>> 0
+ if (!noAssert) checkOffset(offset, byteLength, this.length)
+
+ var i = byteLength
+ var mul = 1
+ var val = this[offset + --i]
+ while (i > 0 && (mul *= 0x100)) {
+ val += this[offset + --i] * mul
+ }
+ mul *= 0x80
+
+ if (val >= mul) val -= Math.pow(2, 8 * byteLength)
+
+ return val
+}
+
+Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 1, this.length)
+ if (!(this[offset] & 0x80)) return (this[offset])
+ return ((0xff - this[offset] + 1) * -1)
+}
+
+Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 2, this.length)
+ var val = this[offset] | (this[offset + 1] << 8)
+ return (val & 0x8000) ? val | 0xFFFF0000 : val
+}
+
+Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 2, this.length)
+ var val = this[offset + 1] | (this[offset] << 8)
+ return (val & 0x8000) ? val | 0xFFFF0000 : val
+}
+
+Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 4, this.length)
+
+ return (this[offset]) |
+ (this[offset + 1] << 8) |
+ (this[offset + 2] << 16) |
+ (this[offset + 3] << 24)
+}
+
+Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 4, this.length)
+
+ return (this[offset] << 24) |
+ (this[offset + 1] << 16) |
+ (this[offset + 2] << 8) |
+ (this[offset + 3])
+}
+
+Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 4, this.length)
+ return ieee754.read(this, offset, true, 23, 4)
+}
+
+Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 4, this.length)
+ return ieee754.read(this, offset, false, 23, 4)
+}
+
+Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 8, this.length)
+ return ieee754.read(this, offset, true, 52, 8)
+}
+
+Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 8, this.length)
+ return ieee754.read(this, offset, false, 52, 8)
+}
+
+function checkInt (buf, value, offset, ext, max, min) {
+ if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance')
+ if (value > max || value < min) throw new RangeError('"value" argument is out of bounds')
+ if (offset + ext > buf.length) throw new RangeError('Index out of range')
+}
+
+Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ byteLength = byteLength >>> 0
+ if (!noAssert) {
+ var maxBytes = Math.pow(2, 8 * byteLength) - 1
+ checkInt(this, value, offset, byteLength, maxBytes, 0)
+ }
+
+ var mul = 1
+ var i = 0
+ this[offset] = value & 0xFF
+ while (++i < byteLength && (mul *= 0x100)) {
+ this[offset + i] = (value / mul) & 0xFF
+ }
+
+ return offset + byteLength
+}
+
+Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ byteLength = byteLength >>> 0
+ if (!noAssert) {
+ var maxBytes = Math.pow(2, 8 * byteLength) - 1
+ checkInt(this, value, offset, byteLength, maxBytes, 0)
+ }
+
+ var i = byteLength - 1
+ var mul = 1
+ this[offset + i] = value & 0xFF
+ while (--i >= 0 && (mul *= 0x100)) {
+ this[offset + i] = (value / mul) & 0xFF
+ }
+
+ return offset + byteLength
+}
+
+Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
+ this[offset] = (value & 0xff)
+ return offset + 1
+}
+
+Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
+ this[offset] = (value & 0xff)
+ this[offset + 1] = (value >>> 8)
+ return offset + 2
+}
+
+Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
+ this[offset] = (value >>> 8)
+ this[offset + 1] = (value & 0xff)
+ return offset + 2
+}
+
+Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
+ this[offset + 3] = (value >>> 24)
+ this[offset + 2] = (value >>> 16)
+ this[offset + 1] = (value >>> 8)
+ this[offset] = (value & 0xff)
+ return offset + 4
+}
+
+Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
+ this[offset] = (value >>> 24)
+ this[offset + 1] = (value >>> 16)
+ this[offset + 2] = (value >>> 8)
+ this[offset + 3] = (value & 0xff)
+ return offset + 4
+}
+
+Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) {
+ var limit = Math.pow(2, (8 * byteLength) - 1)
+
+ checkInt(this, value, offset, byteLength, limit - 1, -limit)
+ }
+
+ var i = 0
+ var mul = 1
+ var sub = 0
+ this[offset] = value & 0xFF
+ while (++i < byteLength && (mul *= 0x100)) {
+ if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {
+ sub = 1
+ }
+ this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
+ }
+
+ return offset + byteLength
+}
+
+Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) {
+ var limit = Math.pow(2, (8 * byteLength) - 1)
+
+ checkInt(this, value, offset, byteLength, limit - 1, -limit)
+ }
+
+ var i = byteLength - 1
+ var mul = 1
+ var sub = 0
+ this[offset + i] = value & 0xFF
+ while (--i >= 0 && (mul *= 0x100)) {
+ if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {
+ sub = 1
+ }
+ this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
+ }
+
+ return offset + byteLength
+}
+
+Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
+ if (value < 0) value = 0xff + value + 1
+ this[offset] = (value & 0xff)
+ return offset + 1
+}
+
+Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
+ this[offset] = (value & 0xff)
+ this[offset + 1] = (value >>> 8)
+ return offset + 2
+}
+
+Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
+ this[offset] = (value >>> 8)
+ this[offset + 1] = (value & 0xff)
+ return offset + 2
+}
+
+Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
+ this[offset] = (value & 0xff)
+ this[offset + 1] = (value >>> 8)
+ this[offset + 2] = (value >>> 16)
+ this[offset + 3] = (value >>> 24)
+ return offset + 4
+}
+
+Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
+ if (value < 0) value = 0xffffffff + value + 1
+ this[offset] = (value >>> 24)
+ this[offset + 1] = (value >>> 16)
+ this[offset + 2] = (value >>> 8)
+ this[offset + 3] = (value & 0xff)
+ return offset + 4
+}
+
+function checkIEEE754 (buf, value, offset, ext, max, min) {
+ if (offset + ext > buf.length) throw new RangeError('Index out of range')
+ if (offset < 0) throw new RangeError('Index out of range')
+}
+
+function writeFloat (buf, value, offset, littleEndian, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) {
+ checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
+ }
+ ieee754.write(buf, value, offset, littleEndian, 23, 4)
+ return offset + 4
+}
+
+Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
+ return writeFloat(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
+ return writeFloat(this, value, offset, false, noAssert)
+}
+
+function writeDouble (buf, value, offset, littleEndian, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) {
+ checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
+ }
+ ieee754.write(buf, value, offset, littleEndian, 52, 8)
+ return offset + 8
+}
+
+Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
+ return writeDouble(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
+ return writeDouble(this, value, offset, false, noAssert)
+}
+
+// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
+Buffer.prototype.copy = function copy (target, targetStart, start, end) {
+ if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer')
+ if (!start) start = 0
+ if (!end && end !== 0) end = this.length
+ if (targetStart >= target.length) targetStart = target.length
+ if (!targetStart) targetStart = 0
+ if (end > 0 && end < start) end = start
+
+ // Copy 0 bytes; we're done
+ if (end === start) return 0
+ if (target.length === 0 || this.length === 0) return 0
+
+ // Fatal error conditions
+ if (targetStart < 0) {
+ throw new RangeError('targetStart out of bounds')
+ }
+ if (start < 0 || start >= this.length) throw new RangeError('Index out of range')
+ if (end < 0) throw new RangeError('sourceEnd out of bounds')
+
+ // Are we oob?
+ if (end > this.length) end = this.length
+ if (target.length - targetStart < end - start) {
+ end = target.length - targetStart + start
+ }
+
+ var len = end - start
+
+ if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') {
+ // Use built-in when available, missing from IE11
+ this.copyWithin(targetStart, start, end)
+ } else if (this === target && start < targetStart && targetStart < end) {
+ // descending copy from end
+ for (var i = len - 1; i >= 0; --i) {
+ target[i + targetStart] = this[i + start]
+ }
+ } else {
+ Uint8Array.prototype.set.call(
+ target,
+ this.subarray(start, end),
+ targetStart
+ )
+ }
+
+ return len
+}
+
+// Usage:
+// buffer.fill(number[, offset[, end]])
+// buffer.fill(buffer[, offset[, end]])
+// buffer.fill(string[, offset[, end]][, encoding])
+Buffer.prototype.fill = function fill (val, start, end, encoding) {
+ // Handle string cases:
+ if (typeof val === 'string') {
+ if (typeof start === 'string') {
+ encoding = start
+ start = 0
+ end = this.length
+ } else if (typeof end === 'string') {
+ encoding = end
+ end = this.length
+ }
+ if (encoding !== undefined && typeof encoding !== 'string') {
+ throw new TypeError('encoding must be a string')
+ }
+ if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {
+ throw new TypeError('Unknown encoding: ' + encoding)
+ }
+ if (val.length === 1) {
+ var code = val.charCodeAt(0)
+ if ((encoding === 'utf8' && code < 128) ||
+ encoding === 'latin1') {
+ // Fast path: If `val` fits into a single byte, use that numeric value.
+ val = code
+ }
+ }
+ } else if (typeof val === 'number') {
+ val = val & 255
+ }
+
+ // Invalid ranges are not set to a default, so can range check early.
+ if (start < 0 || this.length < start || this.length < end) {
+ throw new RangeError('Out of range index')
+ }
+
+ if (end <= start) {
+ return this
+ }
+
+ start = start >>> 0
+ end = end === undefined ? this.length : end >>> 0
+
+ if (!val) val = 0
+
+ var i
+ if (typeof val === 'number') {
+ for (i = start; i < end; ++i) {
+ this[i] = val
+ }
+ } else {
+ var bytes = Buffer.isBuffer(val)
+ ? val
+ : Buffer.from(val, encoding)
+ var len = bytes.length
+ if (len === 0) {
+ throw new TypeError('The value "' + val +
+ '" is invalid for argument "value"')
+ }
+ for (i = 0; i < end - start; ++i) {
+ this[i + start] = bytes[i % len]
+ }
+ }
+
+ return this
+}
+
+// HELPER FUNCTIONS
+// ================
+
+var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g
+
+function base64clean (str) {
+ // Node takes equal signs as end of the Base64 encoding
+ str = str.split('=')[0]
+ // Node strips out invalid characters like \n and \t from the string, base64-js does not
+ str = str.trim().replace(INVALID_BASE64_RE, '')
+ // Node converts strings with length < 2 to ''
+ if (str.length < 2) return ''
+ // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
+ while (str.length % 4 !== 0) {
+ str = str + '='
+ }
+ return str
+}
+
+function toHex (n) {
+ if (n < 16) return '0' + n.toString(16)
+ return n.toString(16)
+}
+
+function utf8ToBytes (string, units) {
+ units = units || Infinity
+ var codePoint
+ var length = string.length
+ var leadSurrogate = null
+ var bytes = []
+
+ for (var i = 0; i < length; ++i) {
+ codePoint = string.charCodeAt(i)
+
+ // is surrogate component
+ if (codePoint > 0xD7FF && codePoint < 0xE000) {
+ // last char was a lead
+ if (!leadSurrogate) {
+ // no lead yet
+ if (codePoint > 0xDBFF) {
+ // unexpected trail
+ if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+ continue
+ } else if (i + 1 === length) {
+ // unpaired lead
+ if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+ continue
+ }
+
+ // valid lead
+ leadSurrogate = codePoint
+
+ continue
+ }
+
+ // 2 leads in a row
+ if (codePoint < 0xDC00) {
+ if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+ leadSurrogate = codePoint
+ continue
+ }
+
+ // valid surrogate pair
+ codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
+ } else if (leadSurrogate) {
+ // valid bmp char, but last char was a lead
+ if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+ }
+
+ leadSurrogate = null
+
+ // encode utf8
+ if (codePoint < 0x80) {
+ if ((units -= 1) < 0) break
+ bytes.push(codePoint)
+ } else if (codePoint < 0x800) {
+ if ((units -= 2) < 0) break
+ bytes.push(
+ codePoint >> 0x6 | 0xC0,
+ codePoint & 0x3F | 0x80
+ )
+ } else if (codePoint < 0x10000) {
+ if ((units -= 3) < 0) break
+ bytes.push(
+ codePoint >> 0xC | 0xE0,
+ codePoint >> 0x6 & 0x3F | 0x80,
+ codePoint & 0x3F | 0x80
+ )
+ } else if (codePoint < 0x110000) {
+ if ((units -= 4) < 0) break
+ bytes.push(
+ codePoint >> 0x12 | 0xF0,
+ codePoint >> 0xC & 0x3F | 0x80,
+ codePoint >> 0x6 & 0x3F | 0x80,
+ codePoint & 0x3F | 0x80
+ )
+ } else {
+ throw new Error('Invalid code point')
+ }
+ }
+
+ return bytes
+}
+
+function asciiToBytes (str) {
+ var byteArray = []
+ for (var i = 0; i < str.length; ++i) {
+ // Node's code seems to be doing this and not & 0x7F..
+ byteArray.push(str.charCodeAt(i) & 0xFF)
+ }
+ return byteArray
+}
+
+function utf16leToBytes (str, units) {
+ var c, hi, lo
+ var byteArray = []
+ for (var i = 0; i < str.length; ++i) {
+ if ((units -= 2) < 0) break
+
+ c = str.charCodeAt(i)
+ hi = c >> 8
+ lo = c % 256
+ byteArray.push(lo)
+ byteArray.push(hi)
+ }
+
+ return byteArray
+}
+
+function base64ToBytes (str) {
+ return base64.toByteArray(base64clean(str))
+}
+
+function blitBuffer (src, dst, offset, length) {
+ for (var i = 0; i < length; ++i) {
+ if ((i + offset >= dst.length) || (i >= src.length)) break
+ dst[i + offset] = src[i]
+ }
+ return i
+}
+
+// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass
+// the `instanceof` check but they should be treated as of that type.
+// See: https://github.com/feross/buffer/issues/166
+function isInstance (obj, type) {
+ return obj instanceof type ||
+ (obj != null && obj.constructor != null && obj.constructor.name != null &&
+ obj.constructor.name === type.name)
+}
+function numberIsNaN (obj) {
+ // For IE11 support
+ return obj !== obj // eslint-disable-line no-self-compare
+}
+
+},{"base64-js":2,"ieee754":8}],4:[function(require,module,exports){
+var charenc = {
+ // UTF-8 encoding
+ utf8: {
+ // Convert a string to a byte array
+ stringToBytes: function(str) {
+ return charenc.bin.stringToBytes(unescape(encodeURIComponent(str)));
+ },
+
+ // Convert a byte array to a string
+ bytesToString: function(bytes) {
+ return decodeURIComponent(escape(charenc.bin.bytesToString(bytes)));
+ }
+ },
+
+ // Binary encoding
+ bin: {
+ // Convert a string to a byte array
+ stringToBytes: function(str) {
+ for (var bytes = [], i = 0; i < str.length; i++)
+ bytes.push(str.charCodeAt(i) & 0xFF);
+ return bytes;
+ },
+
+ // Convert a byte array to a string
+ bytesToString: function(bytes) {
+ for (var str = [], i = 0; i < bytes.length; i++)
+ str.push(String.fromCharCode(bytes[i]));
+ return str.join('');
+ }
+ }
+};
+
+module.exports = charenc;
+
+},{}],5:[function(require,module,exports){
+/** Wrap an API that uses callbacks with Promises
+ * This expects the pattern function withCallback(arg1, arg2, ... argN, callback)
+ * @author Keith Henry <keith.henry@evolutionjobs.co.uk>
+ * @license MIT */
+(function () {
+ 'use strict';
+
+ /** Wrap a function with a callback with a Promise.
+ * @param {function} f The function to wrap, should be pattern: withCallback(arg1, arg2, ... argN, callback).
+ * @param {function} parseCB Optional function to parse multiple callback parameters into a single object.
+ * @returns {Promise} Promise that resolves when the callback fires. */
+ function promisify(f, parseCB) {
+ return (...args) => {
+ let safeArgs = args;
+ let callback;
+ // The Chrome API functions all use arguments, so we can't use f.length to check
+
+ // If there is a last arg
+ if (args && args.length > 0) {
+
+ // ... and the last arg is a function
+ const last = args[args.length - 1];
+ if (typeof last === 'function') {
+ // Trim the last callback arg if it's been passed
+ safeArgs = args.slice(0, args.length - 1);
+ callback = last;
+ }
+ }
+
+ // Return a promise
+ return new Promise((resolve, reject) => {
+ try {
+ // Try to run the original function, with the trimmed args list
+ f(...safeArgs, (...cbArgs) => {
+
+ // If a callback was passed at the end of the original arguments
+ if (callback) {
+ // Don't allow a bug in the callback to stop the promise resolving
+ try { callback(...cbArgs); }
+ catch (cbErr) { reject(cbErr); }
+ }
+
+ // Chrome extensions always fire the callback, but populate chrome.runtime.lastError with exception details
+ if (chrome.runtime.lastError)
+ // Return as an error for the awaited catch block
+ reject(new Error(chrome.runtime.lastError.message || `Error thrown by API ${chrome.runtime.lastError}`));
+ else {
+ if (parseCB) {
+ const cbObj = parseCB(...cbArgs);
+ resolve(cbObj);
+ }
+ else if (!cbArgs || cbArgs.length === 0)
+ resolve();
+ else if (cbArgs.length === 1)
+ resolve(cbArgs[0]);
+ else
+ resolve(cbArgs);
+ }
+ });
+ }
+ catch (err) { reject(err); }
+ });
+ }
+ }
+
+ /** Promisify all the known functions in the map
+ * @param {object} api The Chrome native API to extend
+ * @param {Array} apiMap Collection of sub-API and functions to promisify */
+ function applyMap(api, apiMap) {
+ if (!api)
+ // Not supported by current permissions
+ return;
+
+ for (let funcDef of apiMap) {
+ let funcName;
+ if (typeof funcDef === 'string')
+ funcName = funcDef;
+ else {
+ funcName = funcDef.n;
+ }
+
+ if (!api.hasOwnProperty(funcName))
+ // Member not in API
+ continue;
+
+ const m = api[funcName];
+ if (typeof m === 'function')
+ // This is a function, wrap in a promise
+ api[funcName] = promisify(m.bind(api), funcDef.cb);
+ else
+ // Sub-API, recurse this func with the mapped props
+ applyMap(m, funcDef.props);
+ }
+ }
+
+ /** Apply promise-maps to the Chrome native API.
+ * @param {object} apiMaps The API to apply. */
+ function applyMaps(apiMaps) {
+ for (let apiName in apiMaps) {
+ const callbackApi = chrome[apiName];
+ if (!callbackApi)
+ // Not supported by current permissions
+ continue;
+
+ const apiMap = apiMaps[apiName];
+ applyMap(callbackApi, apiMap);
+ }
+ }
+
+ // accessibilityFeatures https://developer.chrome.com/extensions/accessibilityFeatures
+ const knownA11ySetting = ['get', 'set', 'clear'];
+
+ // ContentSetting https://developer.chrome.com/extensions/contentSettings#type-ContentSetting
+ const knownInContentSetting = ['clear', 'get', 'set', 'getResourceIdentifiers'];
+
+ // StorageArea https://developer.chrome.com/extensions/storage#type-StorageArea
+ const knownInStorageArea = ['get', 'getBytesInUse', 'set', 'remove', 'clear'];
+
+ /** Map of API functions that follow the callback pattern that we can 'promisify' */
+ applyMaps({
+ accessibilityFeatures: [ // Todo: this should extend AccessibilityFeaturesSetting.prototype instead
+ { n: 'spokenFeedback', props: knownA11ySetting },
+ { n: 'largeCursor', props: knownA11ySetting },
+ { n: 'stickyKeys', props: knownA11ySetting },
+ { n: 'highContrast', props: knownA11ySetting },
+ { n: 'screenMagnifier', props: knownA11ySetting },
+ { n: 'autoclick', props: knownA11ySetting },
+ { n: 'virtualKeyboard', props: knownA11ySetting },
+ { n: 'animationPolicy', props: knownA11ySetting }],
+ alarms: ['get', 'getAll', 'clear', 'clearAll'],
+ bookmarks: [
+ 'get', 'getChildren', 'getRecent', 'getTree', 'getSubTree',
+ 'search', 'create', 'move', 'update', 'remove', 'removeTree'],
+ browser: ['openTab'],
+ browserAction: [
+ 'getTitle', 'setIcon', 'getPopup', 'getBadgeText', 'getBadgeBackgroundColor'],
+ browsingData: [
+ 'settings', 'remove', 'removeAppcache', 'removeCache',
+ 'removeCookies', 'removeDownloads', 'removeFileSystems',
+ 'removeFormData', 'removeHistory', 'removeIndexedDB',
+ 'removeLocalStorage', 'removePluginData', 'removePasswords',
+ 'removeWebSQL'],
+ commands: ['getAll'],
+ contentSettings: [ // Todo: this should extend ContentSetting.prototype instead
+ { n: 'cookies', props: knownInContentSetting },
+ { n: 'images', props: knownInContentSetting },
+ { n: 'javascript', props: knownInContentSetting },
+ { n: 'location', props: knownInContentSetting },
+ { n: 'plugins', props: knownInContentSetting },
+ { n: 'popups', props: knownInContentSetting },
+ { n: 'notifications', props: knownInContentSetting },
+ { n: 'fullscreen', props: knownInContentSetting },
+ { n: 'mouselock', props: knownInContentSetting },
+ { n: 'microphone', props: knownInContentSetting },
+ { n: 'camera', props: knownInContentSetting },
+ { n: 'unsandboxedPlugins', props: knownInContentSetting },
+ { n: 'automaticDownloads', props: knownInContentSetting }],
+ contextMenus: ['create', 'update', 'remove', 'removeAll'],
+ cookies: ['get', 'getAll', 'set', 'remove', 'getAllCookieStores'],
+ debugger: ['attach', 'detach', 'sendCommand', 'getTargets'],
+ desktopCapture: ['chooseDesktopMedia'],
+ // TODO: devtools.*
+ documentScan: ['scan'],
+ downloads: [
+ 'download', 'search', 'pause', 'resume', 'cancel',
+ 'getFileIcon', 'erase', 'removeFile', 'acceptDanger'],
+ enterprise: [{ n: 'platformKeys', props: ['getToken', 'getCertificates', 'importCertificate', 'removeCertificate'] }],
+ extension: ['isAllowedIncognitoAccess', 'isAllowedFileSchemeAccess'], // mostly deprecated in favour of runtime
+ fileBrowserHandler: ['selectFile'],
+ fileSystemProvider: ['mount', 'unmount', 'getAll', 'get', 'notify'],
+ fontSettings: [
+ 'setDefaultFontSize', 'getFont', 'getDefaultFontSize', 'getMinimumFontSize',
+ 'setMinimumFontSize', 'getDefaultFixedFontSize', 'clearDefaultFontSize',
+ 'setDefaultFixedFontSize', 'clearFont', 'setFont', 'clearMinimumFontSize',
+ 'getFontList', 'clearDefaultFixedFontSize'],
+ gcm: ['register', 'unregister', 'send'],
+ history: ['search', 'getVisits', 'addUrl', 'deleteUrl', 'deleteRange', 'deleteAll'],
+ i18n: ['getAcceptLanguages', 'detectLanguage'],
+ identity: [
+ 'getAuthToken', 'getProfileUserInfo', 'removeCachedAuthToken', 'launchWebAuthFlow'],
+ idle: ['queryState'],
+ input: [{
+ n: 'ime', props: [
+ 'setMenuItems', 'commitText', 'setCandidates', 'setComposition', 'updateMenuItems',
+ 'setCandidateWindowProperties', 'clearComposition', 'setCursorPosition', 'sendKeyEvents',
+ 'deleteSurroundingText']
+ }],
+ management: [
+ 'setEnabled', 'getPermissionWarningsById', 'get', 'getAll',
+ 'getPermissionWarningsByManifest', 'launchApp', 'uninstall', 'getSelf',
+ 'uninstallSelf', 'createAppShortcut', 'setLaunchType', 'generateAppForLink'],
+ networking: [{ n: 'config', props: ['setNetworkFilter', 'finishAuthentication'] }],
+ notifications: ['create', 'update', 'clear', 'getAll', 'getPermissionLevel'],
+ pageAction: ['getTitle', 'setIcon', 'getPopup'],
+ pageCapture: ['saveAsMHTML'],
+ permissions: ['getAll', 'contains', 'request', 'remove'],
+ platformKeys: ['selectClientCertificates', 'verifyTLSServerCertificate',
+ { n: "getKeyPair", cb: (publicKey, privateKey) => { return { publicKey, privateKey }; } }],
+ runtime: [
+ 'getBackgroundPage', 'openOptionsPage', 'setUninstallURL',
+ 'restartAfterDelay', 'sendMessage',
+ 'sendNativeMessage', 'getPlatformInfo', 'getPackageDirectoryEntry',
+ { n: "requestUpdateCheck", cb: (status, details) => { return { status, details }; } }],
+ scriptBadge: ['getPopup'],
+ sessions: ['getRecentlyClosed', 'getDevices', 'restore'],
+ storage: [ // Todo: this should extend StorageArea.prototype instead
+ { n: 'sync', props: knownInStorageArea },
+ { n: 'local', props: knownInStorageArea },
+ { n: 'managed', props: knownInStorageArea }],
+ socket: [
+ 'create', 'connect', 'bind', 'read', 'write', 'recvFrom', 'sendTo',
+ 'listen', 'accept', 'setKeepAlive', 'setNoDelay', 'getInfo', 'getNetworkList'],
+ sockets: [
+ { n: 'tcp', props: [
+ 'create','update','setPaused','setKeepAlive','setNoDelay','connect',
+ 'disconnect','secure','send','close','getInfo','getSockets'] },
+ { n: 'tcpServer', props: [
+ 'create','update','setPaused','listen','disconnect','close','getInfo','getSockets'] },
+ { n: 'udp', props: [
+ 'create','update','setPaused','bind','send','close','getInfo',
+ 'getSockets','joinGroup','leaveGroup','setMulticastTimeToLive',
+ 'setMulticastLoopbackMode','getJoinedGroups','setBroadcast'] }],
+ system: [
+ { n: 'cpu', props: ['getInfo'] },
+ { n: 'memory', props: ['getInfo'] },
+ { n: 'storage', props: ['getInfo', 'ejectDevice', 'getAvailableCapacity'] }],
+ tabCapture: ['capture', 'getCapturedTabs'],
+ tabs: [
+ 'get', 'getCurrent', 'sendMessage', 'create', 'duplicate',
+ 'query', 'highlight', 'update', 'move', 'reload', 'remove',
+ 'detectLanguage', 'captureVisibleTab', 'executeScript',
+ 'insertCSS', 'setZoom', 'getZoom', 'setZoomSettings',
+ 'getZoomSettings', 'discard'],
+ topSites: ['get'],
+ tts: ['isSpeaking', 'getVoices', 'speak'],
+ types: ['set', 'get', 'clear'],
+ vpnProvider: ['createConfig', 'destroyConfig', 'setParameters', 'sendPacket', 'notifyConnectionStateChanged'],
+ wallpaper: ['setWallpaper'],
+ webNavigation: ['getFrame', 'getAllFrames', 'handlerBehaviorChanged'],
+ windows: ['get', 'getCurrent', 'getLastFocused', 'getAll', 'create', 'update', 'remove']
+ });
+})();
+
+},{}],6:[function(require,module,exports){
+(function() {
+ var base64map
+ = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
+
+ crypt = {
+ // Bit-wise rotation left
+ rotl: function(n, b) {
+ return (n << b) | (n >>> (32 - b));
+ },
+
+ // Bit-wise rotation right
+ rotr: function(n, b) {
+ return (n << (32 - b)) | (n >>> b);
+ },
+
+ // Swap big-endian to little-endian and vice versa
+ endian: function(n) {
+ // If number given, swap endian
+ if (n.constructor == Number) {
+ return crypt.rotl(n, 8) & 0x00FF00FF | crypt.rotl(n, 24) & 0xFF00FF00;
+ }
+
+ // Else, assume array and swap all items
+ for (var i = 0; i < n.length; i++)
+ n[i] = crypt.endian(n[i]);
+ return n;
+ },
+
+ // Generate an array of any length of random bytes
+ randomBytes: function(n) {
+ for (var bytes = []; n > 0; n--)
+ bytes.push(Math.floor(Math.random() * 256));
+ return bytes;
+ },
+
+ // Convert a byte array to big-endian 32-bit words
+ bytesToWords: function(bytes) {
+ for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8)
+ words[b >>> 5] |= bytes[i] << (24 - b % 32);
+ return words;
+ },
+
+ // Convert big-endian 32-bit words to a byte array
+ wordsToBytes: function(words) {
+ for (var bytes = [], b = 0; b < words.length * 32; b += 8)
+ bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);
+ return bytes;
+ },
+
+ // Convert a byte array to a hex string
+ bytesToHex: function(bytes) {
+ for (var hex = [], i = 0; i < bytes.length; i++) {
+ hex.push((bytes[i] >>> 4).toString(16));
+ hex.push((bytes[i] & 0xF).toString(16));
+ }
+ return hex.join('');
+ },
+
+ // Convert a hex string to a byte array
+ hexToBytes: function(hex) {
+ for (var bytes = [], c = 0; c < hex.length; c += 2)
+ bytes.push(parseInt(hex.substr(c, 2), 16));
+ return bytes;
+ },
+
+ // Convert a byte array to a base-64 string
+ bytesToBase64: function(bytes) {
+ for (var base64 = [], i = 0; i < bytes.length; i += 3) {
+ var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
+ for (var j = 0; j < 4; j++)
+ if (i * 8 + j * 6 <= bytes.length * 8)
+ base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F));
+ else
+ base64.push('=');
+ }
+ return base64.join('');
+ },
+
+ // Convert a base-64 string to a byte array
+ base64ToBytes: function(base64) {
+ // Remove non-base-64 characters
+ base64 = base64.replace(/[^A-Z0-9+\/]/ig, '');
+
+ for (var bytes = [], i = 0, imod4 = 0; i < base64.length;
+ imod4 = ++i % 4) {
+ if (imod4 == 0) continue;
+ bytes.push(((base64map.indexOf(base64.charAt(i - 1))
+ & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2))
+ | (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2)));
+ }
+ return bytes;
+ }
+ };
+
+ module.exports = crypt;
+})();
+
+},{}],7:[function(require,module,exports){
+(function (setImmediate){
+/*
+WHAT: SublimeText-like Fuzzy Search
+
+USAGE:
+ fuzzysort.single('fs', 'Fuzzy Search') // {score: -16}
+ fuzzysort.single('test', 'test') // {score: 0}
+ fuzzysort.single('doesnt exist', 'target') // null
+
+ fuzzysort.go('mr', ['Monitor.cpp', 'MeshRenderer.cpp'])
+ // [{score: -18, target: "MeshRenderer.cpp"}, {score: -6009, target: "Monitor.cpp"}]
+
+ fuzzysort.highlight(fuzzysort.single('fs', 'Fuzzy Search'), '<b>', '</b>')
+ // <b>F</b>uzzy <b>S</b>earch
+*/
+
+// UMD (Universal Module Definition) for fuzzysort
+;(function(root, UMD) {
+ if(typeof define === 'function' && define.amd) define([], UMD)
+ else if(typeof module === 'object' && module.exports) module.exports = UMD()
+ else root.fuzzysort = UMD()
+})(this, function UMD() { function fuzzysortNew(instanceOptions) {
+
+ var fuzzysort = {
+
+ single: function(search, target, options) {
+ if(!search) return null
+ if(!isObj(search)) search = fuzzysort.getPreparedSearch(search)
+
+ if(!target) return null
+ if(!isObj(target)) target = fuzzysort.getPrepared(target)
+
+ var allowTypo = options && options.allowTypo!==undefined ? options.allowTypo
+ : instanceOptions && instanceOptions.allowTypo!==undefined ? instanceOptions.allowTypo
+ : true
+ var algorithm = allowTypo ? fuzzysort.algorithm : fuzzysort.algorithmNoTypo
+ return algorithm(search, target, search[0])
+ // var threshold = options && options.threshold || instanceOptions && instanceOptions.threshold || -9007199254740991
+ // var result = algorithm(search, target, search[0])
+ // if(result === null) return null
+ // if(result.score < threshold) return null
+ // return result
+ },
+
+ go: function(search, targets, options) {
+ if(!search) return noResults
+ search = fuzzysort.prepareSearch(search)
+ var searchLowerCode = search[0]
+
+ var threshold = options && options.threshold || instanceOptions && instanceOptions.threshold || -9007199254740991
+ var limit = options && options.limit || instanceOptions && instanceOptions.limit || 9007199254740991
+ var allowTypo = options && options.allowTypo!==undefined ? options.allowTypo
+ : instanceOptions && instanceOptions.allowTypo!==undefined ? instanceOptions.allowTypo
+ : true
+ var algorithm = allowTypo ? fuzzysort.algorithm : fuzzysort.algorithmNoTypo
+ var resultsLen = 0; var limitedCount = 0
+ var targetsLen = targets.length
+
+ // This code is copy/pasted 3 times for performance reasons [options.keys, options.key, no keys]
+
+ // options.keys
+ if(options && options.keys) {
+ var scoreFn = options.scoreFn || defaultScoreFn
+ var keys = options.keys
+ var keysLen = keys.length
+ for(var i = targetsLen - 1; i >= 0; --i) { var obj = targets[i]
+ var objResults = new Array(keysLen)
+ for (var keyI = keysLen - 1; keyI >= 0; --keyI) {
+ var key = keys[keyI]
+ var target = getValue(obj, key)
+ if(!target) { objResults[keyI] = null; continue }
+ if(!isObj(target)) target = fuzzysort.getPrepared(target)
+
+ objResults[keyI] = algorithm(search, target, searchLowerCode)
+ }
+ objResults.obj = obj // before scoreFn so scoreFn can use it
+ var score = scoreFn(objResults)
+ if(score === null) continue
+ if(score < threshold) continue
+ objResults.score = score
+ if(resultsLen < limit) { q.add(objResults); ++resultsLen }
+ else {
+ ++limitedCount
+ if(score > q.peek().score) q.replaceTop(objResults)
+ }
+ }
+
+ // options.key
+ } else if(options && options.key) {
+ var key = options.key
+ for(var i = targetsLen - 1; i >= 0; --i) { var obj = targets[i]
+ var target = getValue(obj, key)
+ if(!target) continue
+ if(!isObj(target)) target = fuzzysort.getPrepared(target)
+
+ var result = algorithm(search, target, searchLowerCode)
+ if(result === null) continue
+ if(result.score < threshold) continue
+
+ // have to clone result so duplicate targets from different obj can each reference the correct obj
+ result = {target:result.target, _targetLowerCodes:null, _nextBeginningIndexes:null, score:result.score, indexes:result.indexes, obj:obj} // hidden
+
+ if(resultsLen < limit) { q.add(result); ++resultsLen }
+ else {
+ ++limitedCount
+ if(result.score > q.peek().score) q.replaceTop(result)
+ }
+ }
+
+ // no keys
+ } else {
+ for(var i = targetsLen - 1; i >= 0; --i) { var target = targets[i]
+ if(!target) continue
+ if(!isObj(target)) target = fuzzysort.getPrepared(target)
+
+ var result = algorithm(search, target, searchLowerCode)
+ if(result === null) continue
+ if(result.score < threshold) continue
+ if(resultsLen < limit) { q.add(result); ++resultsLen }
+ else {
+ ++limitedCount
+ if(result.score > q.peek().score) q.replaceTop(result)
+ }
+ }
+ }
+
+ if(resultsLen === 0) return noResults
+ var results = new Array(resultsLen)
+ for(var i = resultsLen - 1; i >= 0; --i) results[i] = q.poll()
+ results.total = resultsLen + limitedCount
+ return results
+ },
+
+ goAsync: function(search, targets, options) {
+ var canceled = false
+ var p = new Promise(function(resolve, reject) {
+ if(!search) return resolve(noResults)
+ search = fuzzysort.prepareSearch(search)
+ var searchLowerCode = search[0]
+
+ var q = fastpriorityqueue()
+ var iCurrent = targets.length - 1
+ var threshold = options && options.threshold || instanceOptions && instanceOptions.threshold || -9007199254740991
+ var limit = options && options.limit || instanceOptions && instanceOptions.limit || 9007199254740991
+ var allowTypo = options && options.allowTypo!==undefined ? options.allowTypo
+ : instanceOptions && instanceOptions.allowTypo!==undefined ? instanceOptions.allowTypo
+ : true
+ var algorithm = allowTypo ? fuzzysort.algorithm : fuzzysort.algorithmNoTypo
+ var resultsLen = 0; var limitedCount = 0
+ function step() {
+ if(canceled) return reject('canceled')
+
+ var startMs = Date.now()
+
+ // This code is copy/pasted 3 times for performance reasons [options.keys, options.key, no keys]
+
+ // options.keys
+ if(options && options.keys) {
+ var scoreFn = options.scoreFn || defaultScoreFn
+ var keys = options.keys
+ var keysLen = keys.length
+ for(; iCurrent >= 0; --iCurrent) { var obj = targets[iCurrent]
+ var objResults = new Array(keysLen)
+ for (var keyI = keysLen - 1; keyI >= 0; --keyI) {
+ var key = keys[keyI]
+ var target = getValue(obj, key)
+ if(!target) { objResults[keyI] = null; continue }
+ if(!isObj(target)) target = fuzzysort.getPrepared(target)
+
+ objResults[keyI] = algorithm(search, target, searchLowerCode)
+ }
+ objResults.obj = obj // before scoreFn so scoreFn can use it
+ var score = scoreFn(objResults)
+ if(score === null) continue
+ if(score < threshold) continue
+ objResults.score = score
+ if(resultsLen < limit) { q.add(objResults); ++resultsLen }
+ else {
+ ++limitedCount
+ if(score > q.peek().score) q.replaceTop(objResults)
+ }
+
+ if(iCurrent%1000/*itemsPerCheck*/ === 0) {
+ if(Date.now() - startMs >= 10/*asyncInterval*/) {
+ isNode?setImmediate(step):setTimeout(step)
+ return
+ }
+ }
+ }
+
+ // options.key
+ } else if(options && options.key) {
+ var key = options.key
+ for(; iCurrent >= 0; --iCurrent) { var obj = targets[iCurrent]
+ var target = getValue(obj, key)
+ if(!target) continue
+ if(!isObj(target)) target = fuzzysort.getPrepared(target)
+
+ var result = algorithm(search, target, searchLowerCode)
+ if(result === null) continue
+ if(result.score < threshold) continue
+
+ // have to clone result so duplicate targets from different obj can each reference the correct obj
+ result = {target:result.target, _targetLowerCodes:null, _nextBeginningIndexes:null, score:result.score, indexes:result.indexes, obj:obj} // hidden
+
+ if(resultsLen < limit) { q.add(result); ++resultsLen }
+ else {
+ ++limitedCount
+ if(result.score > q.peek().score) q.replaceTop(result)
+ }
+
+ if(iCurrent%1000/*itemsPerCheck*/ === 0) {
+ if(Date.now() - startMs >= 10/*asyncInterval*/) {
+ isNode?setImmediate(step):setTimeout(step)
+ return
+ }
+ }
+ }
+
+ // no keys
+ } else {
+ for(; iCurrent >= 0; --iCurrent) { var target = targets[iCurrent]
+ if(!target) continue
+ if(!isObj(target)) target = fuzzysort.getPrepared(target)
+
+ var result = algorithm(search, target, searchLowerCode)
+ if(result === null) continue
+ if(result.score < threshold) continue
+ if(resultsLen < limit) { q.add(result); ++resultsLen }
+ else {
+ ++limitedCount
+ if(result.score > q.peek().score) q.replaceTop(result)
+ }
+
+ if(iCurrent%1000/*itemsPerCheck*/ === 0) {
+ if(Date.now() - startMs >= 10/*asyncInterval*/) {
+ isNode?setImmediate(step):setTimeout(step)
+ return
+ }
+ }
+ }
+ }
+
+ if(resultsLen === 0) return resolve(noResults)
+ var results = new Array(resultsLen)
+ for(var i = resultsLen - 1; i >= 0; --i) results[i] = q.poll()
+ results.total = resultsLen + limitedCount
+ resolve(results)
+ }
+
+ isNode?setImmediate(step):step()
+ })
+ p.cancel = function() { canceled = true }
+ return p
+ },
+
+ highlight: function(result, hOpen, hClose) {
+ if(result === null) return null
+ if(hOpen === undefined) hOpen = '<b>'
+ if(hClose === undefined) hClose = '</b>'
+ var highlighted = ''
+ var matchesIndex = 0
+ var opened = false
+ var target = result.target
+ var targetLen = target.length
+ var matchesBest = result.indexes
+ for(var i = 0; i < targetLen; ++i) { var char = target[i]
+ if(matchesBest[matchesIndex] === i) {
+ ++matchesIndex
+ if(!opened) { opened = true
+ highlighted += hOpen
+ }
+
+ if(matchesIndex === matchesBest.length) {
+ highlighted += char + hClose + target.substr(i+1)
+ break
+ }
+ } else {
+ if(opened) { opened = false
+ highlighted += hClose
+ }
+ }
+ highlighted += char
+ }
+
+ return highlighted
+ },
+
+ prepare: function(target) {
+ if(!target) return
+ return {target:target, _targetLowerCodes:fuzzysort.prepareLowerCodes(target), _nextBeginningIndexes:null, score:null, indexes:null, obj:null} // hidden
+ },
+ prepareSlow: function(target) {
+ if(!target) return
+ return {target:target, _targetLowerCodes:fuzzysort.prepareLowerCodes(target), _nextBeginningIndexes:fuzzysort.prepareNextBeginningIndexes(target), score:null, indexes:null, obj:null} // hidden
+ },
+ prepareSearch: function(search) {
+ if(!search) return
+ return fuzzysort.prepareLowerCodes(search)
+ },
+
+
+
+ // Below this point is only internal code
+ // Below this point is only internal code
+ // Below this point is only internal code
+ // Below this point is only internal code
+
+
+
+ getPrepared: function(target) {
+ if(target.length > 999) return fuzzysort.prepare(target) // don't cache huge targets
+ var targetPrepared = preparedCache.get(target)
+ if(targetPrepared !== undefined) return targetPrepared
+ targetPrepared = fuzzysort.prepare(target)
+ preparedCache.set(target, targetPrepared)
+ return targetPrepared
+ },
+ getPreparedSearch: function(search) {
+ if(search.length > 999) return fuzzysort.prepareSearch(search) // don't cache huge searches
+ var searchPrepared = preparedSearchCache.get(search)
+ if(searchPrepared !== undefined) return searchPrepared
+ searchPrepared = fuzzysort.prepareSearch(search)
+ preparedSearchCache.set(search, searchPrepared)
+ return searchPrepared
+ },
+
+ algorithm: function(searchLowerCodes, prepared, searchLowerCode) {
+ var targetLowerCodes = prepared._targetLowerCodes
+ var searchLen = searchLowerCodes.length
+ var targetLen = targetLowerCodes.length
+ var searchI = 0 // where we at
+ var targetI = 0 // where you at
+ var typoSimpleI = 0
+ var matchesSimpleLen = 0
+
+ // very basic fuzzy match; to remove non-matching targets ASAP!
+ // walk through target. find sequential matches.
+ // if all chars aren't found then exit
+ for(;;) {
+ var isMatch = searchLowerCode === targetLowerCodes[targetI]
+ if(isMatch) {
+ matchesSimple[matchesSimpleLen++] = targetI
+ ++searchI; if(searchI === searchLen) break
+ searchLowerCode = searchLowerCodes[typoSimpleI===0?searchI : (typoSimpleI===searchI?searchI+1 : (typoSimpleI===searchI-1?searchI-1 : searchI))]
+ }
+
+ ++targetI; if(targetI >= targetLen) { // Failed to find searchI
+ // Check for typo or exit
+ // we go as far as possible before trying to transpose
+ // then we transpose backwards until we reach the beginning
+ for(;;) {
+ if(searchI <= 1) return null // not allowed to transpose first char
+ if(typoSimpleI === 0) { // we haven't tried to transpose yet
+ --searchI
+ var searchLowerCodeNew = searchLowerCodes[searchI]
+ if(searchLowerCode === searchLowerCodeNew) continue // doesn't make sense to transpose a repeat char
+ typoSimpleI = searchI
+ } else {
+ if(typoSimpleI === 1) return null // reached the end of the line for transposing
+ --typoSimpleI
+ searchI = typoSimpleI
+ searchLowerCode = searchLowerCodes[searchI + 1]
+ var searchLowerCodeNew = searchLowerCodes[searchI]
+ if(searchLowerCode === searchLowerCodeNew) continue // doesn't make sense to transpose a repeat char
+ }
+ matchesSimpleLen = searchI
+ targetI = matchesSimple[matchesSimpleLen - 1] + 1
+ break
+ }
+ }
+ }
+
+ var searchI = 0
+ var typoStrictI = 0
+ var successStrict = false
+ var matchesStrictLen = 0
+
+ var nextBeginningIndexes = prepared._nextBeginningIndexes
+ if(nextBeginningIndexes === null) nextBeginningIndexes = prepared._nextBeginningIndexes = fuzzysort.prepareNextBeginningIndexes(prepared.target)
+ var firstPossibleI = targetI = matchesSimple[0]===0 ? 0 : nextBeginningIndexes[matchesSimple[0]-1]
+
+ // Our target string successfully matched all characters in sequence!
+ // Let's try a more advanced and strict test to improve the score
+ // only count it as a match if it's consecutive or a beginning character!
+ if(targetI !== targetLen) for(;;) {
+ if(targetI >= targetLen) {
+ // We failed to find a good spot for this search char, go back to the previous search char and force it forward
+ if(searchI <= 0) { // We failed to push chars forward for a better match
+ // transpose, starting from the beginning
+ ++typoStrictI; if(typoStrictI > searchLen-2) break
+ if(searchLowerCodes[typoStrictI] === searchLowerCodes[typoStrictI+1]) continue // doesn't make sense to transpose a repeat char
+ targetI = firstPossibleI
+ continue
+ }
+
+ --searchI
+ var lastMatch = matchesStrict[--matchesStrictLen]
+ targetI = nextBeginningIndexes[lastMatch]
+
+ } else {
+ var isMatch = searchLowerCodes[typoStrictI===0?searchI : (typoStrictI===searchI?searchI+1 : (typoStrictI===searchI-1?searchI-1 : searchI))] === targetLowerCodes[targetI]
+ if(isMatch) {
+ matchesStrict[matchesStrictLen++] = targetI
+ ++searchI; if(searchI === searchLen) { successStrict = true; break }
+ ++targetI
+ } else {
+ targetI = nextBeginningIndexes[targetI]
+ }
+ }
+ }
+
+ { // tally up the score & keep track of matches for highlighting later
+ if(successStrict) { var matchesBest = matchesStrict; var matchesBestLen = matchesStrictLen }
+ else { var matchesBest = matchesSimple; var matchesBestLen = matchesSimpleLen }
+ var score = 0
+ var lastTargetI = -1
+ for(var i = 0; i < searchLen; ++i) { var targetI = matchesBest[i]
+ // score only goes down if they're not consecutive
+ if(lastTargetI !== targetI - 1) score -= targetI
+ lastTargetI = targetI
+ }
+ if(!successStrict) {
+ score *= 1000
+ if(typoSimpleI !== 0) score += -20/*typoPenalty*/
+ } else {
+ if(typoStrictI !== 0) score += -20/*typoPenalty*/
+ }
+ score -= targetLen - searchLen
+ prepared.score = score
+ prepared.indexes = new Array(matchesBestLen); for(var i = matchesBestLen - 1; i >= 0; --i) prepared.indexes[i] = matchesBest[i]
+
+ return prepared
+ }
+ },
+
+ algorithmNoTypo: function(searchLowerCodes, prepared, searchLowerCode) {
+ var targetLowerCodes = prepared._targetLowerCodes
+ var searchLen = searchLowerCodes.length
+ var targetLen = targetLowerCodes.length
+ var searchI = 0 // where we at
+ var targetI = 0 // where you at
+ var matchesSimpleLen = 0
+
+ // very basic fuzzy match; to remove non-matching targets ASAP!
+ // walk through target. find sequential matches.
+ // if all chars aren't found then exit
+ for(;;) {
+ var isMatch = searchLowerCode === targetLowerCodes[targetI]
+ if(isMatch) {
+ matchesSimple[matchesSimpleLen++] = targetI
+ ++searchI; if(searchI === searchLen) break
+ searchLowerCode = searchLowerCodes[searchI]
+ }
+ ++targetI; if(targetI >= targetLen) return null // Failed to find searchI
+ }
+
+ var searchI = 0
+ var successStrict = false
+ var matchesStrictLen = 0
+
+ var nextBeginningIndexes = prepared._nextBeginningIndexes
+ if(nextBeginningIndexes === null) nextBeginningIndexes = prepared._nextBeginningIndexes = fuzzysort.prepareNextBeginningIndexes(prepared.target)
+ var firstPossibleI = targetI = matchesSimple[0]===0 ? 0 : nextBeginningIndexes[matchesSimple[0]-1]
+
+ // Our target string successfully matched all characters in sequence!
+ // Let's try a more advanced and strict test to improve the score
+ // only count it as a match if it's consecutive or a beginning character!
+ if(targetI !== targetLen) for(;;) {
+ if(targetI >= targetLen) {
+ // We failed to find a good spot for this search char, go back to the previous search char and force it forward
+ if(searchI <= 0) break // We failed to push chars forward for a better match
+
+ --searchI
+ var lastMatch = matchesStrict[--matchesStrictLen]
+ targetI = nextBeginningIndexes[lastMatch]
+
+ } else {
+ var isMatch = searchLowerCodes[searchI] === targetLowerCodes[targetI]
+ if(isMatch) {
+ matchesStrict[matchesStrictLen++] = targetI
+ ++searchI; if(searchI === searchLen) { successStrict = true; break }
+ ++targetI
+ } else {
+ targetI = nextBeginningIndexes[targetI]
+ }
+ }
+ }
+
+ { // tally up the score & keep track of matches for highlighting later
+ if(successStrict) { var matchesBest = matchesStrict; var matchesBestLen = matchesStrictLen }
+ else { var matchesBest = matchesSimple; var matchesBestLen = matchesSimpleLen }
+ var score = 0
+ var lastTargetI = -1
+ for(var i = 0; i < searchLen; ++i) { var targetI = matchesBest[i]
+ // score only goes down if they're not consecutive
+ if(lastTargetI !== targetI - 1) score -= targetI
+ lastTargetI = targetI
+ }
+ if(!successStrict) score *= 1000
+ score -= targetLen - searchLen
+ prepared.score = score
+ prepared.indexes = new Array(matchesBestLen); for(var i = matchesBestLen - 1; i >= 0; --i) prepared.indexes[i] = matchesBest[i]
+
+ return prepared
+ }
+ },
+
+ prepareLowerCodes: function(str) {
+ var strLen = str.length
+ var lowerCodes = [] // new Array(strLen) sparse array is too slow
+ var lower = str.toLowerCase()
+ for(var i = 0; i < strLen; ++i) lowerCodes[i] = lower.charCodeAt(i)
+ return lowerCodes
+ },
+ prepareBeginningIndexes: function(target) {
+ var targetLen = target.length
+ var beginningIndexes = []; var beginningIndexesLen = 0
+ var wasUpper = false
+ var wasAlphanum = false
+ for(var i = 0; i < targetLen; ++i) {
+ var targetCode = target.charCodeAt(i)
+ var isUpper = targetCode>=65&&targetCode<=90
+ var isAlphanum = isUpper || targetCode>=97&&targetCode<=122 || targetCode>=48&&targetCode<=57
+ var isBeginning = isUpper && !wasUpper || !wasAlphanum || !isAlphanum
+ wasUpper = isUpper
+ wasAlphanum = isAlphanum
+ if(isBeginning) beginningIndexes[beginningIndexesLen++] = i
+ }
+ return beginningIndexes
+ },
+ prepareNextBeginningIndexes: function(target) {
+ var targetLen = target.length
+ var beginningIndexes = fuzzysort.prepareBeginningIndexes(target)
+ var nextBeginningIndexes = [] // new Array(targetLen) sparse array is too slow
+ var lastIsBeginning = beginningIndexes[0]
+ var lastIsBeginningI = 0
+ for(var i = 0; i < targetLen; ++i) {
+ if(lastIsBeginning > i) {
+ nextBeginningIndexes[i] = lastIsBeginning
+ } else {
+ lastIsBeginning = beginningIndexes[++lastIsBeginningI]
+ nextBeginningIndexes[i] = lastIsBeginning===undefined ? targetLen : lastIsBeginning
+ }
+ }
+ return nextBeginningIndexes
+ },
+
+ cleanup: cleanup,
+ new: fuzzysortNew,
+ }
+ return fuzzysort
+} // fuzzysortNew
+
+// This stuff is outside fuzzysortNew, because it's shared with instances of fuzzysort.new()
+var isNode = typeof require !== 'undefined' && typeof window === 'undefined'
+// var MAX_INT = Number.MAX_SAFE_INTEGER
+// var MIN_INT = Number.MIN_VALUE
+var preparedCache = new Map()
+var preparedSearchCache = new Map()
+var noResults = []; noResults.total = 0
+var matchesSimple = []; var matchesStrict = []
+function cleanup() { preparedCache.clear(); preparedSearchCache.clear(); matchesSimple = []; matchesStrict = [] }
+function defaultScoreFn(a) {
+ var max = -9007199254740991
+ for (var i = a.length - 1; i >= 0; --i) {
+ var result = a[i]; if(result === null) continue
+ var score = result.score
+ if(score > max) max = score
+ }
+ if(max === -9007199254740991) return null
+ return max
+}
+
+// prop = 'key' 2.5ms optimized for this case, seems to be about as fast as direct obj[prop]
+// prop = 'key1.key2' 10ms
+// prop = ['key1', 'key2'] 27ms
+function getValue(obj, prop) {
+ var tmp = obj[prop]; if(tmp !== undefined) return tmp
+ var segs = prop
+ if(!Array.isArray(prop)) segs = prop.split('.')
+ var len = segs.length
+ var i = -1
+ while (obj && (++i < len)) obj = obj[segs[i]]
+ return obj
+}
+
+function isObj(x) { return typeof x === 'object' } // faster as a function
+
+// Hacked version of https://github.com/lemire/FastPriorityQueue.js
+var fastpriorityqueue=function(){var r=[],o=0,e={};function n(){for(var e=0,n=r[e],c=1;c<o;){var f=c+1;e=c,f<o&&r[f].score<r[c].score&&(e=f),r[e-1>>1]=r[e],c=1+(e<<1)}for(var a=e-1>>1;e>0&&n.score<r[a].score;a=(e=a)-1>>1)r[e]=r[a];r[e]=n}return e.add=function(e){var n=o;r[o++]=e;for(var c=n-1>>1;n>0&&e.score<r[c].score;c=(n=c)-1>>1)r[n]=r[c];r[n]=e},e.poll=function(){if(0!==o){var e=r[0];return r[0]=r[--o],n(),e}},e.peek=function(e){if(0!==o)return r[0]},e.replaceTop=function(o){r[0]=o,n()},e};
+var q = fastpriorityqueue() // reuse this, except for async, it needs to make its own
+
+return fuzzysortNew()
+}) // UMD
+
+// TODO: (performance) wasm version!?
+
+// TODO: (performance) layout memory in an optimal way to go fast by avoiding cache misses
+
+// TODO: (performance) preparedCache is a memory leak
+
+// TODO: (like sublime) backslash === forwardslash
+
+// TODO: (performance) i have no idea how well optizmied the allowing typos algorithm is
+
+}).call(this,require("timers").setImmediate)
+},{"timers":17}],8:[function(require,module,exports){
+exports.read = function (buffer, offset, isLE, mLen, nBytes) {
+ var e, m
+ var eLen = (nBytes * 8) - mLen - 1
+ var eMax = (1 << eLen) - 1
+ var eBias = eMax >> 1
+ var nBits = -7
+ var i = isLE ? (nBytes - 1) : 0
+ var d = isLE ? -1 : 1
+ var s = buffer[offset + i]
+
+ i += d
+
+ e = s & ((1 << (-nBits)) - 1)
+ s >>= (-nBits)
+ nBits += eLen
+ for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {}
+
+ m = e & ((1 << (-nBits)) - 1)
+ e >>= (-nBits)
+ nBits += mLen
+ for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {}
+
+ if (e === 0) {
+ e = 1 - eBias
+ } else if (e === eMax) {
+ return m ? NaN : ((s ? -1 : 1) * Infinity)
+ } else {
+ m = m + Math.pow(2, mLen)
+ e = e - eBias
+ }
+ return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
+}
+
+exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
+ var e, m, c
+ var eLen = (nBytes * 8) - mLen - 1
+ var eMax = (1 << eLen) - 1
+ var eBias = eMax >> 1
+ var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
+ var i = isLE ? 0 : (nBytes - 1)
+ var d = isLE ? 1 : -1
+ var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
+
+ value = Math.abs(value)
+
+ if (isNaN(value) || value === Infinity) {
+ m = isNaN(value) ? 1 : 0
+ e = eMax
+ } else {
+ e = Math.floor(Math.log(value) / Math.LN2)
+ if (value * (c = Math.pow(2, -e)) < 1) {
+ e--
+ c *= 2
+ }
+ if (e + eBias >= 1) {
+ value += rt / c
+ } else {
+ value += rt * Math.pow(2, 1 - eBias)
+ }
+ if (value * c >= 2) {
+ e++
+ c /= 2
+ }
+
+ if (e + eBias >= eMax) {
+ m = 0
+ e = eMax
+ } else if (e + eBias >= 1) {
+ m = ((value * c) - 1) * Math.pow(2, mLen)
+ e = e + eBias
+ } else {
+ m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
+ e = 0
+ }
+ }
+
+ for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
+
+ e = (e << mLen) | m
+ eLen += mLen
+ for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
+
+ buffer[offset + i - d] |= s * 128
+}
+
+},{}],9:[function(require,module,exports){
+(function (global,setImmediate){
+;(function() {
+"use strict"
+function Vnode(tag, key, attrs0, children, text, dom) {
+ return {tag: tag, key: key, attrs: attrs0, children: children, text: text, dom: dom, domSize: undefined, state: undefined, _state: undefined, events: undefined, instance: undefined, skip: false}
+}
+Vnode.normalize = function(node) {
+ if (Array.isArray(node)) return Vnode("[", undefined, undefined, Vnode.normalizeChildren(node), undefined, undefined)
+ if (node != null && typeof node !== "object") return Vnode("#", undefined, undefined, node === false ? "" : node, undefined, undefined)
+ return node
+}
+Vnode.normalizeChildren = function normalizeChildren(children) {
+ for (var i = 0; i < children.length; i++) {
+ children[i] = Vnode.normalize(children[i])
+ }
+ return children
+}
+var selectorParser = /(?:(^|#|\.)([^#\.\[\]]+))|(\[(.+?)(?:\s*=\s*("|'|)((?:\\["'\]]|.)*?)\5)?\])/g
+var selectorCache = {}
+var hasOwn = {}.hasOwnProperty
+function isEmpty(object) {
+ for (var key in object) if (hasOwn.call(object, key)) return false
+ return true
+}
+function compileSelector(selector) {
+ var match, tag = "div", classes = [], attrs = {}
+ while (match = selectorParser.exec(selector)) {
+ var type = match[1], value = match[2]
+ if (type === "" && value !== "") tag = value
+ else if (type === "#") attrs.id = value
+ else if (type === ".") classes.push(value)
+ else if (match[3][0] === "[") {
+ var attrValue = match[6]
+ if (attrValue) attrValue = attrValue.replace(/\\(["'])/g, "$1").replace(/\\\\/g, "\\")
+ if (match[4] === "class") classes.push(attrValue)
+ else attrs[match[4]] = attrValue === "" ? attrValue : attrValue || true
+ }
+ }
+ if (classes.length > 0) attrs.className = classes.join(" ")
+ return selectorCache[selector] = {tag: tag, attrs: attrs}
+}
+function execSelector(state, attrs, children) {
+ var hasAttrs = false, childList, text
+ var className = attrs.className || attrs.class
+ if (!isEmpty(state.attrs) && !isEmpty(attrs)) {
+ var newAttrs = {}
+ for(var key in attrs) {
+ if (hasOwn.call(attrs, key)) {
+ newAttrs[key] = attrs[key]
+ }
+ }
+ attrs = newAttrs
+ }
+ for (var key in state.attrs) {
+ if (hasOwn.call(state.attrs, key)) {
+ attrs[key] = state.attrs[key]
+ }
+ }
+ if (className !== undefined) {
+ if (attrs.class !== undefined) {
+ attrs.class = undefined
+ attrs.className = className
+ }
+ if (state.attrs.className != null) {
+ attrs.className = state.attrs.className + " " + className
+ }
+ }
+ for (var key in attrs) {
+ if (hasOwn.call(attrs, key) && key !== "key") {
+ hasAttrs = true
+ break
+ }
+ }
+ if (Array.isArray(children) && children.length === 1 && children[0] != null && children[0].tag === "#") {
+ text = children[0].children
+ } else {
+ childList = children
+ }
+ return Vnode(state.tag, attrs.key, hasAttrs ? attrs : undefined, childList, text)
+}
+function hyperscript(selector) {
+ // Because sloppy mode sucks
+ var attrs = arguments[1], start = 2, children
+ if (selector == null || typeof selector !== "string" && typeof selector !== "function" && typeof selector.view !== "function") {
+ throw Error("The selector must be either a string or a component.");
+ }
+ if (typeof selector === "string") {
+ var cached = selectorCache[selector] || compileSelector(selector)
+ }
+ if (attrs == null) {
+ attrs = {}
+ } else if (typeof attrs !== "object" || attrs.tag != null || Array.isArray(attrs)) {
+ attrs = {}
+ start = 1
+ }
+ if (arguments.length === start + 1) {
+ children = arguments[start]
+ if (!Array.isArray(children)) children = [children]
+ } else {
+ children = []
+ while (start < arguments.length) children.push(arguments[start++])
+ }
+ var normalized = Vnode.normalizeChildren(children)
+ if (typeof selector === "string") {
+ return execSelector(cached, attrs, normalized)
+ } else {
+ return Vnode(selector, attrs.key, attrs, normalized)
+ }
+}
+hyperscript.trust = function(html) {
+ if (html == null) html = ""
+ return Vnode("<", undefined, undefined, html, undefined, undefined)
+}
+hyperscript.fragment = function(attrs1, children) {
+ return Vnode("[", attrs1.key, attrs1, Vnode.normalizeChildren(children), undefined, undefined)
+}
+var m = hyperscript
+/** @constructor */
+var PromisePolyfill = function(executor) {
+ if (!(this instanceof PromisePolyfill)) throw new Error("Promise must be called with `new`")
+ if (typeof executor !== "function") throw new TypeError("executor must be a function")
+ var self = this, resolvers = [], rejectors = [], resolveCurrent = handler(resolvers, true), rejectCurrent = handler(rejectors, false)
+ var instance = self._instance = {resolvers: resolvers, rejectors: rejectors}
+ var callAsync = typeof setImmediate === "function" ? setImmediate : setTimeout
+ function handler(list, shouldAbsorb) {
+ return function execute(value) {
+ var then
+ try {
+ if (shouldAbsorb && value != null && (typeof value === "object" || typeof value === "function") && typeof (then = value.then) === "function") {
+ if (value === self) throw new TypeError("Promise can't be resolved w/ itself")
+ executeOnce(then.bind(value))
+ }
+ else {
+ callAsync(function() {
+ if (!shouldAbsorb && list.length === 0) console.error("Possible unhandled promise rejection:", value)
+ for (var i = 0; i < list.length; i++) list[i](value)
+ resolvers.length = 0, rejectors.length = 0
+ instance.state = shouldAbsorb
+ instance.retry = function() {execute(value)}
+ })
+ }
+ }
+ catch (e) {
+ rejectCurrent(e)
+ }
+ }
+ }
+ function executeOnce(then) {
+ var runs = 0
+ function run(fn) {
+ return function(value) {
+ if (runs++ > 0) return
+ fn(value)
+ }
+ }
+ var onerror = run(rejectCurrent)
+ try {then(run(resolveCurrent), onerror)} catch (e) {onerror(e)}
+ }
+ executeOnce(executor)
+}
+PromisePolyfill.prototype.then = function(onFulfilled, onRejection) {
+ var self = this, instance = self._instance
+ function handle(callback, list, next, state) {
+ list.push(function(value) {
+ if (typeof callback !== "function") next(value)
+ else try {resolveNext(callback(value))} catch (e) {if (rejectNext) rejectNext(e)}
+ })
+ if (typeof instance.retry === "function" && state === instance.state) instance.retry()
+ }
+ var resolveNext, rejectNext
+ var promise = new PromisePolyfill(function(resolve, reject) {resolveNext = resolve, rejectNext = reject})
+ handle(onFulfilled, instance.resolvers, resolveNext, true), handle(onRejection, instance.rejectors, rejectNext, false)
+ return promise
+}
+PromisePolyfill.prototype.catch = function(onRejection) {
+ return this.then(null, onRejection)
+}
+PromisePolyfill.resolve = function(value) {
+ if (value instanceof PromisePolyfill) return value
+ return new PromisePolyfill(function(resolve) {resolve(value)})
+}
+PromisePolyfill.reject = function(value) {
+ return new PromisePolyfill(function(resolve, reject) {reject(value)})
+}
+PromisePolyfill.all = function(list) {
+ return new PromisePolyfill(function(resolve, reject) {
+ var total = list.length, count = 0, values = []
+ if (list.length === 0) resolve([])
+ else for (var i = 0; i < list.length; i++) {
+ (function(i) {
+ function consume(value) {
+ count++
+ values[i] = value
+ if (count === total) resolve(values)
+ }
+ if (list[i] != null && (typeof list[i] === "object" || typeof list[i] === "function") && typeof list[i].then === "function") {
+ list[i].then(consume, reject)
+ }
+ else consume(list[i])
+ })(i)
+ }
+ })
+}
+PromisePolyfill.race = function(list) {
+ return new PromisePolyfill(function(resolve, reject) {
+ for (var i = 0; i < list.length; i++) {
+ list[i].then(resolve, reject)
+ }
+ })
+}
+if (typeof window !== "undefined") {
+ if (typeof window.Promise === "undefined") window.Promise = PromisePolyfill
+ var PromisePolyfill = window.Promise
+} else if (typeof global !== "undefined") {
+ if (typeof global.Promise === "undefined") global.Promise = PromisePolyfill
+ var PromisePolyfill = global.Promise
+} else {
+}
+var buildQueryString = function(object) {
+ if (Object.prototype.toString.call(object) !== "[object Object]") return ""
+ var args = []
+ for (var key0 in object) {
+ destructure(key0, object[key0])
+ }
+ return args.join("&")
+ function destructure(key0, value) {
+ if (Array.isArray(value)) {
+ for (var i = 0; i < value.length; i++) {
+ destructure(key0 + "[" + i + "]", value[i])
+ }
+ }
+ else if (Object.prototype.toString.call(value) === "[object Object]") {
+ for (var i in value) {
+ destructure(key0 + "[" + i + "]", value[i])
+ }
+ }
+ else args.push(encodeURIComponent(key0) + (value != null && value !== "" ? "=" + encodeURIComponent(value) : ""))
+ }
+}
+var FILE_PROTOCOL_REGEX = new RegExp("^file://", "i")
+var _8 = function($window, Promise) {
+ var callbackCount = 0
+ var oncompletion
+ function setCompletionCallback(callback) {oncompletion = callback}
+ function finalizer() {
+ var count = 0
+ function complete() {if (--count === 0 && typeof oncompletion === "function") oncompletion()}
+ return function finalize(promise0) {
+ var then0 = promise0.then
+ promise0.then = function() {
+ count++
+ var next = then0.apply(promise0, arguments)
+ next.then(complete, function(e) {
+ complete()
+ if (count === 0) throw e
+ })
+ return finalize(next)
+ }
+ return promise0
+ }
+ }
+ function normalize(args, extra) {
+ if (typeof args === "string") {
+ var url = args
+ args = extra || {}
+ if (args.url == null) args.url = url
+ }
+ return args
+ }
+ function request(args, extra) {
+ var finalize = finalizer()
+ args = normalize(args, extra)
+ var promise0 = new Promise(function(resolve, reject) {
+ if (args.method == null) args.method = "GET"
+ args.method = args.method.toUpperCase()
+ var useBody = (args.method === "GET" || args.method === "TRACE") ? false : (typeof args.useBody === "boolean" ? args.useBody : true)
+ if (typeof args.serialize !== "function") args.serialize = typeof FormData !== "undefined" && args.data instanceof FormData ? function(value) {return value} : JSON.stringify
+ if (typeof args.deserialize !== "function") args.deserialize = deserialize
+ if (typeof args.extract !== "function") args.extract = extract
+ args.url = interpolate(args.url, args.data)
+ if (useBody) args.data = args.serialize(args.data)
+ else args.url = assemble(args.url, args.data)
+ var xhr = new $window.XMLHttpRequest(),
+ aborted = false,
+ _abort = xhr.abort
+ xhr.abort = function abort() {
+ aborted = true
+ _abort.call(xhr)
+ }
+ xhr.open(args.method, args.url, typeof args.async === "boolean" ? args.async : true, typeof args.user === "string" ? args.user : undefined, typeof args.password === "string" ? args.password : undefined)
+ if (args.serialize === JSON.stringify && useBody && !(args.headers && args.headers.hasOwnProperty("Content-Type"))) {
+ xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8")
+ }
+ if (args.deserialize === deserialize && !(args.headers && args.headers.hasOwnProperty("Accept"))) {
+ xhr.setRequestHeader("Accept", "application/json, text/*")
+ }
+ if (args.withCredentials) xhr.withCredentials = args.withCredentials
+ for (var key in args.headers) if ({}.hasOwnProperty.call(args.headers, key)) {
+ xhr.setRequestHeader(key, args.headers[key])
+ }
+ if (typeof args.config === "function") xhr = args.config(xhr, args) || xhr
+ xhr.onreadystatechange = function() {
+ // Don't throw errors on xhr.abort().
+ if(aborted) return
+ if (xhr.readyState === 4) {
+ try {
+ var response = (args.extract !== extract) ? args.extract(xhr, args) : args.deserialize(args.extract(xhr, args))
+ if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304 || FILE_PROTOCOL_REGEX.test(args.url)) {
+ resolve(cast(args.type, response))
+ }
+ else {
+ var error = new Error(xhr.responseText)
+ for (var key in response) error[key] = response[key]
+ reject(error)
+ }
+ }
+ catch (e) {
+ reject(e)
+ }
+ }
+ }
+ if (useBody && (args.data != null)) xhr.send(args.data)
+ else xhr.send()
+ })
+ return args.background === true ? promise0 : finalize(promise0)
+ }
+ function jsonp(args, extra) {
+ var finalize = finalizer()
+ args = normalize(args, extra)
+ var promise0 = new Promise(function(resolve, reject) {
+ var callbackName = args.callbackName || "_mithril_" + Math.round(Math.random() * 1e16) + "_" + callbackCount++
+ var script = $window.document.createElement("script")
+ $window[callbackName] = function(data) {
+ script.parentNode.removeChild(script)
+ resolve(cast(args.type, data))
+ delete $window[callbackName]
+ }
+ script.onerror = function() {
+ script.parentNode.removeChild(script)
+ reject(new Error("JSONP request failed"))
+ delete $window[callbackName]
+ }
+ if (args.data == null) args.data = {}
+ args.url = interpolate(args.url, args.data)
+ args.data[args.callbackKey || "callback"] = callbackName
+ script.src = assemble(args.url, args.data)
+ $window.document.documentElement.appendChild(script)
+ })
+ return args.background === true? promise0 : finalize(promise0)
+ }
+ function interpolate(url, data) {
+ if (data == null) return url
+ var tokens = url.match(/:[^\/]+/gi) || []
+ for (var i = 0; i < tokens.length; i++) {
+ var key = tokens[i].slice(1)
+ if (data[key] != null) {
+ url = url.replace(tokens[i], data[key])
+ }
+ }
+ return url
+ }
+ function assemble(url, data) {
+ var querystring = buildQueryString(data)
+ if (querystring !== "") {
+ var prefix = url.indexOf("?") < 0 ? "?" : "&"
+ url += prefix + querystring
+ }
+ return url
+ }
+ function deserialize(data) {
+ try {return data !== "" ? JSON.parse(data) : null}
+ catch (e) {throw new Error(data)}
+ }
+ function extract(xhr) {return xhr.responseText}
+ function cast(type0, data) {
+ if (typeof type0 === "function") {
+ if (Array.isArray(data)) {
+ for (var i = 0; i < data.length; i++) {
+ data[i] = new type0(data[i])
+ }
+ }
+ else return new type0(data)
+ }
+ return data
+ }
+ return {request: request, jsonp: jsonp, setCompletionCallback: setCompletionCallback}
+}
+var requestService = _8(window, PromisePolyfill)
+var coreRenderer = function($window) {
+ var $doc = $window.document
+ var $emptyFragment = $doc.createDocumentFragment()
+ var nameSpace = {
+ svg: "http://www.w3.org/2000/svg",
+ math: "http://www.w3.org/1998/Math/MathML"
+ }
+ var onevent
+ function setEventCallback(callback) {return onevent = callback}
+ function getNameSpace(vnode) {
+ return vnode.attrs && vnode.attrs.xmlns || nameSpace[vnode.tag]
+ }
+ //create
+ function createNodes(parent, vnodes, start, end, hooks, nextSibling, ns) {
+ for (var i = start; i < end; i++) {
+ var vnode = vnodes[i]
+ if (vnode != null) {
+ createNode(parent, vnode, hooks, ns, nextSibling)
+ }
+ }
+ }
+ function createNode(parent, vnode, hooks, ns, nextSibling) {
+ var tag = vnode.tag
+ if (typeof tag === "string") {
+ vnode.state = {}
+ if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks)
+ switch (tag) {
+ case "#": return createText(parent, vnode, nextSibling)
+ case "<": return createHTML(parent, vnode, nextSibling)
+ case "[": return createFragment(parent, vnode, hooks, ns, nextSibling)
+ default: return createElement(parent, vnode, hooks, ns, nextSibling)
+ }
+ }
+ else return createComponent(parent, vnode, hooks, ns, nextSibling)
+ }
+ function createText(parent, vnode, nextSibling) {
+ vnode.dom = $doc.createTextNode(vnode.children)
+ insertNode(parent, vnode.dom, nextSibling)
+ return vnode.dom
+ }
+ function createHTML(parent, vnode, nextSibling) {
+ var match1 = vnode.children.match(/^\s*?<(\w+)/im) || []
+ var parent1 = {caption: "table", thead: "table", tbody: "table", tfoot: "table", tr: "tbody", th: "tr", td: "tr", colgroup: "table", col: "colgroup"}[match1[1]] || "div"
+ var temp = $doc.createElement(parent1)
+ temp.innerHTML = vnode.children
+ vnode.dom = temp.firstChild
+ vnode.domSize = temp.childNodes.length
+ var fragment = $doc.createDocumentFragment()
+ var child
+ while (child = temp.firstChild) {
+ fragment.appendChild(child)
+ }
+ insertNode(parent, fragment, nextSibling)
+ return fragment
+ }
+ function createFragment(parent, vnode, hooks, ns, nextSibling) {
+ var fragment = $doc.createDocumentFragment()
+ if (vnode.children != null) {
+ var children = vnode.children
+ createNodes(fragment, children, 0, children.length, hooks, null, ns)
+ }
+ vnode.dom = fragment.firstChild
+ vnode.domSize = fragment.childNodes.length
+ insertNode(parent, fragment, nextSibling)
+ return fragment
+ }
+ function createElement(parent, vnode, hooks, ns, nextSibling) {
+ var tag = vnode.tag
+ var attrs2 = vnode.attrs
+ var is = attrs2 && attrs2.is
+ ns = getNameSpace(vnode) || ns
+ var element = ns ?
+ is ? $doc.createElementNS(ns, tag, {is: is}) : $doc.createElementNS(ns, tag) :
+ is ? $doc.createElement(tag, {is: is}) : $doc.createElement(tag)
+ vnode.dom = element
+ if (attrs2 != null) {
+ setAttrs(vnode, attrs2, ns)
+ }
+ insertNode(parent, element, nextSibling)
+ if (vnode.attrs != null && vnode.attrs.contenteditable != null) {
+ setContentEditable(vnode)
+ }
+ else {
+ if (vnode.text != null) {
+ if (vnode.text !== "") element.textContent = vnode.text
+ else vnode.children = [Vnode("#", undefined, undefined, vnode.text, undefined, undefined)]
+ }
+ if (vnode.children != null) {
+ var children = vnode.children
+ createNodes(element, children, 0, children.length, hooks, null, ns)
+ setLateAttrs(vnode)
+ }
+ }
+ return element
+ }
+ function initComponent(vnode, hooks) {
+ var sentinel
+ if (typeof vnode.tag.view === "function") {
+ vnode.state = Object.create(vnode.tag)
+ sentinel = vnode.state.view
+ if (sentinel.$$reentrantLock$$ != null) return $emptyFragment
+ sentinel.$$reentrantLock$$ = true
+ } else {
+ vnode.state = void 0
+ sentinel = vnode.tag
+ if (sentinel.$$reentrantLock$$ != null) return $emptyFragment
+ sentinel.$$reentrantLock$$ = true
+ vnode.state = (vnode.tag.prototype != null && typeof vnode.tag.prototype.view === "function") ? new vnode.tag(vnode) : vnode.tag(vnode)
+ }
+ vnode._state = vnode.state
+ if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks)
+ initLifecycle(vnode._state, vnode, hooks)
+ vnode.instance = Vnode.normalize(vnode._state.view.call(vnode.state, vnode))
+ if (vnode.instance === vnode) throw Error("A view cannot return the vnode it received as argument")
+ sentinel.$$reentrantLock$$ = null
+ }
+ function createComponent(parent, vnode, hooks, ns, nextSibling) {
+ initComponent(vnode, hooks)
+ if (vnode.instance != null) {
+ var element = createNode(parent, vnode.instance, hooks, ns, nextSibling)
+ vnode.dom = vnode.instance.dom
+ vnode.domSize = vnode.dom != null ? vnode.instance.domSize : 0
+ insertNode(parent, element, nextSibling)
+ return element
+ }
+ else {
+ vnode.domSize = 0
+ return $emptyFragment
+ }
+ }
+ //update
+ function updateNodes(parent, old, vnodes, recycling, hooks, nextSibling, ns) {
+ if (old === vnodes || old == null && vnodes == null) return
+ else if (old == null) createNodes(parent, vnodes, 0, vnodes.length, hooks, nextSibling, ns)
+ else if (vnodes == null) removeNodes(old, 0, old.length, vnodes)
+ else {
+ if (old.length === vnodes.length) {
+ var isUnkeyed = false
+ for (var i = 0; i < vnodes.length; i++) {
+ if (vnodes[i] != null && old[i] != null) {
+ isUnkeyed = vnodes[i].key == null && old[i].key == null
+ break
+ }
+ }
+ if (isUnkeyed) {
+ for (var i = 0; i < old.length; i++) {
+ if (old[i] === vnodes[i]) continue
+ else if (old[i] == null && vnodes[i] != null) createNode(parent, vnodes[i], hooks, ns, getNextSibling(old, i + 1, nextSibling))
+ else if (vnodes[i] == null) removeNodes(old, i, i + 1, vnodes)
+ else updateNode(parent, old[i], vnodes[i], hooks, getNextSibling(old, i + 1, nextSibling), recycling, ns)
+ }
+ return
+ }
+ }
+ recycling = recycling || isRecyclable(old, vnodes)
+ if (recycling) {
+ var pool = old.pool
+ old = old.concat(old.pool)
+ }
+ var oldStart = 0, start = 0, oldEnd = old.length - 1, end = vnodes.length - 1, map
+ while (oldEnd >= oldStart && end >= start) {
+ var o = old[oldStart], v = vnodes[start]
+ if (o === v && !recycling) oldStart++, start++
+ else if (o == null) oldStart++
+ else if (v == null) start++
+ else if (o.key === v.key) {
+ var shouldRecycle = (pool != null && oldStart >= old.length - pool.length) || ((pool == null) && recycling)
+ oldStart++, start++
+ updateNode(parent, o, v, hooks, getNextSibling(old, oldStart, nextSibling), shouldRecycle, ns)
+ if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling)
+ }
+ else {
+ var o = old[oldEnd]
+ if (o === v && !recycling) oldEnd--, start++
+ else if (o == null) oldEnd--
+ else if (v == null) start++
+ else if (o.key === v.key) {
+ var shouldRecycle = (pool != null && oldEnd >= old.length - pool.length) || ((pool == null) && recycling)
+ updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), shouldRecycle, ns)
+ if (recycling || start < end) insertNode(parent, toFragment(o), getNextSibling(old, oldStart, nextSibling))
+ oldEnd--, start++
+ }
+ else break
+ }
+ }
+ while (oldEnd >= oldStart && end >= start) {
+ var o = old[oldEnd], v = vnodes[end]
+ if (o === v && !recycling) oldEnd--, end--
+ else if (o == null) oldEnd--
+ else if (v == null) end--
+ else if (o.key === v.key) {
+ var shouldRecycle = (pool != null && oldEnd >= old.length - pool.length) || ((pool == null) && recycling)
+ updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), shouldRecycle, ns)
+ if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling)
+ if (o.dom != null) nextSibling = o.dom
+ oldEnd--, end--
+ }
+ else {
+ if (!map) map = getKeyMap(old, oldEnd)
+ if (v != null) {
+ var oldIndex = map[v.key]
+ if (oldIndex != null) {
+ var movable = old[oldIndex]
+ var shouldRecycle = (pool != null && oldIndex >= old.length - pool.length) || ((pool == null) && recycling)
+ updateNode(parent, movable, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns)
+ insertNode(parent, toFragment(movable), nextSibling)
+ old[oldIndex].skip = true
+ if (movable.dom != null) nextSibling = movable.dom
+ }
+ else {
+ var dom = createNode(parent, v, hooks, ns, nextSibling)
+ nextSibling = dom
+ }
+ }
+ end--
+ }
+ if (end < start) break
+ }
+ createNodes(parent, vnodes, start, end + 1, hooks, nextSibling, ns)
+ removeNodes(old, oldStart, oldEnd + 1, vnodes)
+ }
+ }
+ function updateNode(parent, old, vnode, hooks, nextSibling, recycling, ns) {
+ var oldTag = old.tag, tag = vnode.tag
+ if (oldTag === tag) {
+ vnode.state = old.state
+ vnode._state = old._state
+ vnode.events = old.events
+ if (!recycling && shouldNotUpdate(vnode, old)) return
+ if (typeof oldTag === "string") {
+ if (vnode.attrs != null) {
+ if (recycling) {
+ vnode.state = {}
+ initLifecycle(vnode.attrs, vnode, hooks)
+ }
+ else updateLifecycle(vnode.attrs, vnode, hooks)
+ }
+ switch (oldTag) {
+ case "#": updateText(old, vnode); break
+ case "<": updateHTML(parent, old, vnode, nextSibling); break
+ case "[": updateFragment(parent, old, vnode, recycling, hooks, nextSibling, ns); break
+ default: updateElement(old, vnode, recycling, hooks, ns)
+ }
+ }
+ else updateComponent(parent, old, vnode, hooks, nextSibling, recycling, ns)
+ }
+ else {
+ removeNode(old, null)
+ createNode(parent, vnode, hooks, ns, nextSibling)
+ }
+ }
+ function updateText(old, vnode) {
+ if (old.children.toString() !== vnode.children.toString()) {
+ old.dom.nodeValue = vnode.children
+ }
+ vnode.dom = old.dom
+ }
+ function updateHTML(parent, old, vnode, nextSibling) {
+ if (old.children !== vnode.children) {
+ toFragment(old)
+ createHTML(parent, vnode, nextSibling)
+ }
+ else vnode.dom = old.dom, vnode.domSize = old.domSize
+ }
+ function updateFragment(parent, old, vnode, recycling, hooks, nextSibling, ns) {
+ updateNodes(parent, old.children, vnode.children, recycling, hooks, nextSibling, ns)
+ var domSize = 0, children = vnode.children
+ vnode.dom = null
+ if (children != null) {
+ for (var i = 0; i < children.length; i++) {
+ var child = children[i]
+ if (child != null && child.dom != null) {
+ if (vnode.dom == null) vnode.dom = child.dom
+ domSize += child.domSize || 1
+ }
+ }
+ if (domSize !== 1) vnode.domSize = domSize
+ }
+ }
+ function updateElement(old, vnode, recycling, hooks, ns) {
+ var element = vnode.dom = old.dom
+ ns = getNameSpace(vnode) || ns
+ if (vnode.tag === "textarea") {
+ if (vnode.attrs == null) vnode.attrs = {}
+ if (vnode.text != null) {
+ vnode.attrs.value = vnode.text //FIXME handle0 multiple children
+ vnode.text = undefined
+ }
+ }
+ updateAttrs(vnode, old.attrs, vnode.attrs, ns)
+ if (vnode.attrs != null && vnode.attrs.contenteditable != null) {
+ setContentEditable(vnode)
+ }
+ else if (old.text != null && vnode.text != null && vnode.text !== "") {
+ if (old.text.toString() !== vnode.text.toString()) old.dom.firstChild.nodeValue = vnode.text
+ }
+ else {
+ if (old.text != null) old.children = [Vnode("#", undefined, undefined, old.text, undefined, old.dom.firstChild)]
+ if (vnode.text != null) vnode.children = [Vnode("#", undefined, undefined, vnode.text, undefined, undefined)]
+ updateNodes(element, old.children, vnode.children, recycling, hooks, null, ns)
+ }
+ }
+ function updateComponent(parent, old, vnode, hooks, nextSibling, recycling, ns) {
+ if (recycling) {
+ initComponent(vnode, hooks)
+ } else {
+ vnode.instance = Vnode.normalize(vnode._state.view.call(vnode.state, vnode))
+ if (vnode.instance === vnode) throw Error("A view cannot return the vnode it received as argument")
+ if (vnode.attrs != null) updateLifecycle(vnode.attrs, vnode, hooks)
+ updateLifecycle(vnode._state, vnode, hooks)
+ }
+ if (vnode.instance != null) {
+ if (old.instance == null) createNode(parent, vnode.instance, hooks, ns, nextSibling)
+ else updateNode(parent, old.instance, vnode.instance, hooks, nextSibling, recycling, ns)
+ vnode.dom = vnode.instance.dom
+ vnode.domSize = vnode.instance.domSize
+ }
+ else if (old.instance != null) {
+ removeNode(old.instance, null)
+ vnode.dom = undefined
+ vnode.domSize = 0
+ }
+ else {
+ vnode.dom = old.dom
+ vnode.domSize = old.domSize
+ }
+ }
+ function isRecyclable(old, vnodes) {
+ if (old.pool != null && Math.abs(old.pool.length - vnodes.length) <= Math.abs(old.length - vnodes.length)) {
+ var oldChildrenLength = old[0] && old[0].children && old[0].children.length || 0
+ var poolChildrenLength = old.pool[0] && old.pool[0].children && old.pool[0].children.length || 0
+ var vnodesChildrenLength = vnodes[0] && vnodes[0].children && vnodes[0].children.length || 0
+ if (Math.abs(poolChildrenLength - vnodesChildrenLength) <= Math.abs(oldChildrenLength - vnodesChildrenLength)) {
+ return true
+ }
+ }
+ return false
+ }
+ function getKeyMap(vnodes, end) {
+ var map = {}, i = 0
+ for (var i = 0; i < end; i++) {
+ var vnode = vnodes[i]
+ if (vnode != null) {
+ var key2 = vnode.key
+ if (key2 != null) map[key2] = i
+ }
+ }
+ return map
+ }
+ function toFragment(vnode) {
+ var count0 = vnode.domSize
+ if (count0 != null || vnode.dom == null) {
+ var fragment = $doc.createDocumentFragment()
+ if (count0 > 0) {
+ var dom = vnode.dom
+ while (--count0) fragment.appendChild(dom.nextSibling)
+ fragment.insertBefore(dom, fragment.firstChild)
+ }
+ return fragment
+ }
+ else return vnode.dom
+ }
+ function getNextSibling(vnodes, i, nextSibling) {
+ for (; i < vnodes.length; i++) {
+ if (vnodes[i] != null && vnodes[i].dom != null) return vnodes[i].dom
+ }
+ return nextSibling
+ }
+ function insertNode(parent, dom, nextSibling) {
+ if (nextSibling && nextSibling.parentNode) parent.insertBefore(dom, nextSibling)
+ else parent.appendChild(dom)
+ }
+ function setContentEditable(vnode) {
+ var children = vnode.children
+ if (children != null && children.length === 1 && children[0].tag === "<") {
+ var content = children[0].children
+ if (vnode.dom.innerHTML !== content) vnode.dom.innerHTML = content
+ }
+ else if (vnode.text != null || children != null && children.length !== 0) throw new Error("Child node of a contenteditable must be trusted")
+ }
+ //remove
+ function removeNodes(vnodes, start, end, context) {
+ for (var i = start; i < end; i++) {
+ var vnode = vnodes[i]
+ if (vnode != null) {
+ if (vnode.skip) vnode.skip = false
+ else removeNode(vnode, context)
+ }
+ }
+ }
+ function removeNode(vnode, context) {
+ var expected = 1, called = 0
+ if (vnode.attrs && typeof vnode.attrs.onbeforeremove === "function") {
+ var result = vnode.attrs.onbeforeremove.call(vnode.state, vnode)
+ if (result != null && typeof result.then === "function") {
+ expected++
+ result.then(continuation, continuation)
+ }
+ }
+ if (typeof vnode.tag !== "string" && typeof vnode._state.onbeforeremove === "function") {
+ var result = vnode._state.onbeforeremove.call(vnode.state, vnode)
+ if (result != null && typeof result.then === "function") {
+ expected++
+ result.then(continuation, continuation)
+ }
+ }
+ continuation()
+ function continuation() {
+ if (++called === expected) {
+ onremove(vnode)
+ if (vnode.dom) {
+ var count0 = vnode.domSize || 1
+ if (count0 > 1) {
+ var dom = vnode.dom
+ while (--count0) {
+ removeNodeFromDOM(dom.nextSibling)
+ }
+ }
+ removeNodeFromDOM(vnode.dom)
+ if (context != null && vnode.domSize == null && !hasIntegrationMethods(vnode.attrs) && typeof vnode.tag === "string") { //TODO test custom elements
+ if (!context.pool) context.pool = [vnode]
+ else context.pool.push(vnode)
+ }
+ }
+ }
+ }
+ }
+ function removeNodeFromDOM(node) {
+ var parent = node.parentNode
+ if (parent != null) parent.removeChild(node)
+ }
+ function onremove(vnode) {
+ if (vnode.attrs && typeof vnode.attrs.onremove === "function") vnode.attrs.onremove.call(vnode.state, vnode)
+ if (typeof vnode.tag !== "string") {
+ if (typeof vnode._state.onremove === "function") vnode._state.onremove.call(vnode.state, vnode)
+ if (vnode.instance != null) onremove(vnode.instance)
+ } else {
+ var children = vnode.children
+ if (Array.isArray(children)) {
+ for (var i = 0; i < children.length; i++) {
+ var child = children[i]
+ if (child != null) onremove(child)
+ }
+ }
+ }
+ }
+ //attrs2
+ function setAttrs(vnode, attrs2, ns) {
+ for (var key2 in attrs2) {
+ setAttr(vnode, key2, null, attrs2[key2], ns)
+ }
+ }
+ function setAttr(vnode, key2, old, value, ns) {
+ var element = vnode.dom
+ if (key2 === "key" || key2 === "is" || (old === value && !isFormAttribute(vnode, key2)) && typeof value !== "object" || typeof value === "undefined" || isLifecycleMethod(key2)) return
+ var nsLastIndex = key2.indexOf(":")
+ if (nsLastIndex > -1 && key2.substr(0, nsLastIndex) === "xlink") {
+ element.setAttributeNS("http://www.w3.org/1999/xlink", key2.slice(nsLastIndex + 1), value)
+ }
+ else if (key2[0] === "o" && key2[1] === "n" && typeof value === "function") updateEvent(vnode, key2, value)
+ else if (key2 === "style") updateStyle(element, old, value)
+ else if (key2 in element && !isAttribute(key2) && ns === undefined && !isCustomElement(vnode)) {
+ if (key2 === "value") {
+ var normalized0 = "" + value // eslint-disable-line no-implicit-coercion
+ //setting input[value] to same value by typing on focused element moves cursor to end in Chrome
+ if ((vnode.tag === "input" || vnode.tag === "textarea") && vnode.dom.value === normalized0 && vnode.dom === $doc.activeElement) return
+ //setting select[value] to same value while having select open blinks select dropdown in Chrome
+ if (vnode.tag === "select") {
+ if (value === null) {
+ if (vnode.dom.selectedIndex === -1 && vnode.dom === $doc.activeElement) return
+ } else {
+ if (old !== null && vnode.dom.value === normalized0 && vnode.dom === $doc.activeElement) return
+ }
+ }
+ //setting option[value] to same value while having select open blinks select dropdown in Chrome
+ if (vnode.tag === "option" && old != null && vnode.dom.value === normalized0) return
+ }
+ // If you assign an input type1 that is not supported by IE 11 with an assignment expression, an error0 will occur.
+ if (vnode.tag === "input" && key2 === "type") {
+ element.setAttribute(key2, value)
+ return
+ }
+ element[key2] = value
+ }
+ else {
+ if (typeof value === "boolean") {
+ if (value) element.setAttribute(key2, "")
+ else element.removeAttribute(key2)
+ }
+ else element.setAttribute(key2 === "className" ? "class" : key2, value)
+ }
+ }
+ function setLateAttrs(vnode) {
+ var attrs2 = vnode.attrs
+ if (vnode.tag === "select" && attrs2 != null) {
+ if ("value" in attrs2) setAttr(vnode, "value", null, attrs2.value, undefined)
+ if ("selectedIndex" in attrs2) setAttr(vnode, "selectedIndex", null, attrs2.selectedIndex, undefined)
+ }
+ }
+ function updateAttrs(vnode, old, attrs2, ns) {
+ if (attrs2 != null) {
+ for (var key2 in attrs2) {
+ setAttr(vnode, key2, old && old[key2], attrs2[key2], ns)
+ }
+ }
+ if (old != null) {
+ for (var key2 in old) {
+ if (attrs2 == null || !(key2 in attrs2)) {
+ if (key2 === "className") key2 = "class"
+ if (key2[0] === "o" && key2[1] === "n" && !isLifecycleMethod(key2)) updateEvent(vnode, key2, undefined)
+ else if (key2 !== "key") vnode.dom.removeAttribute(key2)
+ }
+ }
+ }
+ }
+ function isFormAttribute(vnode, attr) {
+ return attr === "value" || attr === "checked" || attr === "selectedIndex" || attr === "selected" && vnode.dom === $doc.activeElement
+ }
+ function isLifecycleMethod(attr) {
+ return attr === "oninit" || attr === "oncreate" || attr === "onupdate" || attr === "onremove" || attr === "onbeforeremove" || attr === "onbeforeupdate"
+ }
+ function isAttribute(attr) {
+ return attr === "href" || attr === "list" || attr === "form" || attr === "width" || attr === "height"// || attr === "type"
+ }
+ function isCustomElement(vnode){
+ return vnode.attrs.is || vnode.tag.indexOf("-") > -1
+ }
+ function hasIntegrationMethods(source) {
+ return source != null && (source.oncreate || source.onupdate || source.onbeforeremove || source.onremove)
+ }
+ //style
+ function updateStyle(element, old, style) {
+ if (old === style) element.style.cssText = "", old = null
+ if (style == null) element.style.cssText = ""
+ else if (typeof style === "string") element.style.cssText = style
+ else {
+ if (typeof old === "string") element.style.cssText = ""
+ for (var key2 in style) {
+ element.style[key2] = style[key2]
+ }
+ if (old != null && typeof old !== "string") {
+ for (var key2 in old) {
+ if (!(key2 in style)) element.style[key2] = ""
+ }
+ }
+ }
+ }
+ //event
+ function updateEvent(vnode, key2, value) {
+ var element = vnode.dom
+ var callback = typeof onevent !== "function" ? value : function(e) {
+ var result = value.call(element, e)
+ onevent.call(element, e)
+ return result
+ }
+ if (key2 in element) element[key2] = typeof value === "function" ? callback : null
+ else {
+ var eventName = key2.slice(2)
+ if (vnode.events === undefined) vnode.events = {}
+ if (vnode.events[key2] === callback) return
+ if (vnode.events[key2] != null) element.removeEventListener(eventName, vnode.events[key2], false)
+ if (typeof value === "function") {
+ vnode.events[key2] = callback
+ element.addEventListener(eventName, vnode.events[key2], false)
+ }
+ }
+ }
+ //lifecycle
+ function initLifecycle(source, vnode, hooks) {
+ if (typeof source.oninit === "function") source.oninit.call(vnode.state, vnode)
+ if (typeof source.oncreate === "function") hooks.push(source.oncreate.bind(vnode.state, vnode))
+ }
+ function updateLifecycle(source, vnode, hooks) {
+ if (typeof source.onupdate === "function") hooks.push(source.onupdate.bind(vnode.state, vnode))
+ }
+ function shouldNotUpdate(vnode, old) {
+ var forceVnodeUpdate, forceComponentUpdate
+ if (vnode.attrs != null && typeof vnode.attrs.onbeforeupdate === "function") forceVnodeUpdate = vnode.attrs.onbeforeupdate.call(vnode.state, vnode, old)
+ if (typeof vnode.tag !== "string" && typeof vnode._state.onbeforeupdate === "function") forceComponentUpdate = vnode._state.onbeforeupdate.call(vnode.state, vnode, old)
+ if (!(forceVnodeUpdate === undefined && forceComponentUpdate === undefined) && !forceVnodeUpdate && !forceComponentUpdate) {
+ vnode.dom = old.dom
+ vnode.domSize = old.domSize
+ vnode.instance = old.instance
+ return true
+ }
+ return false
+ }
+ function render(dom, vnodes) {
+ if (!dom) throw new Error("Ensure the DOM element being passed to m.route/m.mount/m.render is not undefined.")
+ var hooks = []
+ var active = $doc.activeElement
+ var namespace = dom.namespaceURI
+ // First time0 rendering into a node clears it out
+ if (dom.vnodes == null) dom.textContent = ""
+ if (!Array.isArray(vnodes)) vnodes = [vnodes]
+ updateNodes(dom, dom.vnodes, Vnode.normalizeChildren(vnodes), false, hooks, null, namespace === "http://www.w3.org/1999/xhtml" ? undefined : namespace)
+ dom.vnodes = vnodes
+ // document.activeElement can return null in IE https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement
+ if (active != null && $doc.activeElement !== active) active.focus()
+ for (var i = 0; i < hooks.length; i++) hooks[i]()
+ }
+ return {render: render, setEventCallback: setEventCallback}
+}
+function throttle(callback) {
+ //60fps translates to 16.6ms, round it down since setTimeout requires int
+ var time = 16
+ var last = 0, pending = null
+ var timeout = typeof requestAnimationFrame === "function" ? requestAnimationFrame : setTimeout
+ return function() {
+ var now = Date.now()
+ if (last === 0 || now - last >= time) {
+ last = now
+ callback()
+ }
+ else if (pending === null) {
+ pending = timeout(function() {
+ pending = null
+ callback()
+ last = Date.now()
+ }, time - (now - last))
+ }
+ }
+}
+var _11 = function($window) {
+ var renderService = coreRenderer($window)
+ renderService.setEventCallback(function(e) {
+ if (e.redraw === false) e.redraw = undefined
+ else redraw()
+ })
+ var callbacks = []
+ function subscribe(key1, callback) {
+ unsubscribe(key1)
+ callbacks.push(key1, throttle(callback))
+ }
+ function unsubscribe(key1) {
+ var index = callbacks.indexOf(key1)
+ if (index > -1) callbacks.splice(index, 2)
+ }
+ function redraw() {
+ for (var i = 1; i < callbacks.length; i += 2) {
+ callbacks[i]()
+ }
+ }
+ return {subscribe: subscribe, unsubscribe: unsubscribe, redraw: redraw, render: renderService.render}
+}
+var redrawService = _11(window)
+requestService.setCompletionCallback(redrawService.redraw)
+var _16 = function(redrawService0) {
+ return function(root, component) {
+ if (component === null) {
+ redrawService0.render(root, [])
+ redrawService0.unsubscribe(root)
+ return
+ }
+
+ if (component.view == null && typeof component !== "function") throw new Error("m.mount(element, component) expects a component, not a vnode")
+
+ var run0 = function() {
+ redrawService0.render(root, Vnode(component))
+ }
+ redrawService0.subscribe(root, run0)
+ redrawService0.redraw()
+ }
+}
+m.mount = _16(redrawService)
+var Promise = PromisePolyfill
+var parseQueryString = function(string) {
+ if (string === "" || string == null) return {}
+ if (string.charAt(0) === "?") string = string.slice(1)
+ var entries = string.split("&"), data0 = {}, counters = {}
+ for (var i = 0; i < entries.length; i++) {
+ var entry = entries[i].split("=")
+ var key5 = decodeURIComponent(entry[0])
+ var value = entry.length === 2 ? decodeURIComponent(entry[1]) : ""
+ if (value === "true") value = true
+ else if (value === "false") value = false
+ var levels = key5.split(/\]\[?|\[/)
+ var cursor = data0
+ if (key5.indexOf("[") > -1) levels.pop()
+ for (var j = 0; j < levels.length; j++) {
+ var level = levels[j], nextLevel = levels[j + 1]
+ var isNumber = nextLevel == "" || !isNaN(parseInt(nextLevel, 10))
+ var isValue = j === levels.length - 1
+ if (level === "") {
+ var key5 = levels.slice(0, j).join()
+ if (counters[key5] == null) counters[key5] = 0
+ level = counters[key5]++
+ }
+ if (cursor[level] == null) {
+ cursor[level] = isValue ? value : isNumber ? [] : {}
+ }
+ cursor = cursor[level]
+ }
+ }
+ return data0
+}
+var coreRouter = function($window) {
+ var supportsPushState = typeof $window.history.pushState === "function"
+ var callAsync0 = typeof setImmediate === "function" ? setImmediate : setTimeout
+ function normalize1(fragment0) {
+ var data = $window.location[fragment0].replace(/(?:%[a-f89][a-f0-9])+/gim, decodeURIComponent)
+ if (fragment0 === "pathname" && data[0] !== "/") data = "/" + data
+ return data
+ }
+ var asyncId
+ function debounceAsync(callback0) {
+ return function() {
+ if (asyncId != null) return
+ asyncId = callAsync0(function() {
+ asyncId = null
+ callback0()
+ })
+ }
+ }
+ function parsePath(path, queryData, hashData) {
+ var queryIndex = path.indexOf("?")
+ var hashIndex = path.indexOf("#")
+ var pathEnd = queryIndex > -1 ? queryIndex : hashIndex > -1 ? hashIndex : path.length
+ if (queryIndex > -1) {
+ var queryEnd = hashIndex > -1 ? hashIndex : path.length
+ var queryParams = parseQueryString(path.slice(queryIndex + 1, queryEnd))
+ for (var key4 in queryParams) queryData[key4] = queryParams[key4]
+ }
+ if (hashIndex > -1) {
+ var hashParams = parseQueryString(path.slice(hashIndex + 1))
+ for (var key4 in hashParams) hashData[key4] = hashParams[key4]
+ }
+ return path.slice(0, pathEnd)
+ }
+ var router = {prefix: "#!"}
+ router.getPath = function() {
+ var type2 = router.prefix.charAt(0)
+ switch (type2) {
+ case "#": return normalize1("hash").slice(router.prefix.length)
+ case "?": return normalize1("search").slice(router.prefix.length) + normalize1("hash")
+ default: return normalize1("pathname").slice(router.prefix.length) + normalize1("search") + normalize1("hash")
+ }
+ }
+ router.setPath = function(path, data, options) {
+ var queryData = {}, hashData = {}
+ path = parsePath(path, queryData, hashData)
+ if (data != null) {
+ for (var key4 in data) queryData[key4] = data[key4]
+ path = path.replace(/:([^\/]+)/g, function(match2, token) {
+ delete queryData[token]
+ return data[token]
+ })
+ }
+ var query = buildQueryString(queryData)
+ if (query) path += "?" + query
+ var hash = buildQueryString(hashData)
+ if (hash) path += "#" + hash
+ if (supportsPushState) {
+ var state = options ? options.state : null
+ var title = options ? options.title : null
+ $window.onpopstate()
+ if (options && options.replace) $window.history.replaceState(state, title, router.prefix + path)
+ else $window.history.pushState(state, title, router.prefix + path)
+ }
+ else $window.location.href = router.prefix + path
+ }
+ router.defineRoutes = function(routes, resolve, reject) {
+ function resolveRoute() {
+ var path = router.getPath()
+ var params = {}
+ var pathname = parsePath(path, params, params)
+ var state = $window.history.state
+ if (state != null) {
+ for (var k in state) params[k] = state[k]
+ }
+ for (var route0 in routes) {
+ var matcher = new RegExp("^" + route0.replace(/:[^\/]+?\.{3}/g, "(.*?)").replace(/:[^\/]+/g, "([^\\/]+)") + "\/?$")
+ if (matcher.test(pathname)) {
+ pathname.replace(matcher, function() {
+ var keys = route0.match(/:[^\/]+/g) || []
+ var values = [].slice.call(arguments, 1, -2)
+ for (var i = 0; i < keys.length; i++) {
+ params[keys[i].replace(/:|\./g, "")] = decodeURIComponent(values[i])
+ }
+ resolve(routes[route0], params, path, route0)
+ })
+ return
+ }
+ }
+ reject(path, params)
+ }
+ if (supportsPushState) $window.onpopstate = debounceAsync(resolveRoute)
+ else if (router.prefix.charAt(0) === "#") $window.onhashchange = resolveRoute
+ resolveRoute()
+ }
+ return router
+}
+var _20 = function($window, redrawService0) {
+ var routeService = coreRouter($window)
+ var identity = function(v) {return v}
+ var render1, component, attrs3, currentPath, lastUpdate
+ var route = function(root, defaultRoute, routes) {
+ if (root == null) throw new Error("Ensure the DOM element that was passed to `m.route` is not undefined")
+ var run1 = function() {
+ if (render1 != null) redrawService0.render(root, render1(Vnode(component, attrs3.key, attrs3)))
+ }
+ var bail = function(path) {
+ if (path !== defaultRoute) routeService.setPath(defaultRoute, null, {replace: true})
+ else throw new Error("Could not resolve default route " + defaultRoute)
+ }
+ routeService.defineRoutes(routes, function(payload, params, path) {
+ var update = lastUpdate = function(routeResolver, comp) {
+ if (update !== lastUpdate) return
+ component = comp != null && (typeof comp.view === "function" || typeof comp === "function")? comp : "div"
+ attrs3 = params, currentPath = path, lastUpdate = null
+ render1 = (routeResolver.render || identity).bind(routeResolver)
+ run1()
+ }
+ if (payload.view || typeof payload === "function") update({}, payload)
+ else {
+ if (payload.onmatch) {
+ Promise.resolve(payload.onmatch(params, path)).then(function(resolved) {
+ update(payload, resolved)
+ }, bail)
+ }
+ else update(payload, "div")
+ }
+ }, bail)
+ redrawService0.subscribe(root, run1)
+ }
+ route.set = function(path, data, options) {
+ if (lastUpdate != null) {
+ options = options || {}
+ options.replace = true
+ }
+ lastUpdate = null
+ routeService.setPath(path, data, options)
+ }
+ route.get = function() {return currentPath}
+ route.prefix = function(prefix0) {routeService.prefix = prefix0}
+ route.link = function(vnode1) {
+ vnode1.dom.setAttribute("href", routeService.prefix + vnode1.attrs.href)
+ vnode1.dom.onclick = function(e) {
+ if (e.ctrlKey || e.metaKey || e.shiftKey || e.which === 2) return
+ e.preventDefault()
+ e.redraw = false
+ var href = this.getAttribute("href")
+ if (href.indexOf(routeService.prefix) === 0) href = href.slice(routeService.prefix.length)
+ route.set(href, undefined, undefined)
+ }
+ }
+ route.param = function(key3) {
+ if(typeof attrs3 !== "undefined" && typeof key3 !== "undefined") return attrs3[key3]
+ return attrs3
+ }
+ return route
+}
+m.route = _20(window, redrawService)
+m.withAttr = function(attrName, callback1, context) {
+ return function(e) {
+ callback1.call(context || this, attrName in e.currentTarget ? e.currentTarget[attrName] : e.currentTarget.getAttribute(attrName))
+ }
+}
+var _28 = coreRenderer(window)
+m.render = _28.render
+m.redraw = redrawService.redraw
+m.request = requestService.request
+m.jsonp = requestService.jsonp
+m.parseQueryString = parseQueryString
+m.buildQueryString = buildQueryString
+m.version = "1.1.6"
+m.vnode = Vnode
+if (typeof module !== "undefined") module["exports"] = m
+else window.m = m
+}());
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("timers").setImmediate)
+},{"timers":17}],10:[function(require,module,exports){
+//! moment.js
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ global.moment = factory()
+}(this, (function () { 'use strict';
+
+ var hookCallback;
+
+ function hooks () {
+ return hookCallback.apply(null, arguments);
+ }
+
+ // This is done to register the method called with moment()
+ // without creating circular dependencies.
+ function setHookCallback (callback) {
+ hookCallback = callback;
+ }
+
+ function isArray(input) {
+ return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
+ }
+
+ function isObject(input) {
+ // IE8 will treat undefined and null as object if it wasn't for
+ // input != null
+ return input != null && Object.prototype.toString.call(input) === '[object Object]';
+ }
+
+ function isObjectEmpty(obj) {
+ if (Object.getOwnPropertyNames) {
+ return (Object.getOwnPropertyNames(obj).length === 0);
+ } else {
+ var k;
+ for (k in obj) {
+ if (obj.hasOwnProperty(k)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ function isUndefined(input) {
+ return input === void 0;
+ }
+
+ function isNumber(input) {
+ return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]';
+ }
+
+ function isDate(input) {
+ return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
+ }
+
+ function map(arr, fn) {
+ var res = [], i;
+ for (i = 0; i < arr.length; ++i) {
+ res.push(fn(arr[i], i));
+ }
+ return res;
+ }
+
+ function hasOwnProp(a, b) {
+ return Object.prototype.hasOwnProperty.call(a, b);
+ }
+
+ function extend(a, b) {
+ for (var i in b) {
+ if (hasOwnProp(b, i)) {
+ a[i] = b[i];
+ }
+ }
+
+ if (hasOwnProp(b, 'toString')) {
+ a.toString = b.toString;
+ }
+
+ if (hasOwnProp(b, 'valueOf')) {
+ a.valueOf = b.valueOf;
+ }
+
+ return a;
+ }
+
+ function createUTC (input, format, locale, strict) {
+ return createLocalOrUTC(input, format, locale, strict, true).utc();
+ }
+
+ function defaultParsingFlags() {
+ // We need to deep clone this object.
+ return {
+ empty : false,
+ unusedTokens : [],
+ unusedInput : [],
+ overflow : -2,
+ charsLeftOver : 0,
+ nullInput : false,
+ invalidMonth : null,
+ invalidFormat : false,
+ userInvalidated : false,
+ iso : false,
+ parsedDateParts : [],
+ meridiem : null,
+ rfc2822 : false,
+ weekdayMismatch : false
+ };
+ }
+
+ function getParsingFlags(m) {
+ if (m._pf == null) {
+ m._pf = defaultParsingFlags();
+ }
+ return m._pf;
+ }
+
+ var some;
+ if (Array.prototype.some) {
+ some = Array.prototype.some;
+ } else {
+ some = function (fun) {
+ var t = Object(this);
+ var len = t.length >>> 0;
+
+ for (var i = 0; i < len; i++) {
+ if (i in t && fun.call(this, t[i], i, t)) {
+ return true;
+ }
+ }
+
+ return false;
+ };
+ }
+
+ function isValid(m) {
+ if (m._isValid == null) {
+ var flags = getParsingFlags(m);
+ var parsedParts = some.call(flags.parsedDateParts, function (i) {
+ return i != null;
+ });
+ var isNowValid = !isNaN(m._d.getTime()) &&
+ flags.overflow < 0 &&
+ !flags.empty &&
+ !flags.invalidMonth &&
+ !flags.invalidWeekday &&
+ !flags.weekdayMismatch &&
+ !flags.nullInput &&
+ !flags.invalidFormat &&
+ !flags.userInvalidated &&
+ (!flags.meridiem || (flags.meridiem && parsedParts));
+
+ if (m._strict) {
+ isNowValid = isNowValid &&
+ flags.charsLeftOver === 0 &&
+ flags.unusedTokens.length === 0 &&
+ flags.bigHour === undefined;
+ }
+
+ if (Object.isFrozen == null || !Object.isFrozen(m)) {
+ m._isValid = isNowValid;
+ }
+ else {
+ return isNowValid;
+ }
+ }
+ return m._isValid;
+ }
+
+ function createInvalid (flags) {
+ var m = createUTC(NaN);
+ if (flags != null) {
+ extend(getParsingFlags(m), flags);
+ }
+ else {
+ getParsingFlags(m).userInvalidated = true;
+ }
+
+ return m;
+ }
+
+ // Plugins that add properties should also add the key here (null value),
+ // so we can properly clone ourselves.
+ var momentProperties = hooks.momentProperties = [];
+
+ function copyConfig(to, from) {
+ var i, prop, val;
+
+ if (!isUndefined(from._isAMomentObject)) {
+ to._isAMomentObject = from._isAMomentObject;
+ }
+ if (!isUndefined(from._i)) {
+ to._i = from._i;
+ }
+ if (!isUndefined(from._f)) {
+ to._f = from._f;
+ }
+ if (!isUndefined(from._l)) {
+ to._l = from._l;
+ }
+ if (!isUndefined(from._strict)) {
+ to._strict = from._strict;
+ }
+ if (!isUndefined(from._tzm)) {
+ to._tzm = from._tzm;
+ }
+ if (!isUndefined(from._isUTC)) {
+ to._isUTC = from._isUTC;
+ }
+ if (!isUndefined(from._offset)) {
+ to._offset = from._offset;
+ }
+ if (!isUndefined(from._pf)) {
+ to._pf = getParsingFlags(from);
+ }
+ if (!isUndefined(from._locale)) {
+ to._locale = from._locale;
+ }
+
+ if (momentProperties.length > 0) {
+ for (i = 0; i < momentProperties.length; i++) {
+ prop = momentProperties[i];
+ val = from[prop];
+ if (!isUndefined(val)) {
+ to[prop] = val;
+ }
+ }
+ }
+
+ return to;
+ }
+
+ var updateInProgress = false;
+
+ // Moment prototype object
+ function Moment(config) {
+ copyConfig(this, config);
+ this._d = new Date(config._d != null ? config._d.getTime() : NaN);
+ if (!this.isValid()) {
+ this._d = new Date(NaN);
+ }
+ // Prevent infinite loop in case updateOffset creates new moment
+ // objects.
+ if (updateInProgress === false) {
+ updateInProgress = true;
+ hooks.updateOffset(this);
+ updateInProgress = false;
+ }
+ }
+
+ function isMoment (obj) {
+ return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
+ }
+
+ function absFloor (number) {
+ if (number < 0) {
+ // -0 -> 0
+ return Math.ceil(number) || 0;
+ } else {
+ return Math.floor(number);
+ }
+ }
+
+ function toInt(argumentForCoercion) {
+ var coercedNumber = +argumentForCoercion,
+ value = 0;
+
+ if (coercedNumber !== 0 && isFinite(coercedNumber)) {
+ value = absFloor(coercedNumber);
+ }
+
+ return value;
+ }
+
+ // compare two arrays, return the number of differences
+ function compareArrays(array1, array2, dontConvert) {
+ var len = Math.min(array1.length, array2.length),
+ lengthDiff = Math.abs(array1.length - array2.length),
+ diffs = 0,
+ i;
+ for (i = 0; i < len; i++) {
+ if ((dontConvert && array1[i] !== array2[i]) ||
+ (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
+ diffs++;
+ }
+ }
+ return diffs + lengthDiff;
+ }
+
+ function warn(msg) {
+ if (hooks.suppressDeprecationWarnings === false &&
+ (typeof console !== 'undefined') && console.warn) {
+ console.warn('Deprecation warning: ' + msg);
+ }
+ }
+
+ function deprecate(msg, fn) {
+ var firstTime = true;
+
+ return extend(function () {
+ if (hooks.deprecationHandler != null) {
+ hooks.deprecationHandler(null, msg);
+ }
+ if (firstTime) {
+ var args = [];
+ var arg;
+ for (var i = 0; i < arguments.length; i++) {
+ arg = '';
+ if (typeof arguments[i] === 'object') {
+ arg += '\n[' + i + '] ';
+ for (var key in arguments[0]) {
+ arg += key + ': ' + arguments[0][key] + ', ';
+ }
+ arg = arg.slice(0, -2); // Remove trailing comma and space
+ } else {
+ arg = arguments[i];
+ }
+ args.push(arg);
+ }
+ warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack);
+ firstTime = false;
+ }
+ return fn.apply(this, arguments);
+ }, fn);
+ }
+
+ var deprecations = {};
+
+ function deprecateSimple(name, msg) {
+ if (hooks.deprecationHandler != null) {
+ hooks.deprecationHandler(name, msg);
+ }
+ if (!deprecations[name]) {
+ warn(msg);
+ deprecations[name] = true;
+ }
+ }
+
+ hooks.suppressDeprecationWarnings = false;
+ hooks.deprecationHandler = null;
+
+ function isFunction(input) {
+ return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
+ }
+
+ function set (config) {
+ var prop, i;
+ for (i in config) {
+ prop = config[i];
+ if (isFunction(prop)) {
+ this[i] = prop;
+ } else {
+ this['_' + i] = prop;
+ }
+ }
+ this._config = config;
+ // Lenient ordinal parsing accepts just a number in addition to
+ // number + (possibly) stuff coming from _dayOfMonthOrdinalParse.
+ // TODO: Remove "ordinalParse" fallback in next major release.
+ this._dayOfMonthOrdinalParseLenient = new RegExp(
+ (this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) +
+ '|' + (/\d{1,2}/).source);
+ }
+
+ function mergeConfigs(parentConfig, childConfig) {
+ var res = extend({}, parentConfig), prop;
+ for (prop in childConfig) {
+ if (hasOwnProp(childConfig, prop)) {
+ if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
+ res[prop] = {};
+ extend(res[prop], parentConfig[prop]);
+ extend(res[prop], childConfig[prop]);
+ } else if (childConfig[prop] != null) {
+ res[prop] = childConfig[prop];
+ } else {
+ delete res[prop];
+ }
+ }
+ }
+ for (prop in parentConfig) {
+ if (hasOwnProp(parentConfig, prop) &&
+ !hasOwnProp(childConfig, prop) &&
+ isObject(parentConfig[prop])) {
+ // make sure changes to properties don't modify parent config
+ res[prop] = extend({}, res[prop]);
+ }
+ }
+ return res;
+ }
+
+ function Locale(config) {
+ if (config != null) {
+ this.set(config);
+ }
+ }
+
+ var keys;
+
+ if (Object.keys) {
+ keys = Object.keys;
+ } else {
+ keys = function (obj) {
+ var i, res = [];
+ for (i in obj) {
+ if (hasOwnProp(obj, i)) {
+ res.push(i);
+ }
+ }
+ return res;
+ };
+ }
+
+ var defaultCalendar = {
+ sameDay : '[Today at] LT',
+ nextDay : '[Tomorrow at] LT',
+ nextWeek : 'dddd [at] LT',
+ lastDay : '[Yesterday at] LT',
+ lastWeek : '[Last] dddd [at] LT',
+ sameElse : 'L'
+ };
+
+ function calendar (key, mom, now) {
+ var output = this._calendar[key] || this._calendar['sameElse'];
+ return isFunction(output) ? output.call(mom, now) : output;
+ }
+
+ var defaultLongDateFormat = {
+ LTS : 'h:mm:ss A',
+ LT : 'h:mm A',
+ L : 'MM/DD/YYYY',
+ LL : 'MMMM D, YYYY',
+ LLL : 'MMMM D, YYYY h:mm A',
+ LLLL : 'dddd, MMMM D, YYYY h:mm A'
+ };
+
+ function longDateFormat (key) {
+ var format = this._longDateFormat[key],
+ formatUpper = this._longDateFormat[key.toUpperCase()];
+
+ if (format || !formatUpper) {
+ return format;
+ }
+
+ this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
+ return val.slice(1);
+ });
+
+ return this._longDateFormat[key];
+ }
+
+ var defaultInvalidDate = 'Invalid date';
+
+ function invalidDate () {
+ return this._invalidDate;
+ }
+
+ var defaultOrdinal = '%d';
+ var defaultDayOfMonthOrdinalParse = /\d{1,2}/;
+
+ function ordinal (number) {
+ return this._ordinal.replace('%d', number);
+ }
+
+ var defaultRelativeTime = {
+ future : 'in %s',
+ past : '%s ago',
+ s : 'a few seconds',
+ ss : '%d seconds',
+ m : 'a minute',
+ mm : '%d minutes',
+ h : 'an hour',
+ hh : '%d hours',
+ d : 'a day',
+ dd : '%d days',
+ M : 'a month',
+ MM : '%d months',
+ y : 'a year',
+ yy : '%d years'
+ };
+
+ function relativeTime (number, withoutSuffix, string, isFuture) {
+ var output = this._relativeTime[string];
+ return (isFunction(output)) ?
+ output(number, withoutSuffix, string, isFuture) :
+ output.replace(/%d/i, number);
+ }
+
+ function pastFuture (diff, output) {
+ var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
+ return isFunction(format) ? format(output) : format.replace(/%s/i, output);
+ }
+
+ var aliases = {};
+
+ function addUnitAlias (unit, shorthand) {
+ var lowerCase = unit.toLowerCase();
+ aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
+ }
+
+ function normalizeUnits(units) {
+ return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
+ }
+
+ function normalizeObjectUnits(inputObject) {
+ var normalizedInput = {},
+ normalizedProp,
+ prop;
+
+ for (prop in inputObject) {
+ if (hasOwnProp(inputObject, prop)) {
+ normalizedProp = normalizeUnits(prop);
+ if (normalizedProp) {
+ normalizedInput[normalizedProp] = inputObject[prop];
+ }
+ }
+ }
+
+ return normalizedInput;
+ }
+
+ var priorities = {};
+
+ function addUnitPriority(unit, priority) {
+ priorities[unit] = priority;
+ }
+
+ function getPrioritizedUnits(unitsObj) {
+ var units = [];
+ for (var u in unitsObj) {
+ units.push({unit: u, priority: priorities[u]});
+ }
+ units.sort(function (a, b) {
+ return a.priority - b.priority;
+ });
+ return units;
+ }
+
+ function zeroFill(number, targetLength, forceSign) {
+ var absNumber = '' + Math.abs(number),
+ zerosToFill = targetLength - absNumber.length,
+ sign = number >= 0;
+ return (sign ? (forceSign ? '+' : '') : '-') +
+ Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
+ }
+
+ var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
+
+ var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
+
+ var formatFunctions = {};
+
+ var formatTokenFunctions = {};
+
+ // token: 'M'
+ // padded: ['MM', 2]
+ // ordinal: 'Mo'
+ // callback: function () { this.month() + 1 }
+ function addFormatToken (token, padded, ordinal, callback) {
+ var func = callback;
+ if (typeof callback === 'string') {
+ func = function () {
+ return this[callback]();
+ };
+ }
+ if (token) {
+ formatTokenFunctions[token] = func;
+ }
+ if (padded) {
+ formatTokenFunctions[padded[0]] = function () {
+ return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
+ };
+ }
+ if (ordinal) {
+ formatTokenFunctions[ordinal] = function () {
+ return this.localeData().ordinal(func.apply(this, arguments), token);
+ };
+ }
+ }
+
+ function removeFormattingTokens(input) {
+ if (input.match(/\[[\s\S]/)) {
+ return input.replace(/^\[|\]$/g, '');
+ }
+ return input.replace(/\\/g, '');
+ }
+
+ function makeFormatFunction(format) {
+ var array = format.match(formattingTokens), i, length;
+
+ for (i = 0, length = array.length; i < length; i++) {
+ if (formatTokenFunctions[array[i]]) {
+ array[i] = formatTokenFunctions[array[i]];
+ } else {
+ array[i] = removeFormattingTokens(array[i]);
+ }
+ }
+
+ return function (mom) {
+ var output = '', i;
+ for (i = 0; i < length; i++) {
+ output += isFunction(array[i]) ? array[i].call(mom, format) : array[i];
+ }
+ return output;
+ };
+ }
+
+ // format date using native date object
+ function formatMoment(m, format) {
+ if (!m.isValid()) {
+ return m.localeData().invalidDate();
+ }
+
+ format = expandFormat(format, m.localeData());
+ formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
+
+ return formatFunctions[format](m);
+ }
+
+ function expandFormat(format, locale) {
+ var i = 5;
+
+ function replaceLongDateFormatTokens(input) {
+ return locale.longDateFormat(input) || input;
+ }
+
+ localFormattingTokens.lastIndex = 0;
+ while (i >= 0 && localFormattingTokens.test(format)) {
+ format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
+ localFormattingTokens.lastIndex = 0;
+ i -= 1;
+ }
+
+ return format;
+ }
+
+ var match1 = /\d/; // 0 - 9
+ var match2 = /\d\d/; // 00 - 99
+ var match3 = /\d{3}/; // 000 - 999
+ var match4 = /\d{4}/; // 0000 - 9999
+ var match6 = /[+-]?\d{6}/; // -999999 - 999999
+ var match1to2 = /\d\d?/; // 0 - 99
+ var match3to4 = /\d\d\d\d?/; // 999 - 9999
+ var match5to6 = /\d\d\d\d\d\d?/; // 99999 - 999999
+ var match1to3 = /\d{1,3}/; // 0 - 999
+ var match1to4 = /\d{1,4}/; // 0 - 9999
+ var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999
+
+ var matchUnsigned = /\d+/; // 0 - inf
+ var matchSigned = /[+-]?\d+/; // -inf - inf
+
+ var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
+ var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
+
+ var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
+
+ // any word (or two) characters or numbers including two/three word month in arabic.
+ // includes scottish gaelic two word and hyphenated months
+ var matchWord = /[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i;
+
+ var regexes = {};
+
+ function addRegexToken (token, regex, strictRegex) {
+ regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
+ return (isStrict && strictRegex) ? strictRegex : regex;
+ };
+ }
+
+ function getParseRegexForToken (token, config) {
+ if (!hasOwnProp(regexes, token)) {
+ return new RegExp(unescapeFormat(token));
+ }
+
+ return regexes[token](config._strict, config._locale);
+ }
+
+ // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
+ function unescapeFormat(s) {
+ return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
+ return p1 || p2 || p3 || p4;
+ }));
+ }
+
+ function regexEscape(s) {
+ return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
+ }
+
+ var tokens = {};
+
+ function addParseToken (token, callback) {
+ var i, func = callback;
+ if (typeof token === 'string') {
+ token = [token];
+ }
+ if (isNumber(callback)) {
+ func = function (input, array) {
+ array[callback] = toInt(input);
+ };
+ }
+ for (i = 0; i < token.length; i++) {
+ tokens[token[i]] = func;
+ }
+ }
+
+ function addWeekParseToken (token, callback) {
+ addParseToken(token, function (input, array, config, token) {
+ config._w = config._w || {};
+ callback(input, config._w, config, token);
+ });
+ }
+
+ function addTimeToArrayFromToken(token, input, config) {
+ if (input != null && hasOwnProp(tokens, token)) {
+ tokens[token](input, config._a, config, token);
+ }
+ }
+
+ var YEAR = 0;
+ var MONTH = 1;
+ var DATE = 2;
+ var HOUR = 3;
+ var MINUTE = 4;
+ var SECOND = 5;
+ var MILLISECOND = 6;
+ var WEEK = 7;
+ var WEEKDAY = 8;
+
+ // FORMATTING
+
+ addFormatToken('Y', 0, 0, function () {
+ var y = this.year();
+ return y <= 9999 ? '' + y : '+' + y;
+ });
+
+ addFormatToken(0, ['YY', 2], 0, function () {
+ return this.year() % 100;
+ });
+
+ addFormatToken(0, ['YYYY', 4], 0, 'year');
+ addFormatToken(0, ['YYYYY', 5], 0, 'year');
+ addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
+
+ // ALIASES
+
+ addUnitAlias('year', 'y');
+
+ // PRIORITIES
+
+ addUnitPriority('year', 1);
+
+ // PARSING
+
+ addRegexToken('Y', matchSigned);
+ addRegexToken('YY', match1to2, match2);
+ addRegexToken('YYYY', match1to4, match4);
+ addRegexToken('YYYYY', match1to6, match6);
+ addRegexToken('YYYYYY', match1to6, match6);
+
+ addParseToken(['YYYYY', 'YYYYYY'], YEAR);
+ addParseToken('YYYY', function (input, array) {
+ array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
+ });
+ addParseToken('YY', function (input, array) {
+ array[YEAR] = hooks.parseTwoDigitYear(input);
+ });
+ addParseToken('Y', function (input, array) {
+ array[YEAR] = parseInt(input, 10);
+ });
+
+ // HELPERS
+
+ function daysInYear(year) {
+ return isLeapYear(year) ? 366 : 365;
+ }
+
+ function isLeapYear(year) {
+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
+ }
+
+ // HOOKS
+
+ hooks.parseTwoDigitYear = function (input) {
+ return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
+ };
+
+ // MOMENTS
+
+ var getSetYear = makeGetSet('FullYear', true);
+
+ function getIsLeapYear () {
+ return isLeapYear(this.year());
+ }
+
+ function makeGetSet (unit, keepTime) {
+ return function (value) {
+ if (value != null) {
+ set$1(this, unit, value);
+ hooks.updateOffset(this, keepTime);
+ return this;
+ } else {
+ return get(this, unit);
+ }
+ };
+ }
+
+ function get (mom, unit) {
+ return mom.isValid() ?
+ mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
+ }
+
+ function set$1 (mom, unit, value) {
+ if (mom.isValid() && !isNaN(value)) {
+ if (unit === 'FullYear' && isLeapYear(mom.year()) && mom.month() === 1 && mom.date() === 29) {
+ mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value, mom.month(), daysInMonth(value, mom.month()));
+ }
+ else {
+ mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
+ }
+ }
+ }
+
+ // MOMENTS
+
+ function stringGet (units) {
+ units = normalizeUnits(units);
+ if (isFunction(this[units])) {
+ return this[units]();
+ }
+ return this;
+ }
+
+
+ function stringSet (units, value) {
+ if (typeof units === 'object') {
+ units = normalizeObjectUnits(units);
+ var prioritized = getPrioritizedUnits(units);
+ for (var i = 0; i < prioritized.length; i++) {
+ this[prioritized[i].unit](units[prioritized[i].unit]);
+ }
+ } else {
+ units = normalizeUnits(units);
+ if (isFunction(this[units])) {
+ return this[units](value);
+ }
+ }
+ return this;
+ }
+
+ function mod(n, x) {
+ return ((n % x) + x) % x;
+ }
+
+ var indexOf;
+
+ if (Arr