(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 (Array.prototype.indexOf) {
        indexOf = Array.prototype.indexOf;
    } else {
        indexOf = function (o) {
            // I know
            var i;
            for (i = 0; i < this.length; ++i) {
                if (this[i] === o) {
                    return i;
                }
            }
            return -1;
        };
    }

    function daysInMonth(year, month) {
        if (isNaN(year) || isNaN(month)) {
            return NaN;
        }
        var modMonth = mod(month, 12);
        year += (month - modMonth) / 12;
        return modMonth === 1 ? (isLeapYear(year) ? 29 : 28) : (31 - modMonth % 7 % 2);
    }

    // FORMATTING

    addFormatToken('M', ['MM', 2], 'Mo', function () {
        return this.month() + 1;
    });

    addFormatToken('MMM', 0, 0, function (format) {
        return this.localeData().monthsShort(this, format);
    });

    addFormatToken('MMMM', 0, 0, function (format) {
        return this.localeData().months(this, format);
    });

    // ALIASES

    addUnitAlias('month', 'M');

    // PRIORITY

    addUnitPriority('month', 8);

    // PARSING

    addRegexToken('M',    match1to2);
    addRegexToken('MM',   match1to2, match2);
    addRegexToken('MMM',  function (isStrict, locale) {
        return locale.monthsShortRegex(isStrict);
    });
    addRegexToken('MMMM', function (isStrict, locale) {
        return locale.monthsRegex(isStrict);
    });

    addParseToken(['M', 'MM'], function (input, array) {
        array[MONTH] = toInt(input) - 1;
    });

    addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
        var month = config._locale.monthsParse(input, token, config._strict);
        // if we didn't find a month name, mark the date as invalid.
        if (month != null) {
            array[MONTH] = month;
        } else {
            getParsingFlags(config).invalidMonth = input;
        }
    });

    // LOCALES

    var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/;
    var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
    function localeMonths (m, format) {
        if (!m) {
            return isArray(this._months) ? this._months :
                this._months['standalone'];
        }
        return isArray(this._months) ? this._months[m.month()] :
            this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()];
    }

    var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
    function localeMonthsShort (m, format) {
        if (!m) {
            return isArray(this._monthsShort) ? this._monthsShort :
                this._monthsShort['standalone'];
        }
        return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
            this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
    }

    function handleStrictParse(monthName, format, strict) {
        var i, ii, mom, llc = monthName.toLocaleLowerCase();
        if (!this._monthsParse) {
            // this is not used
            this._monthsParse = [];
            this._longMonthsParse = [];
            this._shortMonthsParse = [];
            for (i = 0; i < 12; ++i) {
                mom = createUTC([2000, i]);
                this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
                this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
            }
        }

        if (strict) {
            if (format === 'MMM') {
                ii = indexOf.call(this._shortMonthsParse, llc);
                return ii !== -1 ? ii : null;
            } else {
                ii = indexOf.call(this._longMonthsParse, llc);
                return ii !== -1 ? ii : null;
            }
        } else {
            if (format === 'MMM') {
                ii = indexOf.call(this._shortMonthsParse, llc);
                if (ii !== -1) {
                    return ii;
                }
                ii = indexOf.call(this._longMonthsParse, llc);
                return ii !== -1 ? ii : null;
            } else {
                ii = indexOf.call(this._longMonthsParse, llc);
                if (ii !== -1) {
                    return ii;
                }
                ii = indexOf.call(this._shortMonthsParse, llc);
                return ii !== -1 ? ii : null;
            }
        }
    }

    function localeMonthsParse (monthName, format, strict) {
        var i, mom, regex;

        if (this._monthsParseExact) {
            return handleStrictParse.call(this, monthName, format, strict);
        }

        if (!this._monthsParse) {
            this._monthsParse = [];
            this._longMonthsParse = [];
            this._shortMonthsParse = [];
        }

        // TODO: add sorting
        // Sorting makes sure if one month (or abbr) is a prefix of another
        // see sorting in computeMonthsParse
        for (i = 0; i < 12; i++) {
            // make the regex if we don't have it already
            mom = createUTC([2000, i]);
            if (strict && !this._longMonthsParse[i]) {
                this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
                this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
            }
            if (!strict && !this._monthsParse[i]) {
                regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
                this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
            }
            // test the regex
            if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
                return i;
            } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
                return i;
            } else if (!strict && this._monthsParse[i].test(monthName)) {
                return i;
            }
        }
    }

    // MOMENTS

    function setMonth (mom, value) {
        var dayOfMonth;

        if (!mom.isValid()) {
            // No op
            return mom;
        }

        if (typeof value === 'string') {
            if (/^\d+$/.test(value)) {
                value = toInt(value);
            } else {
                value = mom.localeData().monthsParse(value);
                // TODO: Another silent failure?
                if (!isNumber(value)) {
                    return mom;
                }
            }
        }

        dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
        mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
        return mom;
    }

    function getSetMonth (value) {
        if (value != null) {
            setMonth(this, value);
            hooks.updateOffset(this, true);
            return this;
        } else {
            return get(this, 'Month');
        }
    }

    function getDaysInMonth () {
        return daysInMonth(this.year(), this.month());
    }

    var defaultMonthsShortRegex = matchWord;
    function monthsShortRegex (isStrict) {
        if (this._monthsParseExact) {
            if (!hasOwnProp(this, '_monthsRegex')) {
                computeMonthsParse.call(this);
            }
            if (isStrict) {
                return this._monthsShortStrictRegex;
            } else {
                return this._monthsShortRegex;
            }
        } else {
            if (!hasOwnProp(this, '_monthsShortRegex')) {
                this._monthsShortRegex = defaultMonthsShortRegex;
            }
            return this._monthsShortStrictRegex && isStrict ?
                this._monthsShortStrictRegex : this._monthsShortRegex;
        }
    }

    var defaultMonthsRegex = matchWord;
    function monthsRegex (isStrict) {
        if (this._monthsParseExact) {
            if (!hasOwnProp(this, '_monthsRegex')) {
                computeMonthsParse.call(this);
            }
            if (isStrict) {
                return this._monthsStrictRegex;
            } else {
                return this._monthsRegex;
            }
        } else {
            if (!hasOwnProp(this, '_monthsRegex')) {
                this._monthsRegex = defaultMonthsRegex;
            }
            return this._monthsStrictRegex && isStrict ?
                this._monthsStrictRegex : this._monthsRegex;
        }
    }

    function computeMonthsParse () {
        function cmpLenRev(a, b) {
            return b.length - a.length;
        }

        var shortPieces = [], longPieces = [], mixedPieces = [],
            i, mom;
        for (i = 0; i < 12; i++) {
            // make the regex if we don't have it already
            mom = createUTC([2000, i]);
            shortPieces.push(this.monthsShort(mom, ''));
            longPieces.push(this.months(mom, ''));
            mixedPieces.push(this.months(mom, ''));
            mixedPieces.push(this.monthsShort(mom, ''));
        }
        // Sorting makes sure if one month (or abbr) is a prefix of another it
        // will match the longer piece.
        shortPieces.sort(cmpLenRev);
        longPieces.sort(cmpLenRev);
        mixedPieces.sort(cmpLenRev);
        for (i = 0; i < 12; i++) {
            shortPieces[i] = regexEscape(shortPieces[i]);
            longPieces[i] = regexEscape(longPieces[i]);
        }
        for (i = 0; i < 24; i++) {
            mixedPieces[i] = regexEscape(mixedPieces[i]);
        }

        this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
        this._monthsShortRegex = this._monthsRegex;
        this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
        this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
    }

    function createDate (y, m, d, h, M, s, ms) {
        // can't just apply() to create a date:
        // https://stackoverflow.com/q/181348
        var date;
        // the date constructor remaps years 0-99 to 1900-1999
        if (y < 100 && y >= 0) {
            // preserve leap years using a full 400 year cycle, then reset
            date = new Date(y + 400, m, d, h, M, s, ms);
            if (isFinite(date.getFullYear())) {
                date.setFullYear(y);
            }
        } else {
            date = new Date(y, m, d, h, M, s, ms);
        }

        return date;
    }

    function createUTCDate (y) {
        var date;
        // the Date.UTC function remaps years 0-99 to 1900-1999
        if (y < 100 && y >= 0) {
            var args = Array.prototype.slice.call(arguments);
            // preserve leap years using a full 400 year cycle, then reset
            args[0] = y + 400;
            date = new Date(Date.UTC.apply(null, args));
            if (isFinite(date.getUTCFullYear())) {
                date.setUTCFullYear(y);
            }
        } else {
            date = new Date(Date.UTC.apply(null, arguments));
        }

        return date;
    }

    // start-of-first-week - start-of-year
    function firstWeekOffset(year, dow, doy) {
        var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
            fwd = 7 + dow - doy,
            // first-week day local weekday -- which local weekday is fwd
            fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;

        return -fwdlw + fwd - 1;
    }

    // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
    function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
        var localWeekday = (7 + weekday - dow) % 7,
            weekOffset = firstWeekOffset(year, dow, doy),
            dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
            resYear, resDayOfYear;

        if (dayOfYear <= 0) {
            resYear = year - 1;
            resDayOfYear = daysInYear(resYear) + dayOfYear;
        } else if (dayOfYear > daysInYear(year)) {
            resYear = year + 1;
            resDayOfYear = dayOfYear - daysInYear(year);
        } else {
            resYear = year;
            resDayOfYear = dayOfYear;
        }

        return {
            year: resYear,
            dayOfYear: resDayOfYear
        };
    }

    function weekOfYear(mom, dow, doy) {
        var weekOffset = firstWeekOffset(mom.year(), dow, doy),
            week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
            resWeek, resYear;

        if (week < 1) {
            resYear = mom.year() - 1;
            resWeek = week + weeksInYear(resYear, dow, doy);
        } else if (week > weeksInYear(mom.year(), dow, doy)) {
            resWeek = week - weeksInYear(mom.year(), dow, doy);
            resYear = mom.year() + 1;
        } else {
            resYear = mom.year();
            resWeek = week;
        }

        return {
            week: resWeek,
            year: resYear
        };
    }

    function weeksInYear(year, dow, doy) {
        var weekOffset = firstWeekOffset(year, dow, doy),
            weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
        return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
    }

    // FORMATTING

    addFormatToken('w', ['ww', 2], 'wo', 'week');
    addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');

    // ALIASES

    addUnitAlias('week', 'w');
    addUnitAlias('isoWeek', 'W');

    // PRIORITIES

    addUnitPriority('week', 5);
    addUnitPriority('isoWeek', 5);

    // PARSING

    addRegexToken('w',  match1to2);
    addRegexToken('ww', match1to2, match2);
    addRegexToken('W',  match1to2);
    addRegexToken('WW', match1to2, match2);

    addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
        week[token.substr(0, 1)] = toInt(input);
    });

    // HELPERS

    // LOCALES

    function localeWeek (mom) {
        return weekOfYear(mom, this._week.dow, this._week.doy).week;
    }

    var defaultLocaleWeek = {
        dow : 0, // Sunday is the first day of the week.
        doy : 6  // The week that contains Jan 6th is the first week of the year.
    };

    function localeFirstDayOfWeek () {
        return this._week.dow;
    }

    function localeFirstDayOfYear () {
        return this._week.doy;
    }

    // MOMENTS

    function getSetWeek (input) {
        var week = this.localeData().week(this);
        return input == null ? week : this.add((input - week) * 7, 'd');
    }

    function getSetISOWeek (input) {
        var week = weekOfYear(this, 1, 4).week;
        return input == null ? week : this.add((input - week) * 7, 'd');
    }

    // FORMATTING

    addFormatToken('d', 0, 'do', 'day');

    addFormatToken('dd', 0, 0, function (format) {
        return this.localeData().weekdaysMin(this, format);
    });

    addFormatToken('ddd', 0, 0, function (format) {
        return this.localeData().weekdaysShort(this, format);
    });

    addFormatToken('dddd', 0, 0, function (format) {
        return this.localeData().weekdays(this, format);
    });

    addFormatToken('e', 0, 0, 'weekday');
    addFormatToken('E', 0, 0, 'isoWeekday');

    // ALIASES

    addUnitAlias('day', 'd');
    addUnitAlias('weekday', 'e');
    addUnitAlias('isoWeekday', 'E');

    // PRIORITY
    addUnitPriority('day', 11);
    addUnitPriority('weekday', 11);
    addUnitPriority('isoWeekday', 11);

    // PARSING

    addRegexToken('d',    match1to2);
    addRegexToken('e',    match1to2);
    addRegexToken('E',    match1to2);
    addRegexToken('dd',   function (isStrict, locale) {
        return locale.weekdaysMinRegex(isStrict);
    });
    addRegexToken('ddd',   function (isStrict, locale) {
        return locale.weekdaysShortRegex(isStrict);
    });
    addRegexToken('dddd',   function (isStrict, locale) {
        return locale.weekdaysRegex(isStrict);
    });

    addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
        var weekday = config._locale.weekdaysParse(input, token, config._strict);
        // if we didn't get a weekday name, mark the date as invalid
        if (weekday != null) {
            week.d = weekday;
        } else {
            getParsingFlags(config).invalidWeekday = input;
        }
    });

    addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
        week[token] = toInt(input);
    });

    // HELPERS

    function parseWeekday(input, locale) {
        if (typeof input !== 'string') {
            return input;
        }

        if (!isNaN(input)) {
            return parseInt(input, 10);
        }

        input = locale.weekdaysParse(input);
        if (typeof input === 'number') {
            return input;
        }

        return null;
    }

    function parseIsoWeekday(input, locale) {
        if (typeof input === 'string') {
            return locale.weekdaysParse(input) % 7 || 7;
        }
        return isNaN(input) ? null : input;
    }

    // LOCALES
    function shiftWeekdays (ws, n) {
        return ws.slice(n, 7).concat(ws.slice(0, n));
    }

    var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
    function localeWeekdays (m, format) {
        var weekdays = isArray(this._weekdays) ? this._weekdays :
            this._weekdays[(m && m !== true && this._weekdays.isFormat.test(format)) ? 'format' : 'standalone'];
        return (m === true) ? shiftWeekdays(weekdays, this._week.dow)
            : (m) ? weekdays[m.day()] : weekdays;
    }

    var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
    function localeWeekdaysShort (m) {
        return (m === true) ? shiftWeekdays(this._weekdaysShort, this._week.dow)
            : (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort;
    }

    var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
    function localeWeekdaysMin (m) {
        return (m === true) ? shiftWeekdays(this._weekdaysMin, this._week.dow)
            : (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin;
    }

    function handleStrictParse$1(weekdayName, format, strict) {
        var i, ii, mom, llc = weekdayName.toLocaleLowerCase();
        if (!this._weekdaysParse) {
            this._weekdaysParse = [];
            this._shortWeekdaysParse = [];
            this._minWeekdaysParse = [];

            for (i = 0; i < 7; ++i) {
                mom = createUTC([2000, 1]).day(i);
                this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
                this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
                this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
            }
        }

        if (strict) {
            if (format === 'dddd') {
                ii = indexOf.call(this._weekdaysParse, llc);
                return ii !== -1 ? ii : null;
            } else if (format === 'ddd') {
                ii = indexOf.call(this._shortWeekdaysParse, llc);
                return ii !== -1 ? ii : null;
            } else {
                ii = indexOf.call(this._minWeekdaysParse, llc);
                return ii !== -1 ? ii : null;
            }
        } else {
            if (format === 'dddd') {
                ii = indexOf.call(this._weekdaysParse, llc);
                if (ii !== -1) {
                    return ii;
                }
                ii = indexOf.call(this._shortWeekdaysParse, llc);
                if (ii !== -1) {
                    return ii;
                }
                ii = indexOf.call(this._minWeekdaysParse, llc);
                return ii !== -1 ? ii : null;
            } else if (format === 'ddd') {
                ii = indexOf.call(this._shortWeekdaysParse, llc);
                if (ii !== -1) {
                    return ii;
                }
                ii = indexOf.call(this._weekdaysParse, llc);
                if (ii !== -1) {
                    return ii;
                }
                ii = indexOf.call(this._minWeekdaysParse, llc);
                return ii !== -1 ? ii : null;
            } else {
                ii = indexOf.call(this._minWeekdaysParse, llc);
                if (ii !== -1) {
                    return ii;
                }
                ii = indexOf.call(this._weekdaysParse, llc);
                if (ii !== -1) {
                    return ii;
                }
                ii = indexOf.call(this._shortWeekdaysParse, llc);
                return ii !== -1 ? ii : null;
            }
        }
    }

    function localeWeekdaysParse (weekdayName, format, strict) {
        var i, mom, regex;

        if (this._weekdaysParseExact) {
            return handleStrictParse$1.call(this, weekdayName, format, strict);
        }

        if (!this._weekdaysParse) {
            this._weekdaysParse = [];
            this._minWeekdaysParse = [];
            this._shortWeekdaysParse = [];
            this._fullWeekdaysParse = [];
        }

        for (i = 0; i < 7; i++) {
            // make the regex if we don't have it already

            mom = createUTC([2000, 1]).day(i);
            if (strict && !this._fullWeekdaysParse[i]) {
                this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\\.?') + '$', 'i');
                this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\\.?') + '$', 'i');
                this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\\.?') + '$', 'i');
            }
            if (!this._weekdaysParse[i]) {
                regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
                this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
            }
            // test the regex
            if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
                return i;
            } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
                return i;
            } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
                return i;
            } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
                return i;
            }
        }
    }

    // MOMENTS

    function getSetDayOfWeek (input) {
        if (!this.isValid()) {
            return input != null ? this : NaN;
        }
        var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
        if (input != null) {
            input = parseWeekday(input, this.localeData());
            return this.add(input - day, 'd');
        } else {
            return day;
        }
    }

    function getSetLocaleDayOfWeek (input) {
        if (!this.isValid()) {
            return input != null ? this : NaN;
        }
        var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
        return input == null ? weekday : this.add(input - weekday, 'd');
    }

    function getSetISODayOfWeek (input) {
        if (!this.isValid()) {
            return input != null ? this : NaN;
        }

        // behaves the same as moment#day except
        // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
        // as a setter, sunday should belong to the previous week.

        if (input != null) {
            var weekday = parseIsoWeekday(input, this.localeData());
            return this.day(this.day() % 7 ? weekday : weekday - 7);
        } else {
            return this.day() || 7;
        }
    }

    var defaultWeekdaysRegex = matchWord;
    function weekdaysRegex (isStrict) {
        if (this._weekdaysParseExact) {
            if (!hasOwnProp(this, '_weekdaysRegex')) {
                computeWeekdaysParse.call(this);
            }
            if (isStrict) {
                return this._weekdaysStrictRegex;
            } else {
                return this._weekdaysRegex;
            }
        } else {
            if (!hasOwnProp(this, '_weekdaysRegex')) {
                this._weekdaysRegex = defaultWeekdaysRegex;
            }
            return this._weekdaysStrictRegex && isStrict ?
                this._weekdaysStrictRegex : this._weekdaysRegex;
        }
    }

    var defaultWeekdaysShortRegex = matchWord;
    function weekdaysShortRegex (isStrict) {
        if (this._weekdaysParseExact) {
            if (!hasOwnProp(this, '_weekdaysRegex')) {
                computeWeekdaysParse.call(this);
            }
            if (isStrict) {
                return this._weekdaysShortStrictRegex;
            } else {
                return this._weekdaysShortRegex;
            }
        } else {
            if (!hasOwnProp(this, '_weekdaysShortRegex')) {
                this._weekdaysShortRegex = defaultWeekdaysShortRegex;
            }
            return this._weekdaysShortStrictRegex && isStrict ?
                this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
        }
    }

    var defaultWeekdaysMinRegex = matchWord;
    function weekdaysMinRegex (isStrict) {
        if (this._weekdaysParseExact) {
            if (!hasOwnProp(this, '_weekdaysRegex')) {
                computeWeekdaysParse.call(this);
            }
            if (isStrict) {
                return this._weekdaysMinStrictRegex;
            } else {
                return this._weekdaysMinRegex;
            }
        } else {
            if (!hasOwnProp(this, '_weekdaysMinRegex')) {
                this._weekdaysMinRegex = defaultWeekdaysMinRegex;
            }
            return this._weekdaysMinStrictRegex && isStrict ?
                this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
        }
    }


    function computeWeekdaysParse () {
        function cmpLenRev(a, b) {
            return b.length - a.length;
        }

        var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [],
            i, mom, minp, shortp, longp;
        for (i = 0; i < 7; i++) {
            // make the regex if we don't have it already
            mom = createUTC([2000, 1]).day(i);
            minp = this.weekdaysMin(mom, '');
            shortp = this.weekdaysShort(mom, '');
            longp = this.weekdays(mom, '');
            minPieces.push(minp);
            shortPieces.push(shortp);
            longPieces.push(longp);
            mixedPieces.push(minp);
            mixedPieces.push(shortp);
            mixedPieces.push(longp);
        }
        // Sorting makes sure if one weekday (or abbr) is a prefix of another it
        // will match the longer piece.
        minPieces.sort(cmpLenRev);
        shortPieces.sort(cmpLenRev);
        longPieces.sort(cmpLenRev);
        mixedPieces.sort(cmpLenRev);
        for (i = 0; i < 7; i++) {
            shortPieces[i] = regexEscape(shortPieces[i]);
            longPieces[i] = regexEscape(longPieces[i]);
            mixedPieces[i] = regexEscape(mixedPieces[i]);
        }

        this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
        this._weekdaysShortRegex = this._weekdaysRegex;
        this._weekdaysMinRegex = this._weekdaysRegex;

        this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
        this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
        this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
    }

    // FORMATTING

    function hFormat() {
        return this.hours() % 12 || 12;
    }

    function kFormat() {
        return this.hours() || 24;
    }

    addFormatToken('H', ['HH', 2], 0, 'hour');
    addFormatToken('h', ['hh', 2], 0, hFormat);
    addFormatToken('k', ['kk', 2], 0, kFormat);

    addFormatToken('hmm', 0, 0, function () {
        return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
    });

    addFormatToken('hmmss', 0, 0, function () {
        return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
            zeroFill(this.seconds(), 2);
    });

    addFormatToken('Hmm', 0, 0, function () {
        return '' + this.hours() + zeroFill(this.minutes(), 2);
    });

    addFormatToken('Hmmss', 0, 0, function () {
        return '' + this.hours() + zeroFill(this.minutes(), 2) +
            zeroFill(this.seconds(), 2);
    });

    function meridiem (token, lowercase) {
        addFormatToken(token, 0, 0, function () {
            return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
        });
    }

    meridiem('a', true);
    meridiem('A', false);

    // ALIASES

    addUnitAlias('hour', 'h');

    // PRIORITY
    addUnitPriority('hour', 13);

    // PARSING

    function matchMeridiem (isStrict, locale) {
        return locale._meridiemParse;
    }

    addRegexToken('a',  matchMeridiem);
    addRegexToken('A',  matchMeridiem);
    addRegexToken('H',  match1to2);
    addRegexToken('h',  match1to2);
    addRegexToken('k',  match1to2);
    addRegexToken('HH', match1to2, match2);
    addRegexToken('hh', match1to2, match2);
    addRegexToken('kk', match1to2, match2);

    addRegexToken('hmm', match3to4);
    addRegexToken('hmmss', match5to6);
    addRegexToken('Hmm', match3to4);
    addRegexToken('Hmmss', match5to6);

    addParseToken(['H', 'HH'], HOUR);
    addParseToken(['k', 'kk'], function (input, array, config) {
        var kInput = toInt(input);
        array[HOUR] = kInput === 24 ? 0 : kInput;
    });
    addParseToken(['a', 'A'], function (input, array, config) {
        config._isPm = config._locale.isPM(input);
        config._meridiem = input;
    });
    addParseToken(['h', 'hh'], function (input, array, config) {
        array[HOUR] = toInt(input);
        getParsingFlags(config).bigHour = true;
    });
    addParseToken('hmm', function (input, array, config) {
        var pos = input.length - 2;
        array[HOUR] = toInt(input.substr(0, pos));
        array[MINUTE] = toInt(input.substr(pos));
        getParsingFlags(config).bigHour = true;
    });
    addParseToken('hmmss', function (input, array, config) {
        var pos1 = input.length - 4;
        var pos2 = input.length - 2;
        array[HOUR] = toInt(input.substr(0, pos1));
        array[MINUTE] = toInt(input.substr(pos1, 2));
        array[SECOND] = toInt(input.substr(pos2));
        getParsingFlags(config).bigHour = true;
    });
    addParseToken('Hmm', function (input, array, config) {
        var pos = input.length - 2;
        array[HOUR] = toInt(input.substr(0, pos));
        array[MINUTE] = toInt(input.substr(pos));
    });
    addParseToken('Hmmss', function (input, array, config) {
        var pos1 = input.length - 4;
        var pos2 = input.length - 2;
        array[HOUR] = toInt(input.substr(0, pos1));
        array[MINUTE] = toInt(input.substr(pos1, 2));
        array[SECOND] = toInt(input.substr(pos2));
    });

    // LOCALES

    function localeIsPM (input) {
        // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
        // Using charAt should be more compatible.
        return ((input + '').toLowerCase().charAt(0) === 'p');
    }

    var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
    function localeMeridiem (hours, minutes, isLower) {
        if (hours > 11) {
            return isLower ? 'pm' : 'PM';
        } else {
            return isLower ? 'am' : 'AM';
        }
    }


    // MOMENTS

    // Setting the hour should keep the time, because the user explicitly
    // specified which hour they want. So trying to maintain the same hour (in
    // a new timezone) makes sense. Adding/subtracting hours does not follow
    // this rule.
    var getSetHour = makeGetSet('Hours', true);

    var baseConfig = {
        calendar: defaultCalendar,
        longDateFormat: defaultLongDateFormat,
        invalidDate: defaultInvalidDate,
        ordinal: defaultOrdinal,
        dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
        relativeTime: defaultRelativeTime,

        months: defaultLocaleMonths,
        monthsShort: defaultLocaleMonthsShort,

        week: defaultLocaleWeek,

        weekdays: defaultLocaleWeekdays,
        weekdaysMin: defaultLocaleWeekdaysMin,
        weekdaysShort: defaultLocaleWeekdaysShort,

        meridiemParse: defaultLocaleMeridiemParse
    };

    // internal storage for locale config files
    var locales = {};
    var localeFamilies = {};
    var globalLocale;

    function normalizeLocale(key) {
        return key ? key.toLowerCase().replace('_', '-') : key;
    }

    // pick the locale from the array
    // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
    // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
    function chooseLocale(names) {
        var i = 0, j, next, locale, split;

        while (i < names.length) {
            split = normalizeLocale(names[i]).split('-');
            j = split.length;
            next = normalizeLocale(names[i + 1]);
            next = next ? next.split('-') : null;
            while (j > 0) {
                locale = loadLocale(split.slice(0, j).join('-'));
                if (locale) {
                    return locale;
                }
                if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
                    //the next array item is better than a shallower substring of this one
                    break;
                }
                j--;
            }
            i++;
        }
        return globalLocale;
    }

    function loadLocale(name) {
        var oldLocale = null;
        // TODO: Find a better way to register and load all the locales in Node
        if (!locales[name] && (typeof module !== 'undefined') &&
                module && module.exports) {
            try {
                oldLocale = globalLocale._abbr;
                var aliasedRequire = require;
                aliasedRequire('./locale/' + name);
                getSetGlobalLocale(oldLocale);
            } catch (e) {}
        }
        return locales[name];
    }

    // This function will load locale and then set the global locale.  If
    // no arguments are passed in, it will simply return the current global
    // locale key.
    function getSetGlobalLocale (key, values) {
        var data;
        if (key) {
            if (isUndefined(values)) {
                data = getLocale(key);
            }
            else {
                data = defineLocale(key, values);
            }

            if (data) {
                // moment.duration._locale = moment._locale = data;
                globalLocale = data;
            }
            else {
                if ((typeof console !==  'undefined') && console.warn) {
                    //warn user if arguments are passed but the locale could not be set
                    console.warn('Locale ' + key +  ' not found. Did you forget to load it?');
                }
            }
        }

        return globalLocale._abbr;
    }

    function defineLocale (name, config) {
        if (config !== null) {
            var locale, parentConfig = baseConfig;
            config.abbr = name;
            if (locales[name] != null) {
                deprecateSimple('defineLocaleOverride',
                        'use moment.updateLocale(localeName, config) to change ' +
                        'an existing locale. moment.defineLocale(localeName, ' +
                        'config) should only be used for creating a new locale ' +
                        'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
                parentConfig = locales[name]._config;
            } else if (config.parentLocale != null) {
                if (locales[config.parentLocale] != null) {
                    parentConfig = locales[config.parentLocale]._config;
                } else {
                    locale = loadLocale(config.parentLocale);
                    if (locale != null) {
                        parentConfig = locale._config;
                    } else {
                        if (!localeFamilies[config.parentLocale]) {
                            localeFamilies[config.parentLocale] = [];
                        }
                        localeFamilies[config.parentLocale].push({
                            name: name,
                            config: config
                        });
                        return null;
                    }
                }
            }
            locales[name] = new Locale(mergeConfigs(parentConfig, config));

            if (localeFamilies[name]) {
                localeFamilies[name].forEach(function (x) {
                    defineLocale(x.name, x.config);
                });
            }

            // backwards compat for now: also set the locale
            // make sure we set the locale AFTER all child locales have been
            // created, so we won't end up with the child locale set.
            getSetGlobalLocale(name);


            return locales[name];
        } else {
            // useful for testing
            delete locales[name];
            return null;
        }
    }

    function updateLocale(name, config) {
        if (config != null) {
            var locale, tmpLocale, parentConfig = baseConfig;
            // MERGE
            tmpLocale = loadLocale(name);
            if (tmpLocale != null) {
                parentConfig = tmpLocale._config;
            }
            config = mergeConfigs(parentConfig, config);
            locale = new Locale(config);
            locale.parentLocale = locales[name];
            locales[name] = locale;

            // backwards compat for now: also set the locale
            getSetGlobalLocale(name);
        } else {
            // pass null for config to unupdate, useful for tests
            if (locales[name] != null) {
                if (locales[name].parentLocale != null) {
                    locales[name] = locales[name].parentLocale;
                } else if (locales[name] != null) {
                    delete locales[name];
                }
            }
        }
        return locales[name];
    }

    // returns locale data
    function getLocale (key) {
        var locale;

        if (key && key._locale && key._locale._abbr) {
            key = key._locale._abbr;
        }

        if (!key) {
            return globalLocale;
        }

        if (!isArray(key)) {
            //short-circuit everything else
            locale = loadLocale(key);
            if (locale) {
                return locale;
            }
            key = [key];
        }

        return chooseLocale(key);
    }

    function listLocales() {
        return keys(locales);
    }

    function checkOverflow (m) {
        var overflow;
        var a = m._a;

        if (a && getParsingFlags(m).overflow === -2) {
            overflow =
                a[MONTH]       < 0 || a[MONTH]       > 11  ? MONTH :
                a[DATE]        < 1 || a[DATE]        > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
                a[HOUR]        < 0 || a[HOUR]        > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
                a[MINUTE]      < 0 || a[MINUTE]      > 59  ? MINUTE :
                a[SECOND]      < 0 || a[SECOND]      > 59  ? SECOND :
                a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
                -1;

            if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
                overflow = DATE;
            }
            if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
                overflow = WEEK;
            }
            if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
                overflow = WEEKDAY;
            }

            getParsingFlags(m).overflow = overflow;
        }

        return m;
    }

    // Pick the first defined of two or three arguments.
    function defaults(a, b, c) {
        if (a != null) {
            return a;
        }
        if (b != null) {
            return b;
        }
        return c;
    }

    function currentDateArray(config) {
        // hooks is actually the exported moment object
        var nowValue = new Date(hooks.now());
        if (config._useUTC) {
            return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
        }
        return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
    }

    // convert an array to a date.
    // the array should mirror the parameters below
    // note: all values past the year are optional and will default to the lowest possible value.
    // [year, month, day , hour, minute, second, millisecond]
    function configFromArray (config) {
        var i, date, input = [], currentDate, expectedWeekday, yearToUse;

        if (config._d) {
            return;
        }

        currentDate = currentDateArray(config);

        //compute day of the year from weeks and weekdays
        if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
            dayOfYearFromWeekInfo(config);
        }

        //if the day of the year is set, figure out what it is
        if (config._dayOfYear != null) {
            yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);

            if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) {
                getParsingFlags(config)._overflowDayOfYear = true;
            }

            date = createUTCDate(yearToUse, 0, config._dayOfYear);
            config._a[MONTH] = date.getUTCMonth();
            config._a[DATE] = date.getUTCDate();
        }

        // Default to current date.
        // * if no year, month, day of month are given, default to today
        // * if day of month is given, default month and year
        // * if month is given, default only year
        // * if year is given, don't default anything
        for (i = 0; i < 3 && config._a[i] == null; ++i) {
            config._a[i] = input[i] = currentDate[i];
        }

        // Zero out whatever was not defaulted, including time
        for (; i < 7; i++) {
            config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
        }

        // Check for 24:00:00.000
        if (config._a[HOUR] === 24 &&
                config._a[MINUTE] === 0 &&
                config._a[SECOND] === 0 &&
                config._a[MILLISECOND] === 0) {
            config._nextDay = true;
            config._a[HOUR] = 0;
        }

        config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
        expectedWeekday = config._useUTC ? config._d.getUTCDay() : config._d.getDay();

        // Apply timezone offset from input. The actual utcOffset can be changed
        // with parseZone.
        if (config._tzm != null) {
            config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
        }

        if (config._nextDay) {
            config._a[HOUR] = 24;
        }

        // check for mismatching day of week
        if (config._w && typeof config._w.d !== 'undefined' && config._w.d !== expectedWeekday) {
            getParsingFlags(config).weekdayMismatch = true;
        }
    }

    function dayOfYearFromWeekInfo(config) {
        var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;

        w = config._w;
        if (w.GG != null || w.W != null || w.E != null) {
            dow = 1;
            doy = 4;

            // TODO: We need to take the current isoWeekYear, but that depends on
            // how we interpret now (local, utc, fixed offset). So create
            // a now version of current config (take local/utc/offset flags, and
            // create now).
            weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year);
            week = defaults(w.W, 1);
            weekday = defaults(w.E, 1);
            if (weekday < 1 || weekday > 7) {
                weekdayOverflow = true;
            }
        } else {
            dow = config._locale._week.dow;
            doy = config._locale._week.doy;

            var curWeek = weekOfYear(createLocal(), dow, doy);

            weekYear = defaults(w.gg, config._a[YEAR], curWeek.year);

            // Default to current week.
            week = defaults(w.w, curWeek.week);

            if (w.d != null) {
                // weekday -- low day numbers are considered next week
                weekday = w.d;
                if (weekday < 0 || weekday > 6) {
                    weekdayOverflow = true;
                }
            } else if (w.e != null) {
                // local weekday -- counting starts from beginning of week
                weekday = w.e + dow;
                if (w.e < 0 || w.e > 6) {
                    weekdayOverflow = true;
                }
            } else {
                // default to beginning of week
                weekday = dow;
            }
        }
        if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
            getParsingFlags(config)._overflowWeeks = true;
        } else if (weekdayOverflow != null) {
            getParsingFlags(config)._overflowWeekday = true;
        } else {
            temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
            config._a[YEAR] = temp.year;
            config._dayOfYear = temp.dayOfYear;
        }
    }

    // iso 8601 regex
    // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
    var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
    var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;

    var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;

    var isoDates = [
        ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
        ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
        ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
        ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
        ['YYYY-DDD', /\d{4}-\d{3}/],
        ['YYYY-MM', /\d{4}-\d\d/, false],
        ['YYYYYYMMDD', /[+-]\d{10}/],
        ['YYYYMMDD', /\d{8}/],
        // YYYYMM is NOT allowed by the standard
        ['GGGG[W]WWE', /\d{4}W\d{3}/],
        ['GGGG[W]WW', /\d{4}W\d{2}/, false],
        ['YYYYDDD', /\d{7}/]
    ];

    // iso time formats and regexes
    var isoTimes = [
        ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
        ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
        ['HH:mm:ss', /\d\d:\d\d:\d\d/],
        ['HH:mm', /\d\d:\d\d/],
        ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
        ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
        ['HHmmss', /\d\d\d\d\d\d/],
        ['HHmm', /\d\d\d\d/],
        ['HH', /\d\d/]
    ];

    var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;

    // date from iso format
    function configFromISO(config) {
        var i, l,
            string = config._i,
            match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
            allowTime, dateFormat, timeFormat, tzFormat;

        if (match) {
            getParsingFlags(config).iso = true;

            for (i = 0, l = isoDates.length; i < l; i++) {
                if (isoDates[i][1].exec(match[1])) {
                    dateFormat = isoDates[i][0];
                    allowTime = isoDates[i][2] !== false;
                    break;
                }
            }
            if (dateFormat == null) {
                config._isValid = false;
                return;
            }
            if (match[3]) {
                for (i = 0, l = isoTimes.length; i < l; i++) {
                    if (isoTimes[i][1].exec(match[3])) {
                        // match[2] should be 'T' or space
                        timeFormat = (match[2] || ' ') + isoTimes[i][0];
                        break;
                    }
                }
                if (timeFormat == null) {
                    config._isValid = false;
                    return;
                }
            }
            if (!allowTime && timeFormat != null) {
                config._isValid = false;
                return;
            }
            if (match[4]) {
                if (tzRegex.exec(match[4])) {
                    tzFormat = 'Z';
                } else {
                    config._isValid = false;
                    return;
                }
            }
            config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
            configFromStringAndFormat(config);
        } else {
            config._isValid = false;
        }
    }

    // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
    var rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;

    function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) {
        var result = [
            untruncateYear(yearStr),
            defaultLocaleMonthsShort.indexOf(monthStr),
            parseInt(dayStr, 10),
            parseInt(hourStr, 10),
            parseInt(minuteStr, 10)
        ];

        if (secondStr) {
            result.push(parseInt(secondStr, 10));
        }

        return result;
    }

    function untruncateYear(yearStr) {
        var year = parseInt(yearStr, 10);
        if (year <= 49) {
            return 2000 + year;
        } else if (year <= 999) {
            return 1900 + year;
        }
        return year;
    }

    function preprocessRFC2822(s) {
        // Remove comments and folding whitespace and replace multiple-spaces with a single space
        return s.replace(/\([^)]*\)|[\n\t]/g, ' ').replace(/(\s\s+)/g, ' ').replace(/^\s\s*/, '').replace(/\s\s*$/, '');
    }

    function checkWeekday(weekdayStr, parsedInput, config) {
        if (weekdayStr) {
            // TODO: Replace the vanilla JS Date object with an indepentent day-of-week check.
            var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr),
                weekdayActual = new Date(parsedInput[0], parsedInput[1], parsedInput[2]).getDay();
            if (weekdayProvided !== weekdayActual) {
                getParsingFlags(config).weekdayMismatch = true;
                config._isValid = false;
                return false;
            }
        }
        return true;
    }

    var obsOffsets = {
        UT: 0,
        GMT: 0,
        EDT: -4 * 60,
        EST: -5 * 60,
        CDT: -5 * 60,
        CST: -6 * 60,
        MDT: -6 * 60,
        MST: -7 * 60,
        PDT: -7 * 60,
        PST: -8 * 60
    };

    function calculateOffset(obsOffset, militaryOffset, numOffset) {
        if (obsOffset) {
            return obsOffsets[obsOffset];
        } else if (militaryOffset) {
            // the only allowed military tz is Z
            return 0;
        } else {
            var hm = parseInt(numOffset, 10);
            var m = hm % 100, h = (hm - m) / 100;
            return h * 60 + m;
        }
    }

    // date and time from ref 2822 format
    function configFromRFC2822(config) {
        var match = rfc2822.exec(preprocessRFC2822(config._i));
        if (match) {
            var parsedArray = extractFromRFC2822Strings(match[4], match[3], match[2], match[5], match[6], match[7]);
            if (!checkWeekday(match[1], parsedArray, config)) {
                return;
            }

            config._a = parsedArray;
            config._tzm = calculateOffset(match[8], match[9], match[10]);

            config._d = createUTCDate.apply(null, config._a);
            config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);

            getParsingFlags(config).rfc2822 = true;
        } else {
            config._isValid = false;
        }
    }

    // date from iso format or fallback
    function configFromString(config) {
        var matched = aspNetJsonRegex.exec(config._i);

        if (matched !== null) {
            config._d = new Date(+matched[1]);
            return;
        }

        configFromISO(config);
        if (config._isValid === false) {
            delete config._isValid;
        } else {
            return;
        }

        configFromRFC2822(config);
        if (config._isValid === false) {
            delete config._isValid;
        } else {
            return;
        }

        // Final attempt, use Input Fallback
        hooks.createFromInputFallback(config);
    }

    hooks.createFromInputFallback = deprecate(
        'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' +
        'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' +
        'discouraged and will be removed in an upcoming major release. Please refer to ' +
        'http://momentjs.com/guides/#/warnings/js-date/ for more info.',
        function (config) {
            config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
        }
    );

    // constant that refers to the ISO standard
    hooks.ISO_8601 = function () {};

    // constant that refers to the RFC 2822 form
    hooks.RFC_2822 = function () {};

    // date from string and format string
    function configFromStringAndFormat(config) {
        // TODO: Move this to another part of the creation flow to prevent circular deps
        if (config._f === hooks.ISO_8601) {
            configFromISO(config);
            return;
        }
        if (config._f === hooks.RFC_2822) {
            configFromRFC2822(config);
            return;
        }
        config._a = [];
        getParsingFlags(config).empty = true;

        // This array is used to make a Date, either with `new Date` or `Date.UTC`
        var string = '' + config._i,
            i, parsedInput, tokens, token, skipped,
            stringLength = string.length,
            totalParsedInputLength = 0;

        tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];

        for (i = 0; i < tokens.length; i++) {
            token = tokens[i];
            parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
            // console.log('token', token, 'parsedInput', parsedInput,
            //         'regex', getParseRegexForToken(token, config));
            if (parsedInput) {
                skipped = string.substr(0, string.indexOf(parsedInput));
                if (skipped.length > 0) {
                    getParsingFlags(config).unusedInput.push(skipped);
                }
                string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
                totalParsedInputLength += parsedInput.length;
            }
            // don't parse if it's not a known token
            if (formatTokenFunctions[token]) {
                if (parsedInput) {
                    getParsingFlags(config).empty = false;
                }
                else {
                    getParsingFlags(config).unusedTokens.push(token);
                }
                addTimeToArrayFromToken(token, parsedInput, config);
            }
            else if (config._strict && !parsedInput) {
                getParsingFlags(config).unusedTokens.push(token);
            }
        }

        // add remaining unparsed input length to the string
        getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
        if (string.length > 0) {
            getParsingFlags(config).unusedInput.push(string);
        }

        // clear _12h flag if hour is <= 12
        if (config._a[HOUR] <= 12 &&
            getParsingFlags(config).bigHour === true &&
            config._a[HOUR] > 0) {
            getParsingFlags(config).bigHour = undefined;
        }

        getParsingFlags(config).parsedDateParts = config._a.slice(0);
        getParsingFlags(config).meridiem = config._meridiem;
        // handle meridiem
        config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);

        configFromArray(config);
        checkOverflow(config);
    }


    function meridiemFixWrap (locale, hour, meridiem) {
        var isPm;

        if (meridiem == null) {
            // nothing to do
            return hour;
        }
        if (locale.meridiemHour != null) {
            return locale.meridiemHour(hour, meridiem);
        } else if (locale.isPM != null) {
            // Fallback
            isPm = locale.isPM(meridiem);
            if (isPm && hour < 12) {
                hour += 12;
            }
            if (!isPm && hour === 12) {
                hour = 0;
            }
            return hour;
        } else {
            // this is not supposed to happen
            return hour;
        }
    }

    // date from string and array of format strings
    function configFromStringAndArray(config) {
        var tempConfig,
            bestMoment,

            scoreToBeat,
            i,
            currentScore;

        if (config._f.length === 0) {
            getParsingFlags(config).invalidFormat = true;
            config._d = new Date(NaN);
            return;
        }

        for (i = 0; i < config._f.length; i++) {
            currentScore = 0;
            tempConfig = copyConfig({}, config);
            if (config._useUTC != null) {
                tempConfig._useUTC = config._useUTC;
            }
            tempConfig._f = config._f[i];
            configFromStringAndFormat(tempConfig);

            if (!isValid(tempConfig)) {
                continue;
            }

            // if there is any input that was not parsed add a penalty for that format
            currentScore += getParsingFlags(tempConfig).charsLeftOver;

            //or tokens
            currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;

            getParsingFlags(tempConfig).score = currentScore;

            if (scoreToBeat == null || currentScore < scoreToBeat) {
                scoreToBeat = currentScore;
                bestMoment = tempConfig;
            }
        }

        extend(config, bestMoment || tempConfig);
    }

    function configFromObject(config) {
        if (config._d) {
            return;
        }

        var i = normalizeObjectUnits(config._i);
        config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
            return obj && parseInt(obj, 10);
        });

        configFromArray(config);
    }

    function createFromConfig (config) {
        var res = new Moment(checkOverflow(prepareConfig(config)));
        if (res._nextDay) {
            // Adding is smart enough around DST
            res.add(1, 'd');
            res._nextDay = undefined;
        }

        return res;
    }

    function prepareConfig (config) {
        var input = config._i,
            format = config._f;

        config._locale = config._locale || getLocale(config._l);

        if (input === null || (format === undefined && input === '')) {
            return createInvalid({nullInput: true});
        }

        if (typeof input === 'string') {
            config._i = input = config._locale.preparse(input);
        }

        if (isMoment(input)) {
            return new Moment(checkOverflow(input));
        } else if (isDate(input)) {
            config._d = input;
        } else if (isArray(format)) {
            configFromStringAndArray(config);
        } else if (format) {
            configFromStringAndFormat(config);
        }  else {
            configFromInput(config);
        }

        if (!isValid(config)) {
            config._d = null;
        }

        return config;
    }

    function configFromInput(config) {
        var input = config._i;
        if (isUndefined(input)) {
            config._d = new Date(hooks.now());
        } else if (isDate(input)) {
            config._d = new Date(input.valueOf());
        } else if (typeof input === 'string') {
            configFromString(config);
        } else if (isArray(input)) {
            config._a = map(input.slice(0), function (obj) {
                return parseInt(obj, 10);
            });
            configFromArray(config);
        } else if (isObject(input)) {
            configFromObject(config);
        } else if (isNumber(input)) {
            // from milliseconds
            config._d = new Date(input);
        } else {
            hooks.createFromInputFallback(config);
        }
    }

    function createLocalOrUTC (input, format, locale, strict, isUTC) {
        var c = {};

        if (locale === true || locale === false) {
            strict = locale;
            locale = undefined;
        }

        if ((isObject(input) && isObjectEmpty(input)) ||
                (isArray(input) && input.length === 0)) {
            input = undefined;
        }
        // object construction must be done this way.
        // https://github.com/moment/moment/issues/1423
        c._isAMomentObject = true;
        c._useUTC = c._isUTC = isUTC;
        c._l = locale;
        c._i = input;
        c._f = format;
        c._strict = strict;

        return createFromConfig(c);
    }

    function createLocal (input, format, locale, strict) {
        return createLocalOrUTC(input, format, locale, strict, false);
    }

    var prototypeMin = deprecate(
        'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/',
        function () {
            var other = createLocal.apply(null, arguments);
            if (this.isValid() && other.isValid()) {
                return other < this ? this : other;
            } else {
                return createInvalid();
            }
        }
    );

    var prototypeMax = deprecate(
        'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/',
        function () {
            var other = createLocal.apply(null, arguments);
            if (this.isValid() && other.isValid()) {
                return other > this ? this : other;
            } else {
                return createInvalid();
            }
        }
    );

    // Pick a moment m from moments so that m[fn](other) is true for all
    // other. This relies on the function fn to be transitive.
    //
    // moments should either be an array of moment objects or an array, whose
    // first element is an array of moment objects.
    function pickBy(fn, moments) {
        var res, i;
        if (moments.length === 1 && isArray(moments[0])) {
            moments = moments[0];
        }
        if (!moments.length) {
            return createLocal();
        }
        res = moments[0];
        for (i = 1; i < moments.length; ++i) {
            if (!moments[i].isValid() || moments[i][fn](res)) {
                res = moments[i];
            }
        }
        return res;
    }

    // TODO: Use [].sort instead?
    function min () {
        var args = [].slice.call(arguments, 0);

        return pickBy('isBefore', args);
    }

    function max () {
        var args = [].slice.call(arguments, 0);

        return pickBy('isAfter', args);
    }

    var now = function () {
        return Date.now ? Date.now() : +(new Date());
    };

    var ordering = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'];

    function isDurationValid(m) {
        for (var key in m) {
            if (!(indexOf.call(ordering, key) !== -1 && (m[key] == null || !isNaN(m[key])))) {
                return false;
            }
        }

        var unitHasDecimal = false;
        for (var i = 0; i < ordering.length; ++i) {
            if (m[ordering[i]]) {
                if (unitHasDecimal) {
                    return false; // only allow non-integers for smallest unit
                }
                if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {
                    unitHasDecimal = true;
                }
            }
        }

        return true;
    }

    function isValid$1() {
        return this._isValid;
    }

    function createInvalid$1() {
        return createDuration(NaN);
    }

    function Duration (duration) {
        var normalizedInput = normalizeObjectUnits(duration),
            years = normalizedInput.year || 0,
            quarters = normalizedInput.quarter || 0,
            months = normalizedInput.month || 0,
            weeks = normalizedInput.week || normalizedInput.isoWeek || 0,
            days = normalizedInput.day || 0,
            hours = normalizedInput.hour || 0,
            minutes = normalizedInput.minute || 0,
            seconds = normalizedInput.second || 0,
            milliseconds = normalizedInput.millisecond || 0;

        this._isValid = isDurationValid(normalizedInput);

        // representation for dateAddRemove
        this._milliseconds = +milliseconds +
            seconds * 1e3 + // 1000
            minutes * 6e4 + // 1000 * 60
            hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
        // Because of dateAddRemove treats 24 hours as different from a
        // day when working around DST, we need to store them separately
        this._days = +days +
            weeks * 7;
        // It is impossible to translate months into days without knowing
        // which months you are are talking about, so we have to store
        // it separately.
        this._months = +months +
            quarters * 3 +
            years * 12;

        this._data = {};

        this._locale = getLocale();

        this._bubble();
    }

    function isDuration (obj) {
        return obj instanceof Duration;
    }

    function absRound (number) {
        if (number < 0) {
            return Math.round(-1 * number) * -1;
        } else {
            return Math.round(number);
        }
    }

    // FORMATTING

    function offset (token, separator) {
        addFormatToken(token, 0, 0, function () {
            var offset = this.utcOffset();
            var sign = '+';
            if (offset < 0) {
                offset = -offset;
                sign = '-';
            }
            return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
        });
    }

    offset('Z', ':');
    offset('ZZ', '');

    // PARSING

    addRegexToken('Z',  matchShortOffset);
    addRegexToken('ZZ', matchShortOffset);
    addParseToken(['Z', 'ZZ'], function (input, array, config) {
        config._useUTC = true;
        config._tzm = offsetFromString(matchShortOffset, input);
    });

    // HELPERS

    // timezone chunker
    // '+10:00' > ['10',  '00']
    // '-1530'  > ['-15', '30']
    var chunkOffset = /([\+\-]|\d\d)/gi;

    function offsetFromString(matcher, string) {
        var matches = (string || '').match(matcher);

        if (matches === null) {
            return null;
        }

        var chunk   = matches[matches.length - 1] || [];
        var parts   = (chunk + '').match(chunkOffset) || ['-', 0, 0];
        var minutes = +(parts[1] * 60) + toInt(parts[2]);

        return minutes === 0 ?
          0 :
          parts[0] === '+' ? minutes : -minutes;
    }

    // Return a moment from input, that is local/utc/zone equivalent to model.
    function cloneWithOffset(input, model) {
        var res, diff;
        if (model._isUTC) {
            res = model.clone();
            diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf();
            // Use low-level api, because this fn is low-level api.
            res._d.setTime(res._d.valueOf() + diff);
            hooks.updateOffset(res, false);
            return res;
        } else {
            return createLocal(input).local();
        }
    }

    function getDateOffset (m) {
        // On Firefox.24 Date#getTimezoneOffset returns a floating point.
        // https://github.com/moment/moment/pull/1871
        return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
    }

    // HOOKS

    // This function will be called whenever a moment is mutated.
    // It is intended to keep the offset in sync with the timezone.
    hooks.updateOffset = function () {};

    // MOMENTS

    // keepLocalTime = true means only change the timezone, without
    // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
    // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
    // +0200, so we adjust the time as needed, to be valid.
    //
    // Keeping the time actually adds/subtracts (one hour)
    // from the actual represented time. That is why we call updateOffset
    // a second time. In case it wants us to change the offset again
    // _changeInProgress == true case, then we have to adjust, because
    // there is no such time in the given timezone.
    function getSetOffset (input, keepLocalTime, keepMinutes) {
        var offset = this._offset || 0,
            localAdjust;
        if (!this.isValid()) {
            return input != null ? this : NaN;
        }
        if (input != null) {
            if (typeof input === 'string') {
                input = offsetFromString(matchShortOffset, input);
                if (input === null) {
                    return this;
                }
            } else if (Math.abs(input) < 16 && !keepMinutes) {
                input = input * 60;
            }
            if (!this._isUTC && keepLocalTime) {
                localAdjust = getDateOffset(this);
            }
            this._offset = input;
            this._isUTC = true;
            if (localAdjust != null) {
                this.add(localAdjust, 'm');
            }
            if (offset !== input) {
                if (!keepLocalTime || this._changeInProgress) {
                    addSubtract(this, createDuration(input - offset, 'm'), 1, false);
                } else if (!this._changeInProgress) {
                    this._changeInProgress = true;
                    hooks.updateOffset(this, true);
                    this._changeInProgress = null;
                }
            }
            return this;
        } else {
            return this._isUTC ? offset : getDateOffset(this);
        }
    }

    function getSetZone (input, keepLocalTime) {
        if (input != null) {
            if (typeof input !== 'string') {
                input = -input;
            }

            this.utcOffset(input, keepLocalTime);

            return this;
        } else {
            return -this.utcOffset();
        }
    }

    function setOffsetToUTC (keepLocalTime) {
        return this.utcOffset(0, keepLocalTime);
    }

    function setOffsetToLocal (keepLocalTime) {
        if (this._isUTC) {
            this.utcOffset(0, keepLocalTime);
            this._isUTC = false;

            if (keepLocalTime) {
                this.subtract(getDateOffset(this), 'm');
            }
        }
        return this;
    }

    function setOffsetToParsedOffset () {
        if (this._tzm != null) {
            this.utcOffset(this._tzm, false, true);
        } else if (typeof this._i === 'string') {
            var tZone = offsetFromString(matchOffset, this._i);
            if (tZone != null) {
                this.utcOffset(tZone);
            }
            else {
                this.utcOffset(0, true);
            }
        }
        return this;
    }

    function hasAlignedHourOffset (input) {
        if (!this.isValid()) {
            return false;
        }
        input = input ? createLocal(input).utcOffset() : 0;

        return (this.utcOffset() - input) % 60 === 0;
    }

    function isDaylightSavingTime () {
        return (
            this.utcOffset() > this.clone().month(0).utcOffset() ||
            this.utcOffset() > this.clone().month(5).utcOffset()
        );
    }

    function isDaylightSavingTimeShifted () {
        if (!isUndefined(this._isDSTShifted)) {
            return this._isDSTShifted;
        }

        var c = {};

        copyConfig(c, this);
        c = prepareConfig(c);

        if (c._a) {
            var other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
            this._isDSTShifted = this.isValid() &&
                compareArrays(c._a, other.toArray()) > 0;
        } else {
            this._isDSTShifted = false;
        }

        return this._isDSTShifted;
    }

    function isLocal () {
        return this.isValid() ? !this._isUTC : false;
    }

    function isUtcOffset () {
        return this.isValid() ? this._isUTC : false;
    }

    function isUtc () {
        return this.isValid() ? this._isUTC && this._offset === 0 : false;
    }

    // ASP.NET json date format regex
    var aspNetRegex = /^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/;

    // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
    // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
    // and further modified to allow for strings containing both week and day
    var isoRegex = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;

    function createDuration (input, key) {
        var duration = input,
            // matching against regexp is expensive, do it on demand
            match = null,
            sign,
            ret,
            diffRes;

        if (isDuration(input)) {
            duration = {
                ms : input._milliseconds,
                d  : input._days,
                M  : input._months
            };
        } else if (isNumber(input)) {
            duration = {};
            if (key) {
                duration[key] = input;
            } else {
                duration.milliseconds = input;
            }
        } else if (!!(match = aspNetRegex.exec(input))) {
            sign = (match[1] === '-') ? -1 : 1;
            duration = {
                y  : 0,
                d  : toInt(match[DATE])                         * sign,
                h  : toInt(match[HOUR])                         * sign,
                m  : toInt(match[MINUTE])                       * sign,
                s  : toInt(match[SECOND])                       * sign,
                ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match
            };
        } else if (!!(match = isoRegex.exec(input))) {
            sign = (match[1] === '-') ? -1 : 1;
            duration = {
                y : parseIso(match[2], sign),
                M : parseIso(match[3], sign),
                w : parseIso(match[4], sign),
                d : parseIso(match[5], sign),
                h : parseIso(match[6], sign),
                m : parseIso(match[7], sign),
                s : parseIso(match[8], sign)
            };
        } else if (duration == null) {// checks for null or undefined
            duration = {};
        } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
            diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));

            duration = {};
            duration.ms = diffRes.milliseconds;
            duration.M = diffRes.months;
        }

        ret = new Duration(duration);

        if (isDuration(input) && hasOwnProp(input, '_locale')) {
            ret._locale = input._locale;
        }

        return ret;
    }

    createDuration.fn = Duration.prototype;
    createDuration.invalid = createInvalid$1;

    function parseIso (inp, sign) {
        // We'd normally use ~~inp for this, but unfortunately it also
        // converts floats to ints.
        // inp may be undefined, so careful calling replace on it.
        var res = inp && parseFloat(inp.replace(',', '.'));
        // apply sign while we're at it
        return (isNaN(res) ? 0 : res) * sign;
    }

    function positiveMomentsDifference(base, other) {
        var res = {};

        res.months = other.month() - base.month() +
            (other.year() - base.year()) * 12;
        if (base.clone().add(res.months, 'M').isAfter(other)) {
            --res.months;
        }

        res.milliseconds = +other - +(base.clone().add(res.months, 'M'));

        return res;
    }

    function momentsDifference(base, other) {
        var res;
        if (!(base.isValid() && other.isValid())) {
            return {milliseconds: 0, months: 0};
        }

        other = cloneWithOffset(other, base);
        if (base.isBefore(other)) {
            res = positiveMomentsDifference(base, other);
        } else {
            res = positiveMomentsDifference(other, base);
            res.milliseconds = -res.milliseconds;
            res.months = -res.months;
        }

        return res;
    }

    // TODO: remove 'name' arg after deprecation is removed
    function createAdder(direction, name) {
        return function (val, period) {
            var dur, tmp;
            //invert the arguments, but complain about it
            if (period !== null && !isNaN(+period)) {
                deprecateSimple(name, 'moment().' + name  + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' +
                'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.');
                tmp = val; val = period; period = tmp;
            }

            val = typeof val === 'string' ? +val : val;
            dur = createDuration(val, period);
            addSubtract(this, dur, direction);
            return this;
        };
    }

    function addSubtract (mom, duration, isAdding, updateOffset) {
        var milliseconds = duration._milliseconds,
            days = absRound(duration._days),
            months = absRound(duration._months);

        if (!mom.isValid()) {
            // No op
            return;
        }

        updateOffset = updateOffset == null ? true : updateOffset;

        if (months) {
            setMonth(mom, get(mom, 'Month') + months * isAdding);
        }
        if (days) {
            set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);
        }
        if (milliseconds) {
            mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
        }
        if (updateOffset) {
            hooks.updateOffset(mom, days || months);
        }
    }

    var add      = createAdder(1, 'add');
    var subtract = createAdder(-1, 'subtract');

    function getCalendarFormat(myMoment, now) {
        var diff = myMoment.diff(now, 'days', true);
        return diff < -6 ? 'sameElse' :
                diff < -1 ? 'lastWeek' :
                diff < 0 ? 'lastDay' :
                diff < 1 ? 'sameDay' :
                diff < 2 ? 'nextDay' :
                diff < 7 ? 'nextWeek' : 'sameElse';
    }

    function calendar$1 (time, formats) {
        // We want to compare the start of today, vs this.
        // Getting start-of-today depends on whether we're local/utc/offset or not.
        var now = time || createLocal(),
            sod = cloneWithOffset(now, this).startOf('day'),
            format = hooks.calendarFormat(this, sod) || 'sameElse';

        var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]);

        return this.format(output || this.localeData().calendar(format, this, createLocal(now)));
    }

    function clone () {
        return new Moment(this);
    }

    function isAfter (input, units) {
        var localInput = isMoment(input) ? input : createLocal(input);
        if (!(this.isValid() && localInput.isValid())) {
            return false;
        }
        units = normalizeUnits(units) || 'millisecond';
        if (units === 'millisecond') {
            return this.valueOf() > localInput.valueOf();
        } else {
            return localInput.valueOf() < this.clone().startOf(units).valueOf();
        }
    }

    function isBefore (input, units) {
        var localInput = isMoment(input) ? input : createLocal(input);
        if (!(this.isValid() && localInput.isValid())) {
            return false;
        }
        units = normalizeUnits(units) || 'millisecond';
        if (units === 'millisecond') {
            return this.valueOf() < localInput.valueOf();
        } else {
            return this.clone().endOf(units).valueOf() < localInput.valueOf();
        }
    }

    function isBetween (from, to, units, inclusivity) {
        var localFrom = isMoment(from) ? from : createLocal(from),
            localTo = isMoment(to) ? to : createLocal(to);
        if (!(this.isValid() && localFrom.isValid() && localTo.isValid())) {
            return false;
        }
        inclusivity = inclusivity || '()';
        return (inclusivity[0] === '(' ? this.isAfter(localFrom, units) : !this.isBefore(localFrom, units)) &&
            (inclusivity[1] === ')' ? this.isBefore(localTo, units) : !this.isAfter(localTo, units));
    }

    function isSame (input, units) {
        var localInput = isMoment(input) ? input : createLocal(input),
            inputMs;
        if (!(this.isValid() && localInput.isValid())) {
            return false;
        }
        units = normalizeUnits(units) || 'millisecond';
        if (units === 'millisecond') {
            return this.valueOf() === localInput.valueOf();
        } else {
            inputMs = localInput.valueOf();
            return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
        }
    }

    function isSameOrAfter (input, units) {
        return this.isSame(input, units) || this.isAfter(input, units);
    }

    function isSameOrBefore (input, units) {
        return this.isSame(input, units) || this.isBefore(input, units);
    }

    function diff (input, units, asFloat) {
        var that,
            zoneDelta,
            output;

        if (!this.isValid()) {
            return NaN;
        }

        that = cloneWithOffset(input, this);

        if (!that.isValid()) {
            return NaN;
        }

        zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;

        units = normalizeUnits(units);

        switch (units) {
            case 'year': output = monthDiff(this, that) / 12; break;
            case 'month': output = monthDiff(this, that); break;
            case 'quarter': output = monthDiff(this, that) / 3; break;
            case 'second': output = (this - that) / 1e3; break; // 1000
            case 'minute': output = (this - that) / 6e4; break; // 1000 * 60
            case 'hour': output = (this - that) / 36e5; break; // 1000 * 60 * 60
            case 'day': output = (this - that - zoneDelta) / 864e5; break; // 1000 * 60 * 60 * 24, negate dst
            case 'week': output = (this - that - zoneDelta) / 6048e5; break; // 1000 * 60 * 60 * 24 * 7, negate dst
            default: output = this - that;
        }

        return asFloat ? output : absFloor(output);
    }

    function monthDiff (a, b) {
        // difference in months
        var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
            // b is in (anchor - 1 month, anchor + 1 month)
            anchor = a.clone().add(wholeMonthDiff, 'months'),
            anchor2, adjust;

        if (b - anchor < 0) {
            anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
            // linear across the month
            adjust = (b - anchor) / (anchor - anchor2);
        } else {
            anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
            // linear across the month
            adjust = (b - anchor) / (anchor2 - anchor);
        }

        //check for negative zero, return zero if negative zero
        return -(wholeMonthDiff + adjust) || 0;
    }

    hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
    hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';

    function toString () {
        return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
    }

    function toISOString(keepOffset) {
        if (!this.isValid()) {
            return null;
        }
        var utc = keepOffset !== true;
        var m = utc ? this.clone().utc() : this;
        if (m.year() < 0 || m.year() > 9999) {
            return formatMoment(m, utc ? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ');
        }
        if (isFunction(Date.prototype.toISOString)) {
            // native implementation is ~50x faster, use it when we can
            if (utc) {
                return this.toDate().toISOString();
            } else {
                return new Date(this.valueOf() + this.utcOffset() * 60 * 1000).toISOString().replace('Z', formatMoment(m, 'Z'));
            }
        }
        return formatMoment(m, utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ');
    }

    /**
     * Return a human readable representation of a moment that can
     * also be evaluated to get a new moment which is the same
     *
     * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
     */
    function inspect () {
        if (!this.isValid()) {
            return 'moment.invalid(/* ' + this._i + ' */)';
        }
        var func = 'moment';
        var zone = '';
        if (!this.isLocal()) {
            func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
            zone = 'Z';
        }
        var prefix = '[' + func + '("]';
        var year = (0 <= this.year() && this.year() <= 9999) ? 'YYYY' : 'YYYYYY';
        var datetime = '-MM-DD[T]HH:mm:ss.SSS';
        var suffix = zone + '[")]';

        return this.format(prefix + year + datetime + suffix);
    }

    function format (inputString) {
        if (!inputString) {
            inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat;
        }
        var output = formatMoment(this, inputString);
        return this.localeData().postformat(output);
    }

    function from (time, withoutSuffix) {
        if (this.isValid() &&
                ((isMoment(time) && time.isValid()) ||
                 createLocal(time).isValid())) {
            return createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
        } else {
            return this.localeData().invalidDate();
        }
    }

    function fromNow (withoutSuffix) {
        return this.from(createLocal(), withoutSuffix);
    }

    function to (time, withoutSuffix) {
        if (this.isValid() &&
                ((isMoment(time) && time.isValid()) ||
                 createLocal(time).isValid())) {
            return createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
        } else {
            return this.localeData().invalidDate();
        }
    }

    function toNow (withoutSuffix) {
        return this.to(createLocal(), withoutSuffix);
    }

    // If passed a locale key, it will set the locale for this
    // instance.  Otherwise, it will return the locale configuration
    // variables for this instance.
    function locale (key) {
        var newLocaleData;

        if (key === undefined) {
            return this._locale._abbr;
        } else {
            newLocaleData = getLocale(key);
            if (newLocaleData != null) {
                this._locale = newLocaleData;
            }
            return this;
        }
    }

    var lang = deprecate(
        'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
        function (key) {
            if (key === undefined) {
                return this.localeData();
            } else {
                return this.locale(key);
            }
        }
    );

    function localeData () {
        return this._locale;
    }

    var MS_PER_SECOND = 1000;
    var MS_PER_MINUTE = 60 * MS_PER_SECOND;
    var MS_PER_HOUR = 60 * MS_PER_MINUTE;
    var MS_PER_400_YEARS = (365 * 400 + 97) * 24 * MS_PER_HOUR;

    // actual modulo - handles negative numbers (for dates before 1970):
    function mod$1(dividend, divisor) {
        return (dividend % divisor + divisor) % divisor;
    }

    function localStartOfDate(y, m, d) {
        // the date constructor remaps years 0-99 to 1900-1999
        if (y < 100 && y >= 0) {
            // preserve leap years using a full 400 year cycle, then reset
            return new Date(y + 400, m, d) - MS_PER_400_YEARS;
        } else {
            return new Date(y, m, d).valueOf();
        }
    }

    function utcStartOfDate(y, m, d) {
        // Date.UTC remaps years 0-99 to 1900-1999
        if (y < 100 && y >= 0) {
            // preserve leap years using a full 400 year cycle, then reset
            return Date.UTC(y + 400, m, d) - MS_PER_400_YEARS;
        } else {
            return Date.UTC(y, m, d);
        }
    }

    function startOf (units) {
        var time;
        units = normalizeUnits(units);
        if (units === undefined || units === 'millisecond' || !this.isValid()) {
            return this;
        }

        var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;

        switch (units) {
            case 'year':
                time = startOfDate(this.year(), 0, 1);
                break;
            case 'quarter':
                time = startOfDate(this.year(), this.month() - this.month() % 3, 1);
                break;
            case 'month':
                time = startOfDate(this.year(), this.month(), 1);
                break;
            case 'week':
                time = startOfDate(this.year(), this.month(), this.date() - this.weekday());
                break;
            case 'isoWeek':
                time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1));
                break;
            case 'day':
            case 'date':
                time = startOfDate(this.year(), this.month(), this.date());
                break;
            case 'hour':
                time = this._d.valueOf();
                time -= mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR);
                break;
            case 'minute':
                time = this._d.valueOf();
                time -= mod$1(time, MS_PER_MINUTE);
                break;
            case 'second':
                time = this._d.valueOf();
                time -= mod$1(time, MS_PER_SECOND);
                break;
        }

        this._d.setTime(time);
        hooks.updateOffset(this, true);
        return this;
    }

    function endOf (units) {
        var time;
        units = normalizeUnits(units);
        if (units === undefined || units === 'millisecond' || !this.isValid()) {
            return this;
        }

        var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;

        switch (units) {
            case 'year':
                time = startOfDate(this.year() + 1, 0, 1) - 1;
                break;
            case 'quarter':
                time = startOfDate(this.year(), this.month() - this.month() % 3 + 3, 1) - 1;
                break;
            case 'month':
                time = startOfDate(this.year(), this.month() + 1, 1) - 1;
                break;
            case 'week':
                time = startOfDate(this.year(), this.month(), this.date() - this.weekday() + 7) - 1;
                break;
            case 'isoWeek':
                time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1) + 7) - 1;
                break;
            case 'day':
            case 'date':
                time = startOfDate(this.year(), this.month(), this.date() + 1) - 1;
                break;
            case 'hour':
                time = this._d.valueOf();
                time += MS_PER_HOUR - mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR) - 1;
                break;
            case 'minute':
                time = this._d.valueOf();
                time += MS_PER_MINUTE - mod$1(time, MS_PER_MINUTE) - 1;
                break;
            case 'second':
                time = this._d.valueOf();
                time += MS_PER_SECOND - mod$1(time, MS_PER_SECOND) - 1;
                break;
        }

        this._d.setTime(time);
        hooks.updateOffset(this, true);
        return this;
    }

    function valueOf () {
        return this._d.valueOf() - ((this._offset || 0) * 60000);
    }

    function unix () {
        return Math.floor(this.valueOf() / 1000);
    }

    function toDate () {
        return new Date(this.valueOf());
    }

    function toArray () {
        var m = this;
        return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
    }

    function toObject () {
        var m = this;
        return {
            years: m.year(),
            months: m.month(),
            date: m.date(),
            hours: m.hours(),
            minutes: m.minutes(),
            seconds: m.seconds(),
            milliseconds: m.milliseconds()
        };
    }

    function toJSON () {
        // new Date(NaN).toJSON() === null
        return this.isValid() ? this.toISOString() : null;
    }

    function isValid$2 () {
        return isValid(this);
    }

    function parsingFlags () {
        return extend({}, getParsingFlags(this));
    }

    function invalidAt () {
        return getParsingFlags(this).overflow;
    }

    function creationData() {
        return {
            input: this._i,
            format: this._f,
            locale: this._locale,
            isUTC: this._isUTC,
            strict: this._strict
        };
    }

    // FORMATTING

    addFormatToken(0, ['gg', 2], 0, function () {
        return this.weekYear() % 100;
    });

    addFormatToken(0, ['GG', 2], 0, function () {
        return this.isoWeekYear() % 100;
    });

    function addWeekYearFormatToken (token, getter) {
        addFormatToken(0, [token, token.length], 0, getter);
    }

    addWeekYearFormatToken('gggg',     'weekYear');
    addWeekYearFormatToken('ggggg',    'weekYear');
    addWeekYearFormatToken('GGGG',  'isoWeekYear');
    addWeekYearFormatToken('GGGGG', 'isoWeekYear');

    // ALIASES

    addUnitAlias('weekYear', 'gg');
    addUnitAlias('isoWeekYear', 'GG');

    // PRIORITY

    addUnitPriority('weekYear', 1);
    addUnitPriority('isoWeekYear', 1);


    // PARSING

    addRegexToken('G',      matchSigned);
    addRegexToken('g',      matchSigned);
    addRegexToken('GG',     match1to2, match2);
    addRegexToken('gg',     match1to2, match2);
    addRegexToken('GGGG',   match1to4, match4);
    addRegexToken('gggg',   match1to4, match4);
    addRegexToken('GGGGG',  match1to6, match6);
    addRegexToken('ggggg',  match1to6, match6);

    addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
        week[token.substr(0, 2)] = toInt(input);
    });

    addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
        week[token] = hooks.parseTwoDigitYear(input);
    });

    // MOMENTS

    function getSetWeekYear (input) {
        return getSetWeekYearHelper.call(this,
                input,
                this.week(),
                this.weekday(),
                this.localeData()._week.dow,
                this.localeData()._week.doy);
    }

    function getSetISOWeekYear (input) {
        return getSetWeekYearHelper.call(this,
                input, this.isoWeek(), this.isoWeekday(), 1, 4);
    }

    function getISOWeeksInYear () {
        return weeksInYear(this.year(), 1, 4);
    }

    function getWeeksInYear () {
        var weekInfo = this.localeData()._week;
        return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
    }

    function getSetWeekYearHelper(input, week, weekday, dow, doy) {
        var weeksTarget;
        if (input == null) {
            return weekOfYear(this, dow, doy).year;
        } else {
            weeksTarget = weeksInYear(input, dow, doy);
            if (week > weeksTarget) {
                week = weeksTarget;
            }
            return setWeekAll.call(this, input, week, weekday, dow, doy);
        }
    }

    function setWeekAll(weekYear, week, weekday, dow, doy) {
        var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
            date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);

        this.year(date.getUTCFullYear());
        this.month(date.getUTCMonth());
        this.date(date.getUTCDate());
        return this;
    }

    // FORMATTING

    addFormatToken('Q', 0, 'Qo', 'quarter');

    // ALIASES

    addUnitAlias('quarter', 'Q');

    // PRIORITY

    addUnitPriority('quarter', 7);

    // PARSING

    addRegexToken('Q', match1);
    addParseToken('Q', function (input, array) {
        array[MONTH] = (toInt(input) - 1) * 3;
    });

    // MOMENTS

    function getSetQuarter (input) {
        return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
    }

    // FORMATTING

    addFormatToken('D', ['DD', 2], 'Do', 'date');

    // ALIASES

    addUnitAlias('date', 'D');

    // PRIORITY
    addUnitPriority('date', 9);

    // PARSING

    addRegexToken('D',  match1to2);
    addRegexToken('DD', match1to2, match2);
    addRegexToken('Do', function (isStrict, locale) {
        // TODO: Remove "ordinalParse" fallback in next major release.
        return isStrict ?
          (locale._dayOfMonthOrdinalParse || locale._ordinalParse) :
          locale._dayOfMonthOrdinalParseLenient;
    });

    addParseToken(['D', 'DD'], DATE);
    addParseToken('Do', function (input, array) {
        array[DATE] = toInt(input.match(match1to2)[0]);
    });

    // MOMENTS

    var getSetDayOfMonth = makeGetSet('Date', true);

    // FORMATTING

    addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');

    // ALIASES

    addUnitAlias('dayOfYear', 'DDD');

    // PRIORITY
    addUnitPriority('dayOfYear', 4);

    // PARSING

    addRegexToken('DDD',  match1to3);
    addRegexToken('DDDD', match3);
    addParseToken(['DDD', 'DDDD'], function (input, array, config) {
        config._dayOfYear = toInt(input);
    });

    // HELPERS

    // MOMENTS

    function getSetDayOfYear (input) {
        var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
        return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
    }

    // FORMATTING

    addFormatToken('m', ['mm', 2], 0, 'minute');

    // ALIASES

    addUnitAlias('minute', 'm');

    // PRIORITY

    addUnitPriority('minute', 14);

    // PARSING

    addRegexToken('m',  match1to2);
    addRegexToken('mm', match1to2, match2);
    addParseToken(['m', 'mm'], MINUTE);

    // MOMENTS

    var getSetMinute = makeGetSet('Minutes', false);

    // FORMATTING

    addFormatToken('s', ['ss', 2], 0, 'second');

    // ALIASES

    addUnitAlias('second', 's');

    // PRIORITY

    addUnitPriority('second', 15);

    // PARSING

    addRegexToken('s',  match1to2);
    addRegexToken('ss', match1to2, match2);
    addParseToken(['s', 'ss'], SECOND);

    // MOMENTS

    var getSetSecond = makeGetSet('Seconds', false);

    // FORMATTING

    addFormatToken('S', 0, 0, function () {
        return ~~(this.millisecond() / 100);
    });

    addFormatToken(0, ['SS', 2], 0, function () {
        return ~~(this.millisecond() / 10);
    });

    addFormatToken(0, ['SSS', 3], 0, 'millisecond');
    addFormatToken(0, ['SSSS', 4], 0, function () {
        return this.millisecond() * 10;
    });
    addFormatToken(0, ['SSSSS', 5], 0, function () {
        return this.millisecond() * 100;
    });
    addFormatToken(0, ['SSSSSS', 6], 0, function () {
        return this.millisecond() * 1000;
    });
    addFormatToken(0, ['SSSSSSS', 7], 0, function () {
        return this.millisecond() * 10000;
    });
    addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
        return this.millisecond() * 100000;
    });
    addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
        return this.millisecond() * 1000000;
    });


    // ALIASES

    addUnitAlias('millisecond', 'ms');

    // PRIORITY

    addUnitPriority('millisecond', 16);

    // PARSING

    addRegexToken('S',    match1to3, match1);
    addRegexToken('SS',   match1to3, match2);
    addRegexToken('SSS',  match1to3, match3);

    var token;
    for (token = 'SSSS'; token.length <= 9; token += 'S') {
        addRegexToken(token, matchUnsigned);
    }

    function parseMs(input, array) {
        array[MILLISECOND] = toInt(('0.' + input) * 1000);
    }

    for (token = 'S'; token.length <= 9; token += 'S') {
        addParseToken(token, parseMs);
    }
    // MOMENTS

    var getSetMillisecond = makeGetSet('Milliseconds', false);

    // FORMATTING

    addFormatToken('z',  0, 0, 'zoneAbbr');
    addFormatToken('zz', 0, 0, 'zoneName');

    // MOMENTS

    function getZoneAbbr () {
        return this._isUTC ? 'UTC' : '';
    }

    function getZoneName () {
        return this._isUTC ? 'Coordinated Universal Time' : '';
    }

    var proto = Moment.prototype;

    proto.add               = add;
    proto.calendar          = calendar$1;
    proto.clone             = clone;
    proto.diff              = diff;
    proto.endOf             = endOf;
    proto.format            = format;
    proto.from              = from;
    proto.fromNow           = fromNow;
    proto.to                = to;
    proto.toNow             = toNow;
    proto.get               = stringGet;
    proto.invalidAt         = invalidAt;
    proto.isAfter           = isAfter;
    proto.isBefore          = isBefore;
    proto.isBetween         = isBetween;
    proto.isSame            = isSame;
    proto.isSameOrAfter     = isSameOrAfter;
    proto.isSameOrBefore    = isSameOrBefore;
    proto.isValid           = isValid$2;
    proto.lang              = lang;
    proto.locale            = locale;
    proto.localeData        = localeData;
    proto.max               = prototypeMax;
    proto.min               = prototypeMin;
    proto.parsingFlags      = parsingFlags;
    proto.set               = stringSet;
    proto.startOf           = startOf;
    proto.subtract          = subtract;
    proto.toArray           = toArray;
    proto.toObject          = toObject;
    proto.toDate            = toDate;
    proto.toISOString       = toISOString;
    proto.inspect           = inspect;
    proto.toJSON            = toJSON;
    proto.toString          = toString;
    proto.unix              = unix;
    proto.valueOf           = valueOf;
    proto.creationData      = creationData;
    proto.year       = getSetYear;
    proto.isLeapYear = getIsLeapYear;
    proto.weekYear    = getSetWeekYear;
    proto.isoWeekYear = getSetISOWeekYear;
    proto.quarter = proto.quarters = getSetQuarter;
    proto.month       = getSetMonth;
    proto.daysInMonth = getDaysInMonth;
    proto.week           = proto.weeks        = getSetWeek;
    proto.isoWeek        = proto.isoWeeks     = getSetISOWeek;
    proto.weeksInYear    = getWeeksInYear;
    proto.isoWeeksInYear = getISOWeeksInYear;
    proto.date       = getSetDayOfMonth;
    proto.day        = proto.days             = getSetDayOfWeek;
    proto.weekday    = getSetLocaleDayOfWeek;
    proto.isoWeekday = getSetISODayOfWeek;
    proto.dayOfYear  = getSetDayOfYear;
    proto.hour = proto.hours = getSetHour;
    proto.minute = proto.minutes = getSetMinute;
    proto.second = proto.seconds = getSetSecond;
    proto.millisecond = proto.milliseconds = getSetMillisecond;
    proto.utcOffset            = getSetOffset;
    proto.utc                  = setOffsetToUTC;
    proto.local                = setOffsetToLocal;
    proto.parseZone            = setOffsetToParsedOffset;
    proto.hasAlignedHourOffset = hasAlignedHourOffset;
    proto.isDST                = isDaylightSavingTime;
    proto.isLocal              = isLocal;
    proto.isUtcOffset          = isUtcOffset;
    proto.isUtc                = isUtc;
    proto.isUTC                = isUtc;
    proto.zoneAbbr = getZoneAbbr;
    proto.zoneName = getZoneName;
    proto.dates  = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
    proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
    proto.years  = deprecate('years accessor is deprecated. Use year instead', getSetYear);
    proto.zone   = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone);
    proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted);

    function createUnix (input) {
        return createLocal(input * 1000);
    }

    function createInZone () {
        return createLocal.apply(null, arguments).parseZone();
    }

    function preParsePostFormat (string) {
        return string;
    }

    var proto$1 = Locale.prototype;

    proto$1.calendar        = calendar;
    proto$1.longDateFormat  = longDateFormat;
    proto$1.invalidDate     = invalidDate;
    proto$1.ordinal         = ordinal;
    proto$1.preparse        = preParsePostFormat;
    proto$1.postformat      = preParsePostFormat;
    proto$1.relativeTime    = relativeTime;
    proto$1.pastFuture      = pastFuture;
    proto$1.set             = set;

    proto$1.months            =        localeMonths;
    proto$1.monthsShort       =        localeMonthsShort;
    proto$1.monthsParse       =        localeMonthsParse;
    proto$1.monthsRegex       = monthsRegex;
    proto$1.monthsShortRegex  = monthsShortRegex;
    proto$1.week = localeWeek;
    proto$1.firstDayOfYear = localeFirstDayOfYear;
    proto$1.firstDayOfWeek = localeFirstDayOfWeek;

    proto$1.weekdays       =        localeWeekdays;
    proto$1.weekdaysMin    =        localeWeekdaysMin;
    proto$1.weekdaysShort  =        localeWeekdaysShort;
    proto$1.weekdaysParse  =        localeWeekdaysParse;

    proto$1.weekdaysRegex       =        weekdaysRegex;
    proto$1.weekdaysShortRegex  =        weekdaysShortRegex;
    proto$1.weekdaysMinRegex    =        weekdaysMinRegex;

    proto$1.isPM = localeIsPM;
    proto$1.meridiem = localeMeridiem;

    function get$1 (format, index, field, setter) {
        var locale = getLocale();
        var utc = createUTC().set(setter, index);
        return locale[field](utc, format);
    }

    function listMonthsImpl (format, index, field) {
        if (isNumber(format)) {
            index = format;
            format = undefined;
        }

        format = format || '';

        if (index != null) {
            return get$1(format, index, field, 'month');
        }

        var i;
        var out = [];
        for (i = 0; i < 12; i++) {
            out[i] = get$1(format, i, field, 'month');
        }
        return out;
    }

    // ()
    // (5)
    // (fmt, 5)
    // (fmt)
    // (true)
    // (true, 5)
    // (true, fmt, 5)
    // (true, fmt)
    function listWeekdaysImpl (localeSorted, format, index, field) {
        if (typeof localeSorted === 'boolean') {
            if (isNumber(format)) {
                index = format;
                format = undefined;
            }

            format = format || '';
        } else {
            format = localeSorted;
            index = format;
            localeSorted = false;

            if (isNumber(format)) {
                index = format;
                format = undefined;
            }

            format = format || '';
        }

        var locale = getLocale(),
            shift = localeSorted ? locale._week.dow : 0;

        if (index != null) {
            return get$1(format, (index + shift) % 7, field, 'day');
        }

        var i;
        var out = [];
        for (i = 0; i < 7; i++) {
            out[i] = get$1(format, (i + shift) % 7, field, 'day');
        }
        return out;
    }

    function listMonths (format, index) {
        return listMonthsImpl(format, index, 'months');
    }

    function listMonthsShort (format, index) {
        return listMonthsImpl(format, index, 'monthsShort');
    }

    function listWeekdays (localeSorted, format, index) {
        return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
    }

    function listWeekdaysShort (localeSorted, format, index) {
        return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
    }

    function listWeekdaysMin (localeSorted, format, index) {
        return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
    }

    getSetGlobalLocale('en', {
        dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
        ordinal : function (number) {
            var b = number % 10,
                output = (toInt(number % 100 / 10) === 1) ? 'th' :
                (b === 1) ? 'st' :
                (b === 2) ? 'nd' :
                (b === 3) ? 'rd' : 'th';
            return number + output;
        }
    });

    // Side effect imports

    hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale);
    hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale);

    var mathAbs = Math.abs;

    function abs () {
        var data           = this._data;

        this._milliseconds = mathAbs(this._milliseconds);
        this._days         = mathAbs(this._days);
        this._months       = mathAbs(this._months);

        data.milliseconds  = mathAbs(data.milliseconds);
        data.seconds       = mathAbs(data.seconds);
        data.minutes       = mathAbs(data.minutes);
        data.hours         = mathAbs(data.hours);
        data.months        = mathAbs(data.months);
        data.years         = mathAbs(data.years);

        return this;
    }

    function addSubtract$1 (duration, input, value, direction) {
        var other = createDuration(input, value);

        duration._milliseconds += direction * other._milliseconds;
        duration._days         += direction * other._days;
        duration._months       += direction * other._months;

        return duration._bubble();
    }

    // supports only 2.0-style add(1, 's') or add(duration)
    function add$1 (input, value) {
        return addSubtract$1(this, input, value, 1);
    }

    // supports only 2.0-style subtract(1, 's') or subtract(duration)
    function subtract$1 (input, value) {
        return addSubtract$1(this, input, value, -1);
    }

    function absCeil (number) {
        if (number < 0) {
            return Math.floor(number);
        } else {
            return Math.ceil(number);
        }
    }

    function bubble () {
        var milliseconds = this._milliseconds;
        var days         = this._days;
        var months       = this._months;
        var data         = this._data;
        var seconds, minutes, hours, years, monthsFromDays;

        // if we have a mix of positive and negative values, bubble down first
        // check: https://github.com/moment/moment/issues/2166
        if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
                (milliseconds <= 0 && days <= 0 && months <= 0))) {
            milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
            days = 0;
            months = 0;
        }

        // The following code bubbles up values, see the tests for
        // examples of what that means.
        data.milliseconds = milliseconds % 1000;

        seconds           = absFloor(milliseconds / 1000);
        data.seconds      = seconds % 60;

        minutes           = absFloor(seconds / 60);
        data.minutes      = minutes % 60;

        hours             = absFloor(minutes / 60);
        data.hours        = hours % 24;

        days += absFloor(hours / 24);

        // convert days to months
        monthsFromDays = absFloor(daysToMonths(days));
        months += monthsFromDays;
        days -= absCeil(monthsToDays(monthsFromDays));

        // 12 months -> 1 year
        years = absFloor(months / 12);
        months %= 12;

        data.days   = days;
        data.months = months;
        data.years  = years;

        return this;
    }

    function daysToMonths (days) {
        // 400 years have 146097 days (taking into account leap year rules)
        // 400 years have 12 months === 4800
        return days * 4800 / 146097;
    }

    function monthsToDays (months) {
        // the reverse of daysToMonths
        return months * 146097 / 4800;
    }

    function as (units) {
        if (!this.isValid()) {
            return NaN;
        }
        var days;
        var months;
        var milliseconds = this._milliseconds;

        units = normalizeUnits(units);

        if (units === 'month' || units === 'quarter' || units === 'year') {
            days = this._days + milliseconds / 864e5;
            months = this._months + daysToMonths(days);
            switch (units) {
                case 'month':   return months;
                case 'quarter': return months / 3;
                case 'year':    return months / 12;
            }
        } else {
            // handle milliseconds separately because of floating point math errors (issue #1867)
            days = this._days + Math.round(monthsToDays(this._months));
            switch (units) {
                case 'week'   : return days / 7     + milliseconds / 6048e5;
                case 'day'    : return days         + milliseconds / 864e5;
                case 'hour'   : return days * 24    + milliseconds / 36e5;
                case 'minute' : return days * 1440  + milliseconds / 6e4;
                case 'second' : return days * 86400 + milliseconds / 1000;
                // Math.floor prevents floating point math errors here
                case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
                default: throw new Error('Unknown unit ' + units);
            }
        }
    }

    // TODO: Use this.as('ms')?
    function valueOf$1 () {
        if (!this.isValid()) {
            return NaN;
        }
        return (
            this._milliseconds +
            this._days * 864e5 +
            (this._months % 12) * 2592e6 +
            toInt(this._months / 12) * 31536e6
        );
    }

    function makeAs (alias) {
        return function () {
            return this.as(alias);
        };
    }

    var asMilliseconds = makeAs('ms');
    var asSeconds      = makeAs('s');
    var asMinutes      = makeAs('m');
    var asHours        = makeAs('h');
    var asDays         = makeAs('d');
    var asWeeks        = makeAs('w');
    var asMonths       = makeAs('M');
    var asQuarters     = makeAs('Q');
    var asYears        = makeAs('y');

    function clone$1 () {
        return createDuration(this);
    }

    function get$2 (units) {
        units = normalizeUnits(units);
        return this.isValid() ? this[units + 's']() : NaN;
    }

    function makeGetter(name) {
        return function () {
            return this.isValid() ? this._data[name] : NaN;
        };
    }

    var milliseconds = makeGetter('milliseconds');
    var seconds      = makeGetter('seconds');
    var minutes      = makeGetter('minutes');
    var hours        = makeGetter('hours');
    var days         = makeGetter('days');
    var months       = makeGetter('months');
    var years        = makeGetter('years');

    function weeks () {
        return absFloor(this.days() / 7);
    }

    var round = Math.round;
    var thresholds = {
        ss: 44,         // a few seconds to seconds
        s : 45,         // seconds to minute
        m : 45,         // minutes to hour
        h : 22,         // hours to day
        d : 26,         // days to month
        M : 11          // months to year
    };

    // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
    function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
        return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
    }

    function relativeTime$1 (posNegDuration, withoutSuffix, locale) {
        var duration = createDuration(posNegDuration).abs();
        var seconds  = round(duration.as('s'));
        var minutes  = round(duration.as('m'));
        var hours    = round(duration.as('h'));
        var days     = round(duration.as('d'));
        var months   = round(duration.as('M'));
        var years    = round(duration.as('y'));

        var a = seconds <= thresholds.ss && ['s', seconds]  ||
                seconds < thresholds.s   && ['ss', seconds] ||
                minutes <= 1             && ['m']           ||
                minutes < thresholds.m   && ['mm', minutes] ||
                hours   <= 1             && ['h']           ||
                hours   < thresholds.h   && ['hh', hours]   ||
                days    <= 1             && ['d']           ||
                days    < thresholds.d   && ['dd', days]    ||
                months  <= 1             && ['M']           ||
                months  < thresholds.M   && ['MM', months]  ||
                years   <= 1             && ['y']           || ['yy', years];

        a[2] = withoutSuffix;
        a[3] = +posNegDuration > 0;
        a[4] = locale;
        return substituteTimeAgo.apply(null, a);
    }

    // This function allows you to set the rounding function for relative time strings
    function getSetRelativeTimeRounding (roundingFunction) {
        if (roundingFunction === undefined) {
            return round;
        }
        if (typeof(roundingFunction) === 'function') {
            round = roundingFunction;
            return true;
        }
        return false;
    }

    // This function allows you to set a threshold for relative time strings
    function getSetRelativeTimeThreshold (threshold, limit) {
        if (thresholds[threshold] === undefined) {
            return false;
        }
        if (limit === undefined) {
            return thresholds[threshold];
        }
        thresholds[threshold] = limit;
        if (threshold === 's') {
            thresholds.ss = limit - 1;
        }
        return true;
    }

    function humanize (withSuffix) {
        if (!this.isValid()) {
            return this.localeData().invalidDate();
        }

        var locale = this.localeData();
        var output = relativeTime$1(this, !withSuffix, locale);

        if (withSuffix) {
            output = locale.pastFuture(+this, output);
        }

        return locale.postformat(output);
    }

    var abs$1 = Math.abs;

    function sign(x) {
        return ((x > 0) - (x < 0)) || +x;
    }

    function toISOString$1() {
        // for ISO strings we do not use the normal bubbling rules:
        //  * milliseconds bubble up until they become hours
        //  * days do not bubble at all
        //  * months bubble up until they become years
        // This is because there is no context-free conversion between hours and days
        // (think of clock changes)
        // and also not between days and months (28-31 days per month)
        if (!this.isValid()) {
            return this.localeData().invalidDate();
        }

        var seconds = abs$1(this._milliseconds) / 1000;
        var days         = abs$1(this._days);
        var months       = abs$1(this._months);
        var minutes, hours, years;

        // 3600 seconds -> 60 minutes -> 1 hour
        minutes           = absFloor(seconds / 60);
        hours             = absFloor(minutes / 60);
        seconds %= 60;
        minutes %= 60;

        // 12 months -> 1 year
        years  = absFloor(months / 12);
        months %= 12;


        // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
        var Y = years;
        var M = months;
        var D = days;
        var h = hours;
        var m = minutes;
        var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
        var total = this.asSeconds();

        if (!total) {
            // this is the same as C#'s (Noda) and python (isodate)...
            // but not other JS (goog.date)
            return 'P0D';
        }

        var totalSign = total < 0 ? '-' : '';
        var ymSign = sign(this._months) !== sign(total) ? '-' : '';
        var daysSign = sign(this._days) !== sign(total) ? '-' : '';
        var hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';

        return totalSign + 'P' +
            (Y ? ymSign + Y + 'Y' : '') +
            (M ? ymSign + M + 'M' : '') +
            (D ? daysSign + D + 'D' : '') +
            ((h || m || s) ? 'T' : '') +
            (h ? hmsSign + h + 'H' : '') +
            (m ? hmsSign + m + 'M' : '') +
            (s ? hmsSign + s + 'S' : '');
    }

    var proto$2 = Duration.prototype;

    proto$2.isValid        = isValid$1;
    proto$2.abs            = abs;
    proto$2.add            = add$1;
    proto$2.subtract       = subtract$1;
    proto$2.as             = as;
    proto$2.asMilliseconds = asMilliseconds;
    proto$2.asSeconds      = asSeconds;
    proto$2.asMinutes      = asMinutes;
    proto$2.asHours        = asHours;
    proto$2.asDays         = asDays;
    proto$2.asWeeks        = asWeeks;
    proto$2.asMonths       = asMonths;
    proto$2.asQuarters     = asQuarters;
    proto$2.asYears        = asYears;
    proto$2.valueOf        = valueOf$1;
    proto$2._bubble        = bubble;
    proto$2.clone          = clone$1;
    proto$2.get            = get$2;
    proto$2.milliseconds   = milliseconds;
    proto$2.seconds        = seconds;
    proto$2.minutes        = minutes;
    proto$2.hours          = hours;
    proto$2.days           = days;
    proto$2.weeks          = weeks;
    proto$2.months         = months;
    proto$2.years          = years;
    proto$2.humanize       = humanize;
    proto$2.toISOString    = toISOString$1;
    proto$2.toString       = toISOString$1;
    proto$2.toJSON         = toISOString$1;
    proto$2.locale         = locale;
    proto$2.localeData     = localeData;

    proto$2.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString$1);
    proto$2.lang = lang;

    // Side effect imports

    // FORMATTING

    addFormatToken('X', 0, 0, 'unix');
    addFormatToken('x', 0, 0, 'valueOf');

    // PARSING

    addRegexToken('x', matchSigned);
    addRegexToken('X', matchTimestamp);
    addParseToken('X', function (input, array, config) {
        config._d = new Date(parseFloat(input, 10) * 1000);
    });
    addParseToken('x', function (input, array, config) {
        config._d = new Date(toInt(input));
    });

    // Side effect imports


    hooks.version = '2.24.0';

    setHookCallback(createLocal);

    hooks.fn                    = proto;
    hooks.min                   = min;
    hooks.max                   = max;
    hooks.now                   = now;
    hooks.utc                   = createUTC;
    hooks.unix                  = createUnix;
    hooks.months                = listMonths;
    hooks.isDate                = isDate;
    hooks.locale                = getSetGlobalLocale;
    hooks.invalid               = createInvalid;
    hooks.duration              = createDuration;
    hooks.isMoment              = isMoment;
    hooks.weekdays              = listWeekdays;
    hooks.parseZone             = createInZone;
    hooks.localeData            = getLocale;
    hooks.isDuration            = isDuration;
    hooks.monthsShort           = listMonthsShort;
    hooks.weekdaysMin           = listWeekdaysMin;
    hooks.defineLocale          = defineLocale;
    hooks.updateLocale          = updateLocale;
    hooks.locales               = listLocales;
    hooks.weekdaysShort         = listWeekdaysShort;
    hooks.normalizeUnits        = normalizeUnits;
    hooks.relativeTimeRounding  = getSetRelativeTimeRounding;
    hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
    hooks.calendarFormat        = getCalendarFormat;
    hooks.prototype             = proto;

    // currently HTML5 input type only supports 24-hour formats
    hooks.HTML5_FMT = {
        DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm',             // <input type="datetime-local" />
        DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss',  // <input type="datetime-local" step="1" />
        DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS',   // <input type="datetime-local" step="0.001" />
        DATE: 'YYYY-MM-DD',                             // <input type="date" />
        TIME: 'HH:mm',                                  // <input type="time" />
        TIME_SECONDS: 'HH:mm:ss',                       // <input type="time" step="1" />
        TIME_MS: 'HH:mm:ss.SSS',                        // <input type="time" step="0.001" />
        WEEK: 'GGGG-[W]WW',                             // <input type="week" />
        MONTH: 'YYYY-MM'                                // <input type="month" />
    };

    return hooks;

})));

},{}],11:[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; };

},{}],12:[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 : {})
},{}],13:[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]';
};

},{}],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';

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;
};

},{}],15:[function(require,module,exports){
'use strict';

exports.decode = exports.parse = require('./decode');
exports.encode = exports.stringify = require('./encode');

},{"./decode":13,"./encode":14}],16:[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":3,"charenc":4,"crypt":6}],17:[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":11,"timers":17}],18:[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":19,"./lib/domain.js":20,"./lib/is-ip.js":22,"./lib/is-valid.js":23,"./lib/public-suffix.js":24,"./lib/subdomain.js":25,"./lib/suffix-trie.js":26,"./lib/tld-exists.js":27,"./rules.json":28}],19:[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":23,"url":29}],20:[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);
};

},{}],21:[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);
};

},{}],22:[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));
};

},{}],23:[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
  );
};

},{}],24:[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":21}],25:[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);
};

},{}],26:[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;

},{}],27:[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":21}],28:[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}}}
},{}],29:[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":30,"punycode":12,"querystring":15}],30:[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;
  }
};

},{}],31:[function(require,module,exports){
module.exports = Interface;

const m = require("mithril");
const Moment = require("moment");
const SearchInterface = require("./searchinterface");
const helpers = require("../helpers");

const LATEST_NATIVE_APP_VERSION = 3000003;

/**
 * Popup main interface
 *
 * @since 3.0.0
 *
 * @param object settings Settings object
 * @param array  logins   Array of available logins
 * @return void
 */
function Interface(settings, logins) {
    // public methods
    this.attach = attach;
    this.view = view;
    this.search = search;

    // fields
    this.settings = settings;
    this.logins = logins;
    this.results = [];
    this.currentDomainOnly = !settings.tab.url.match(/^(chrome|about):/);
    this.searchPart = new SearchInterface(this);

    // initialise with empty search
    this.search("");
}

/**
 * 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(this.searchPart));

    nodes.push(
        m(
            "div.logins",
            this.results.map(function(result) {
                const storeBgColor = result.store.bgColor || result.store.settings.bgColor;
                const storeColor = result.store.color || result.store.settings.color;

                return m(
                    "div.part.login",
                    {
                        key: result.index,
                        tabindex: 0,
                        onclick: function(e) {
                            var action = e.target.getAttribute("action");
                            if (action) {
                                result.doAction(action);
                            } else {
                                result.doAction("fill");
                            }
                        },
                        onkeydown: keyHandler.bind(result)
                    },
                    [
                        m("div.name", [
                            m("div.line1", [
                                m(
                                    "div.store.badge",
                                    {
                                        style: `background-color: ${storeBgColor};
                                                color: ${storeColor}`
                                    },
                                    result.store.name
                                ),
                                m("div.path", [m.trust(result.path)]),
                                result.recent.when > 0
                                    ? m("div.recent", {
                                          title:
                                              "Used here " +
                                              result.recent.count +
                                              " time" +
                                              (result.recent.count > 1 ? "s" : "") +
                                              ", last " +
                                              Moment(new Date(result.recent.when)).fromNow()
                                      })
                                    : null
                            ]),
                            m("div.line2", [m.trust(result.display)])
                        ]),
                        m("div.action.copy-password", {
                            tabindex: 0,
                            title: "Copy password",
                            action: "copyPassword"
                        }),
                        m("div.action.copy-user", {
                            tabindex: 0,
                            title: "Copy username",
                            action: "copyUsername"
                        })
                    ]
                );
            })
        )
    );

    if (this.settings.version < LATEST_NATIVE_APP_VERSION) {
        nodes.push(
            m("div.updates", [
                m("span", "Update native host app: "),
                m(
                    "a",
                    {
                        href: "https://github.com/browserpass/browserpass-native#installation",
                        target: "_blank"
                    },
                    "instructions"
                )
            ])
        );
    }

    return nodes;
}

/**
 * Run a search
 *
 * @param string searchQuery Search query
 * @return void
 */
function search(searchQuery) {
    this.results = helpers.filterSortLogins(this.logins, searchQuery, this.currentDomainOnly);
}

/**
 * Handle result key presses
 *
 * @param Event  e    Keydown event
 * @param object this Result object
 * @return void
 */
function keyHandler(e) {
    e.preventDefault();
    var login = e.target.classList.contains("login") ? e.target : e.target.closest(".login");
    switch (e.code) {
        case "Tab":
            var partElement = e.target.closest(".part");
            var targetElement = e.shiftKey ? "previousElementSibling" : "nextElementSibling";
            if (partElement[targetElement] && partElement[targetElement].hasAttribute("tabindex")) {
                partElement[targetElement].focus();
            } else {
                document.querySelector(".part.search input[type=text]").focus();
            }
            break;
        case "ArrowDown":
            if (login.nextElementSibling) {
                login.nextElementSibling.focus();
            }
            break;
        case "ArrowUp":
            if (login.previousElementSibling) {
                login.previousElementSibling.focus();
            } else {
                document.querySelector(".part.search input[type=text]").focus();
            }
            break;
        case "ArrowRight":
            if (e.target.classList.contains("login")) {
                e.target.querySelector(".action").focus();
            } else if (e.target.nextElementSibling) {
                e.target.nextElementSibling.focus();
            }
            break;
        case "ArrowLeft":
            if (e.target.previousElementSibling.classList.contains("action")) {
                e.target.previousElementSibling.focus();
            } else {
                login.focus();
            }
            break;
        case "Enter":
            if (e.target.hasAttribute("action")) {
                this.doAction(e.target.getAttribute("action"));
            } else {
                this.doAction("fill");
            }
            break;
        case "KeyC":
            if (e.ctrlKey) {
                this.doAction(e.shiftKey ? "copyUsername" : "copyPassword");
            }
            break;
        case "KeyG":
            if (e.ctrlKey) {
                this.doAction(e.shiftKey ? "launchInNewTab" : "launch");
            }
            break;
    }
}

},{"../helpers":1,"./searchinterface":33,"mithril":9,"moment":10}],32:[function(require,module,exports){
//------------------------------------- Initialisation --------------------------------------//
"use strict";

require("chrome-extension-async");
const Interface = require("./interface");
const helpers = require("../helpers");

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);
}

/**
 * Run the main popup logic
 *
 * @since 3.0.0
 *
 * @return void
 */
async function run() {
    try {
        var response = await chrome.runtime.sendMessage({ action: "getSettings" });
        if (response.status != "ok") {
            throw new Error(response.message);
        }
        var settings = response.settings;

        if (settings.hasOwnProperty("hostError")) {
            throw new Error(settings.hostError.params.message);
        }

        if (typeof settings.host === "undefined") {
            throw new Error("Unable to retrieve current tab information");
        }

        // get list of logins
        response = await chrome.runtime.sendMessage({ action: "listFiles" });
        if (response.status != "ok") {
            throw new Error(response.message);
        }

        const logins = helpers.prepareLogins(response.files, settings);
        for (let login of logins) {
            login.doAction = withLogin.bind({ settings: settings, login: login });
        }

        var popup = new Interface(settings, logins);
        popup.attach(document.body);
    } catch (e) {
        handleError(e);
    }
}

/**
 * Do a login action
 *
 * @since 3.0.0
 *
 * @param string action Action to take
 * @return void
 */
async function withLogin(action) {
    try {
        // replace popup with a "please wait" notice
        switch (action) {
            case "fill":
                handleError("Filling login details...", "notice");
                break;
            case "launch":
                handleError("Launching URL...", "notice");
                break;
            case "launchInNewTab":
                handleError("Launching URL in a new tab...", "notice");
                break;
            case "copyPassword":
                handleError("Copying password to clipboard...", "notice");
                break;
            case "copyUsername":
                handleError("Copying username to clipboard...", "notice");
                break;
            default:
                handleError("Please wait...", "notice");
                break;
        }

        // Firefox requires data to be serializable,
        // this removes everything offending such as functions
        const login = JSON.parse(JSON.stringify(this.login));

        // hand off action to background script
        var response = await chrome.runtime.sendMessage({
            action: action,
            login: login
        });
        if (response.status != "ok") {
            throw new Error(response.message);
        } else {
            window.close();
        }
    } catch (e) {
        handleError(e);
    }
}

},{"../helpers":1,"./interface":31,"chrome-extension-async":5}],33:[function(require,module,exports){
module.exports = SearchInterface;

const m = require("mithril");

/**
 * Search interface
 *
 * @since 3.0.0
 *
 * @param object interface Popup main interface
 * @return void
 */
function SearchInterface(popup) {
    // public methods
    this.view = view;

    // fields
    this.popup = popup;
}

/**
 * Generates vnodes for render
 *
 * @since 3.0.0
 *
 * @param function ctl    Controller
 * @param object   params Runtime params
 * @return []Vnode
 */
function view(ctl, params) {
    var self = this;
    return m(
        "form.part.search",
        {
            onkeydown: function(e) {
                switch (e.code) {
                    case "Tab":
                        e.preventDefault();
                        if (e.shiftKey) {
                            document.querySelector(".part.login:last-child").focus();
                            break;
                        }
                    // fall through to ArrowDown
                    case "ArrowDown":
                        e.preventDefault();
                        if (self.popup.results.length) {
                            document.querySelector("*[tabindex]").focus();
                        }
                        break;
                    case "Enter":
                        e.preventDefault();
                        if (self.popup.results.length) {
                            self.popup.results[0].doAction("fill");
                        }
                        break;
                }
            }
        },
        [
            this.popup.currentDomainOnly
                ? m("div.hint.badge", [
                      this.popup.settings.host,
                      m("div.remove-hint", {
                          onclick: function(e) {
                              var target = document.querySelector(
                                  ".part.search > input[type=text]"
                              );
                              target.focus();
                              self.popup.currentDomainOnly = false;
                              self.popup.search(target.value);
                          }
                      })
                  ])
                : null,
            m("input[type=text]", {
                focused: true,
                placeholder: "Search logins...",
                oncreate: function(e) {
                    e.dom.focus();
                },
                oninput: function(e) {
                    self.popup.search(e.target.value);
                },
                onkeydown: function(e) {
                    switch (e.code) {
                        case "Backspace":
                            if (self.popup.currentDomainOnly) {
                                if (e.target.value.length == 0) {
                                    self.popup.currentDomainOnly = false;
                                    self.popup.search("");
                                } else if (
                                    e.target.selectionStart == 0 &&
                                    e.target.selectionEnd == 0
                                ) {
                                    self.popup.currentDomainOnly = false;
                                    self.popup.search(e.target.value);
                                }
                            }
                            break;
                        case "KeyC":
                            if (e.ctrlKey && e.target.selectionStart == e.target.selectionEnd) {
                                e.preventDefault();
                                self.popup.results[0].doAction(
                                    e.shiftKey ? "copyUsername" : "copyPassword"
                                );
                            }
                            break;
                        case "KeyG":
                            if (e.ctrlKey && e.target.selectionStart == e.target.selectionEnd) {
                                e.preventDefault();
                                self.popup.results[0].doAction(
                                    e.shiftKey ? "launchInNewTab" : "launch"
                                );
                            }
                            break;
                    }
                }
            })
        ]
    );
}

},{"mithril":9}]},{},[32]);
