(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
    typeof define === 'function' && define.amd ? define(['exports'], factory) :
    (factory((global.svelte = {})));
}(this, (function (exports) { 'use strict';

    /*! *****************************************************************************
    Copyright (c) Microsoft Corporation. All rights reserved.
    Licensed under the Apache License, Version 2.0 (the "License"); you may not use
    this file except in compliance with the License. You may obtain a copy of the
    License at http://www.apache.org/licenses/LICENSE-2.0

    THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
    WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
    MERCHANTABLITY OR NON-INFRINGEMENT.

    See the Apache Version 2.0 License for specific language governing permissions
    and limitations under the License.
    ***************************************************************************** */

    function __awaiter(thisArg, _arguments, P, generator) {
        return new (P || (P = Promise))(function (resolve, reject) {
            function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
            function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
            function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
            step((generator = generator.apply(thisArg, _arguments || [])).next());
        });
    }

    // Reserved word lists for various dialects of the language

    var reservedWords = {
      3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile",
      5: "class enum extends super const export import",
      6: "enum",
      strict: "implements interface let package private protected public static yield",
      strictBind: "eval arguments"
    };

    // And the keywords

    var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this";

    var keywords = {
      5: ecma5AndLessKeywords,
      6: ecma5AndLessKeywords + " const class extends export import super"
    };

    var keywordRelationalOperator = /^in(stanceof)?$/;

    // ## Character categories

    // Big ugly regular expressions that match characters in the
    // whitespace, identifier, and identifier-start categories. These
    // are only applied when a character is found to actually have a
    // code point above 128.
    // Generated by `bin/generate-identifier-regex.js`.

    var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08bd\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312e\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fea\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7ae\ua7b0-\ua7b7\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab65\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
    var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d4-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c03\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2-\u1cf4\u1cf7-\u1cf9\u1dc0-\u1df9\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua900-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f";

    var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
    var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");

    nonASCIIidentifierStartChars = nonASCIIidentifierChars = null;

    // These are a run-length and offset encoded representation of the
    // >0xffff code points that are a valid part of identifiers. The
    // offset starts at 0x10000, and each pair of numbers represents an
    // offset to the next range, and then a size of the range. They were
    // generated by bin/generate-identifier-regex.js

    // eslint-disable-next-line comma-spacing
    var astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,14,29,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,26,45,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,785,52,76,44,33,24,27,35,42,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,54,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,86,25,391,63,32,0,257,0,11,39,8,0,22,0,12,39,3,3,55,56,264,8,2,36,18,0,50,29,113,6,2,1,2,37,22,0,698,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,881,68,12,0,67,12,65,1,31,6124,20,754,9486,286,82,395,2309,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,4149,196,60,67,1213,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42710,42,4148,12,221,3,5761,15,7472,3104,541];

    // eslint-disable-next-line comma-spacing
    var astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,1306,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,52,0,13,2,49,13,10,2,4,9,83,11,7,0,161,11,6,9,7,3,57,0,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,87,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,423,9,280,9,41,6,2,3,9,0,10,10,47,15,406,7,2,7,17,9,57,21,2,13,123,5,4,0,2,1,2,6,2,0,9,9,19719,9,135,4,60,6,26,9,1016,45,17,3,19723,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,2214,6,110,6,6,9,792487,239];

    // This has a complexity linear to the value of the code. The
    // assumption is that looking up astral identifier characters is
    // rare.
    function isInAstralSet(code, set) {
      var pos = 0x10000;
      for (var i = 0; i < set.length; i += 2) {
        pos += set[i];
        if (pos > code) { return false }
        pos += set[i + 1];
        if (pos >= code) { return true }
      }
    }

    // Test whether a given character code starts an identifier.

    function isIdentifierStart(code, astral) {
      if (code < 65) { return code === 36 }
      if (code < 91) { return true }
      if (code < 97) { return code === 95 }
      if (code < 123) { return true }
      if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) }
      if (astral === false) { return false }
      return isInAstralSet(code, astralIdentifierStartCodes)
    }

    // Test whether a given character is part of an identifier.

    function isIdentifierChar(code, astral) {
      if (code < 48) { return code === 36 }
      if (code < 58) { return true }
      if (code < 65) { return false }
      if (code < 91) { return true }
      if (code < 97) { return code === 95 }
      if (code < 123) { return true }
      if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) }
      if (astral === false) { return false }
      return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes)
    }

    // ## Token types

    // The assignment of fine-grained, information-carrying type objects
    // allows the tokenizer to store the information it has about a
    // token in a way that is very cheap for the parser to look up.

    // All token type variables start with an underscore, to make them
    // easy to recognize.

    // The `beforeExpr` property is used to disambiguate between regular
    // expressions and divisions. It is set on all token types that can
    // be followed by an expression (thus, a slash after them would be a
    // regular expression).
    //
    // The `startsExpr` property is used to check if the token ends a
    // `yield` expression. It is set on all token types that either can
    // directly start an expression (like a quotation mark) or can
    // continue an expression (like the body of a string).
    //
    // `isLoop` marks a keyword as starting a loop, which is important
    // to know when parsing a label, in order to allow or disallow
    // continue jumps to that label.

    var TokenType = function TokenType(label, conf) {
      if ( conf === void 0 ) conf = {};

      this.label = label;
      this.keyword = conf.keyword;
      this.beforeExpr = !!conf.beforeExpr;
      this.startsExpr = !!conf.startsExpr;
      this.isLoop = !!conf.isLoop;
      this.isAssign = !!conf.isAssign;
      this.prefix = !!conf.prefix;
      this.postfix = !!conf.postfix;
      this.binop = conf.binop || null;
      this.updateContext = null;
    };

    function binop(name, prec) {
      return new TokenType(name, {beforeExpr: true, binop: prec})
    }
    var beforeExpr = {beforeExpr: true};
    var startsExpr = {startsExpr: true};

    // Map keyword names to token types.

    var keywords$1 = {};

    // Succinct definitions of keyword token types
    function kw(name, options) {
      if ( options === void 0 ) options = {};

      options.keyword = name;
      return keywords$1[name] = new TokenType(name, options)
    }

    var types = {
      num: new TokenType("num", startsExpr),
      regexp: new TokenType("regexp", startsExpr),
      string: new TokenType("string", startsExpr),
      name: new TokenType("name", startsExpr),
      eof: new TokenType("eof"),

      // Punctuation token types.
      bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}),
      bracketR: new TokenType("]"),
      braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}),
      braceR: new TokenType("}"),
      parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}),
      parenR: new TokenType(")"),
      comma: new TokenType(",", beforeExpr),
      semi: new TokenType(";", beforeExpr),
      colon: new TokenType(":", beforeExpr),
      dot: new TokenType("."),
      question: new TokenType("?", beforeExpr),
      arrow: new TokenType("=>", beforeExpr),
      template: new TokenType("template"),
      invalidTemplate: new TokenType("invalidTemplate"),
      ellipsis: new TokenType("...", beforeExpr),
      backQuote: new TokenType("`", startsExpr),
      dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}),

      // Operators. These carry several kinds of properties to help the
      // parser use them properly (the presence of these properties is
      // what categorizes them as operators).
      //
      // `binop`, when present, specifies that this operator is a binary
      // operator, and will refer to its precedence.
      //
      // `prefix` and `postfix` mark the operator as a prefix or postfix
      // unary operator.
      //
      // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
      // binary operators with a very low precedence, that should result
      // in AssignmentExpression nodes.

      eq: new TokenType("=", {beforeExpr: true, isAssign: true}),
      assign: new TokenType("_=", {beforeExpr: true, isAssign: true}),
      incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}),
      prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}),
      logicalOR: binop("||", 1),
      logicalAND: binop("&&", 2),
      bitwiseOR: binop("|", 3),
      bitwiseXOR: binop("^", 4),
      bitwiseAND: binop("&", 5),
      equality: binop("==/!=/===/!==", 6),
      relational: binop("</>/<=/>=", 7),
      bitShift: binop("<</>>/>>>", 8),
      plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}),
      modulo: binop("%", 10),
      star: binop("*", 10),
      slash: binop("/", 10),
      starstar: new TokenType("**", {beforeExpr: true}),

      // Keyword token types.
      _break: kw("break"),
      _case: kw("case", beforeExpr),
      _catch: kw("catch"),
      _continue: kw("continue"),
      _debugger: kw("debugger"),
      _default: kw("default", beforeExpr),
      _do: kw("do", {isLoop: true, beforeExpr: true}),
      _else: kw("else", beforeExpr),
      _finally: kw("finally"),
      _for: kw("for", {isLoop: true}),
      _function: kw("function", startsExpr),
      _if: kw("if"),
      _return: kw("return", beforeExpr),
      _switch: kw("switch"),
      _throw: kw("throw", beforeExpr),
      _try: kw("try"),
      _var: kw("var"),
      _const: kw("const"),
      _while: kw("while", {isLoop: true}),
      _with: kw("with"),
      _new: kw("new", {beforeExpr: true, startsExpr: true}),
      _this: kw("this", startsExpr),
      _super: kw("super", startsExpr),
      _class: kw("class", startsExpr),
      _extends: kw("extends", beforeExpr),
      _export: kw("export"),
      _import: kw("import"),
      _null: kw("null", startsExpr),
      _true: kw("true", startsExpr),
      _false: kw("false", startsExpr),
      _in: kw("in", {beforeExpr: true, binop: 7}),
      _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}),
      _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}),
      _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}),
      _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true})
    };

    // Matches a whole line break (where CRLF is considered a single
    // line break). Used to count lines.

    var lineBreak = /\r\n?|\n|\u2028|\u2029/;
    var lineBreakG = new RegExp(lineBreak.source, "g");

    function isNewLine(code) {
      return code === 10 || code === 13 || code === 0x2028 || code === 0x2029
    }

    var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/;

    var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g;

    var ref = Object.prototype;
    var hasOwnProperty = ref.hasOwnProperty;
    var toString = ref.toString;

    // Checks if an object has a property.

    function has(obj, propName) {
      return hasOwnProperty.call(obj, propName)
    }

    var isArray = Array.isArray || (function (obj) { return (
      toString.call(obj) === "[object Array]"
    ); });

    // These are used when `options.locations` is on, for the
    // `startLoc` and `endLoc` properties.

    var Position = function Position(line, col) {
      this.line = line;
      this.column = col;
    };

    Position.prototype.offset = function offset (n) {
      return new Position(this.line, this.column + n)
    };

    var SourceLocation = function SourceLocation(p, start, end) {
      this.start = start;
      this.end = end;
      if (p.sourceFile !== null) { this.source = p.sourceFile; }
    };

    // The `getLineInfo` function is mostly useful when the
    // `locations` option is off (for performance reasons) and you
    // want to find the line/column position for a given character
    // offset. `input` should be the code string that the offset refers
    // into.

    function getLineInfo(input, offset) {
      for (var line = 1, cur = 0;;) {
        lineBreakG.lastIndex = cur;
        var match = lineBreakG.exec(input);
        if (match && match.index < offset) {
          ++line;
          cur = match.index + match[0].length;
        } else {
          return new Position(line, offset - cur)
        }
      }
    }

    // A second optional argument can be given to further configure
    // the parser process. These options are recognized:

    var defaultOptions = {
      // `ecmaVersion` indicates the ECMAScript version to parse. Must
      // be either 3, 5, 6 (2015), 7 (2016), or 8 (2017). This influences support
      // for strict mode, the set of reserved words, and support for
      // new syntax features. The default is 7.
      ecmaVersion: 7,
      // `sourceType` indicates the mode the code should be parsed in.
      // Can be either `"script"` or `"module"`. This influences global
      // strict mode and parsing of `import` and `export` declarations.
      sourceType: "script",
      // `onInsertedSemicolon` can be a callback that will be called
      // when a semicolon is automatically inserted. It will be passed
      // th position of the comma as an offset, and if `locations` is
      // enabled, it is given the location as a `{line, column}` object
      // as second argument.
      onInsertedSemicolon: null,
      // `onTrailingComma` is similar to `onInsertedSemicolon`, but for
      // trailing commas.
      onTrailingComma: null,
      // By default, reserved words are only enforced if ecmaVersion >= 5.
      // Set `allowReserved` to a boolean value to explicitly turn this on
      // an off. When this option has the value "never", reserved words
      // and keywords can also not be used as property names.
      allowReserved: null,
      // When enabled, a return at the top level is not considered an
      // error.
      allowReturnOutsideFunction: false,
      // When enabled, import/export statements are not constrained to
      // appearing at the top of the program.
      allowImportExportEverywhere: false,
      // When enabled, hashbang directive in the beginning of file
      // is allowed and treated as a line comment.
      allowHashBang: false,
      // When `locations` is on, `loc` properties holding objects with
      // `start` and `end` properties in `{line, column}` form (with
      // line being 1-based and column 0-based) will be attached to the
      // nodes.
      locations: false,
      // A function can be passed as `onToken` option, which will
      // cause Acorn to call that function with object in the same
      // format as tokens returned from `tokenizer().getToken()`. Note
      // that you are not allowed to call the parser from the
      // callback—that will corrupt its internal state.
      onToken: null,
      // A function can be passed as `onComment` option, which will
      // cause Acorn to call that function with `(block, text, start,
      // end)` parameters whenever a comment is skipped. `block` is a
      // boolean indicating whether this is a block (`/* */`) comment,
      // `text` is the content of the comment, and `start` and `end` are
      // character offsets that denote the start and end of the comment.
      // When the `locations` option is on, two more parameters are
      // passed, the full `{line, column}` locations of the start and
      // end of the comments. Note that you are not allowed to call the
      // parser from the callback—that will corrupt its internal state.
      onComment: null,
      // Nodes have their start and end characters offsets recorded in
      // `start` and `end` properties (directly on the node, rather than
      // the `loc` object, which holds line/column data. To also add a
      // [semi-standardized][range] `range` property holding a `[start,
      // end]` array with the same numbers, set the `ranges` option to
      // `true`.
      //
      // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
      ranges: false,
      // It is possible to parse multiple files into a single AST by
      // passing the tree produced by parsing the first file as
      // `program` option in subsequent parses. This will add the
      // toplevel forms of the parsed file to the `Program` (top) node
      // of an existing parse tree.
      program: null,
      // When `locations` is on, you can pass this to record the source
      // file in every node's `loc` object.
      sourceFile: null,
      // This value, if given, is stored in every node, whether
      // `locations` is on or off.
      directSourceFile: null,
      // When enabled, parenthesized expressions are represented by
      // (non-standard) ParenthesizedExpression nodes
      preserveParens: false,
      plugins: {}
    };

    // Interpret and default an options object

    function getOptions(opts) {
      var options = {};

      for (var opt in defaultOptions)
        { options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; }

      if (options.ecmaVersion >= 2015)
        { options.ecmaVersion -= 2009; }

      if (options.allowReserved == null)
        { options.allowReserved = options.ecmaVersion < 5; }

      if (isArray(options.onToken)) {
        var tokens = options.onToken;
        options.onToken = function (token) { return tokens.push(token); };
      }
      if (isArray(options.onComment))
        { options.onComment = pushComment(options, options.onComment); }

      return options
    }

    function pushComment(options, array) {
      return function(block, text, start, end, startLoc, endLoc) {
        var comment = {
          type: block ? "Block" : "Line",
          value: text,
          start: start,
          end: end
        };
        if (options.locations)
          { comment.loc = new SourceLocation(this, startLoc, endLoc); }
        if (options.ranges)
          { comment.range = [start, end]; }
        array.push(comment);
      }
    }

    // Registered plugins
    var plugins = {};

    function keywordRegexp(words) {
      return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$")
    }

    var Parser = function Parser(options, input, startPos) {
      this.options = options = getOptions(options);
      this.sourceFile = options.sourceFile;
      this.keywords = keywordRegexp(keywords[options.ecmaVersion >= 6 ? 6 : 5]);
      var reserved = "";
      if (!options.allowReserved) {
        for (var v = options.ecmaVersion;; v--)
          { if (reserved = reservedWords[v]) { break } }
        if (options.sourceType == "module") { reserved += " await"; }
      }
      this.reservedWords = keywordRegexp(reserved);
      var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict;
      this.reservedWordsStrict = keywordRegexp(reservedStrict);
      this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords.strictBind);
      this.input = String(input);

      // Used to signal to callers of `readWord1` whether the word
      // contained any escape sequences. This is needed because words with
      // escape sequences must not be interpreted as keywords.
      this.containsEsc = false;

      // Load plugins
      this.loadPlugins(options.plugins);

      // Set up token state

      // The current position of the tokenizer in the input.
      if (startPos) {
        this.pos = startPos;
        this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1;
        this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length;
      } else {
        this.pos = this.lineStart = 0;
        this.curLine = 1;
      }

      // Properties of the current token:
      // Its type
      this.type = types.eof;
      // For tokens that include more information than their type, the value
      this.value = null;
      // Its start and end offset
      this.start = this.end = this.pos;
      // And, if locations are used, the {line, column} object
      // corresponding to those offsets
      this.startLoc = this.endLoc = this.curPosition();

      // Position information for the previous token
      this.lastTokEndLoc = this.lastTokStartLoc = null;
      this.lastTokStart = this.lastTokEnd = this.pos;

      // The context stack is used to superficially track syntactic
      // context to predict whether a regular expression is allowed in a
      // given position.
      this.context = this.initialContext();
      this.exprAllowed = true;

      // Figure out if it's a module code.
      this.inModule = options.sourceType === "module";
      this.strict = this.inModule || this.strictDirective(this.pos);

      // Used to signify the start of a potential arrow function
      this.potentialArrowAt = -1;

      // Flags to track whether we are in a function, a generator, an async function.
      this.inFunction = this.inGenerator = this.inAsync = false;
      // Positions to delayed-check that yield/await does not exist in default parameters.
      this.yieldPos = this.awaitPos = 0;
      // Labels in scope.
      this.labels = [];

      // If enabled, skip leading hashbang line.
      if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!")
        { this.skipLineComment(2); }

      // Scope tracking for duplicate variable names (see scope.js)
      this.scopeStack = [];
      this.enterFunctionScope();

      // For RegExp validation
      this.regexpState = null;
    };

    // DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them
    Parser.prototype.isKeyword = function isKeyword (word) { return this.keywords.test(word) };
    Parser.prototype.isReservedWord = function isReservedWord (word) { return this.reservedWords.test(word) };

    Parser.prototype.extend = function extend (name, f) {
      this[name] = f(this[name]);
    };

    Parser.prototype.loadPlugins = function loadPlugins (pluginConfigs) {
        var this$1 = this;

      for (var name in pluginConfigs) {
        var plugin = plugins[name];
        if (!plugin) { throw new Error("Plugin '" + name + "' not found") }
        plugin(this$1, pluginConfigs[name]);
      }
    };

    Parser.prototype.parse = function parse () {
      var node = this.options.program || this.startNode();
      this.nextToken();
      return this.parseTopLevel(node)
    };

    var pp = Parser.prototype;

    // ## Parser utilities

    var literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)"|;)/;
    pp.strictDirective = function(start) {
      var this$1 = this;

      for (;;) {
        skipWhiteSpace.lastIndex = start;
        start += skipWhiteSpace.exec(this$1.input)[0].length;
        var match = literal.exec(this$1.input.slice(start));
        if (!match) { return false }
        if ((match[1] || match[2]) == "use strict") { return true }
        start += match[0].length;
      }
    };

    // Predicate that tests whether the next token is of the given
    // type, and if yes, consumes it as a side effect.

    pp.eat = function(type) {
      if (this.type === type) {
        this.next();
        return true
      } else {
        return false
      }
    };

    // Tests whether parsed token is a contextual keyword.

    pp.isContextual = function(name) {
      return this.type === types.name && this.value === name && !this.containsEsc
    };

    // Consumes contextual keyword if possible.

    pp.eatContextual = function(name) {
      if (!this.isContextual(name)) { return false }
      this.next();
      return true
    };

    // Asserts that following token is given contextual keyword.

    pp.expectContextual = function(name) {
      if (!this.eatContextual(name)) { this.unexpected(); }
    };

    // Test whether a semicolon can be inserted at the current position.

    pp.canInsertSemicolon = function() {
      return this.type === types.eof ||
        this.type === types.braceR ||
        lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
    };

    pp.insertSemicolon = function() {
      if (this.canInsertSemicolon()) {
        if (this.options.onInsertedSemicolon)
          { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); }
        return true
      }
    };

    // Consume a semicolon, or, failing that, see if we are allowed to
    // pretend that there is a semicolon at this position.

    pp.semicolon = function() {
      if (!this.eat(types.semi) && !this.insertSemicolon()) { this.unexpected(); }
    };

    pp.afterTrailingComma = function(tokType, notNext) {
      if (this.type == tokType) {
        if (this.options.onTrailingComma)
          { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); }
        if (!notNext)
          { this.next(); }
        return true
      }
    };

    // Expect a token of a given type. If found, consume it, otherwise,
    // raise an unexpected token error.

    pp.expect = function(type) {
      this.eat(type) || this.unexpected();
    };

    // Raise an unexpected token error.

    pp.unexpected = function(pos) {
      this.raise(pos != null ? pos : this.start, "Unexpected token");
    };

    function DestructuringErrors() {
      this.shorthandAssign =
      this.trailingComma =
      this.parenthesizedAssign =
      this.parenthesizedBind =
      this.doubleProto =
        -1;
    }

    pp.checkPatternErrors = function(refDestructuringErrors, isAssign) {
      if (!refDestructuringErrors) { return }
      if (refDestructuringErrors.trailingComma > -1)
        { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); }
      var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind;
      if (parens > -1) { this.raiseRecoverable(parens, "Parenthesized pattern"); }
    };

    pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) {
      if (!refDestructuringErrors) { return false }
      var shorthandAssign = refDestructuringErrors.shorthandAssign;
      var doubleProto = refDestructuringErrors.doubleProto;
      if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 }
      if (shorthandAssign >= 0)
        { this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); }
      if (doubleProto >= 0)
        { this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); }
    };

    pp.checkYieldAwaitInDefaultParams = function() {
      if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos))
        { this.raise(this.yieldPos, "Yield expression cannot be a default value"); }
      if (this.awaitPos)
        { this.raise(this.awaitPos, "Await expression cannot be a default value"); }
    };

    pp.isSimpleAssignTarget = function(expr) {
      if (expr.type === "ParenthesizedExpression")
        { return this.isSimpleAssignTarget(expr.expression) }
      return expr.type === "Identifier" || expr.type === "MemberExpression"
    };

    var pp$1 = Parser.prototype;

    // ### Statement parsing

    // Parse a program. Initializes the parser, reads any number of
    // statements, and wraps them in a Program node.  Optionally takes a
    // `program` argument.  If present, the statements will be appended
    // to its body instead of creating a new node.

    pp$1.parseTopLevel = function(node) {
      var this$1 = this;

      var exports = {};
      if (!node.body) { node.body = []; }
      while (this.type !== types.eof) {
        var stmt = this$1.parseStatement(true, true, exports);
        node.body.push(stmt);
      }
      this.adaptDirectivePrologue(node.body);
      this.next();
      if (this.options.ecmaVersion >= 6) {
        node.sourceType = this.options.sourceType;
      }
      return this.finishNode(node, "Program")
    };

    var loopLabel = {kind: "loop"};
    var switchLabel = {kind: "switch"};

    pp$1.isLet = function() {
      if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false }
      skipWhiteSpace.lastIndex = this.pos;
      var skip = skipWhiteSpace.exec(this.input);
      var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next);
      if (nextCh === 91 || nextCh == 123) { return true } // '{' and '['
      if (isIdentifierStart(nextCh, true)) {
        var pos = next + 1;
        while (isIdentifierChar(this.input.charCodeAt(pos), true)) { ++pos; }
        var ident = this.input.slice(next, pos);
        if (!keywordRelationalOperator.test(ident)) { return true }
      }
      return false
    };

    // check 'async [no LineTerminator here] function'
    // - 'async /*foo*/ function' is OK.
    // - 'async /*\n*/ function' is invalid.
    pp$1.isAsyncFunction = function() {
      if (this.options.ecmaVersion < 8 || !this.isContextual("async"))
        { return false }

      skipWhiteSpace.lastIndex = this.pos;
      var skip = skipWhiteSpace.exec(this.input);
      var next = this.pos + skip[0].length;
      return !lineBreak.test(this.input.slice(this.pos, next)) &&
        this.input.slice(next, next + 8) === "function" &&
        (next + 8 == this.input.length || !isIdentifierChar(this.input.charAt(next + 8)))
    };

    // Parse a single statement.
    //
    // If expecting a statement and finding a slash operator, parse a
    // regular expression literal. This is to handle cases like
    // `if (foo) /blah/.exec(foo)`, where looking at the previous token
    // does not help.

    pp$1.parseStatement = function(declaration, topLevel, exports) {
      var starttype = this.type, node = this.startNode(), kind;

      if (this.isLet()) {
        starttype = types._var;
        kind = "let";
      }

      // Most types of statements are recognized by the keyword they
      // start with. Many are trivial to parse, some require a bit of
      // complexity.

      switch (starttype) {
      case types._break: case types._continue: return this.parseBreakContinueStatement(node, starttype.keyword)
      case types._debugger: return this.parseDebuggerStatement(node)
      case types._do: return this.parseDoStatement(node)
      case types._for: return this.parseForStatement(node)
      case types._function:
        if (!declaration && this.options.ecmaVersion >= 6) { this.unexpected(); }
        return this.parseFunctionStatement(node, false)
      case types._class:
        if (!declaration) { this.unexpected(); }
        return this.parseClass(node, true)
      case types._if: return this.parseIfStatement(node)
      case types._return: return this.parseReturnStatement(node)
      case types._switch: return this.parseSwitchStatement(node)
      case types._throw: return this.parseThrowStatement(node)
      case types._try: return this.parseTryStatement(node)
      case types._const: case types._var:
        kind = kind || this.value;
        if (!declaration && kind != "var") { this.unexpected(); }
        return this.parseVarStatement(node, kind)
      case types._while: return this.parseWhileStatement(node)
      case types._with: return this.parseWithStatement(node)
      case types.braceL: return this.parseBlock()
      case types.semi: return this.parseEmptyStatement(node)
      case types._export:
      case types._import:
        if (!this.options.allowImportExportEverywhere) {
          if (!topLevel)
            { this.raise(this.start, "'import' and 'export' may only appear at the top level"); }
          if (!this.inModule)
            { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); }
        }
        return starttype === types._import ? this.parseImport(node) : this.parseExport(node, exports)

        // If the statement does not start with a statement keyword or a
        // brace, it's an ExpressionStatement or LabeledStatement. We
        // simply start parsing an expression, and afterwards, if the
        // next token is a colon and the expression was a simple
        // Identifier node, we switch to interpreting it as a label.
      default:
        if (this.isAsyncFunction()) {
          if (!declaration) { this.unexpected(); }
          this.next();
          return this.parseFunctionStatement(node, true)
        }

        var maybeName = this.value, expr = this.parseExpression();
        if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon))
          { return this.parseLabeledStatement(node, maybeName, expr) }
        else { return this.parseExpressionStatement(node, expr) }
      }
    };

    pp$1.parseBreakContinueStatement = function(node, keyword) {
      var this$1 = this;

      var isBreak = keyword == "break";
      this.next();
      if (this.eat(types.semi) || this.insertSemicolon()) { node.label = null; }
      else if (this.type !== types.name) { this.unexpected(); }
      else {
        node.label = this.parseIdent();
        this.semicolon();
      }

      // Verify that there is an actual destination to break or
      // continue to.
      var i = 0;
      for (; i < this.labels.length; ++i) {
        var lab = this$1.labels[i];
        if (node.label == null || lab.name === node.label.name) {
          if (lab.kind != null && (isBreak || lab.kind === "loop")) { break }
          if (node.label && isBreak) { break }
        }
      }
      if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); }
      return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement")
    };

    pp$1.parseDebuggerStatement = function(node) {
      this.next();
      this.semicolon();
      return this.finishNode(node, "DebuggerStatement")
    };

    pp$1.parseDoStatement = function(node) {
      this.next();
      this.labels.push(loopLabel);
      node.body = this.parseStatement(false);
      this.labels.pop();
      this.expect(types._while);
      node.test = this.parseParenExpression();
      if (this.options.ecmaVersion >= 6)
        { this.eat(types.semi); }
      else
        { this.semicolon(); }
      return this.finishNode(node, "DoWhileStatement")
    };

    // Disambiguating between a `for` and a `for`/`in` or `for`/`of`
    // loop is non-trivial. Basically, we have to parse the init `var`
    // statement or expression, disallowing the `in` operator (see
    // the second parameter to `parseExpression`), and then check
    // whether the next token is `in` or `of`. When there is no init
    // part (semicolon immediately after the opening parenthesis), it
    // is a regular `for` loop.

    pp$1.parseForStatement = function(node) {
      this.next();
      var awaitAt = (this.options.ecmaVersion >= 9 && this.inAsync && this.eatContextual("await")) ? this.lastTokStart : -1;
      this.labels.push(loopLabel);
      this.enterLexicalScope();
      this.expect(types.parenL);
      if (this.type === types.semi) {
        if (awaitAt > -1) { this.unexpected(awaitAt); }
        return this.parseFor(node, null)
      }
      var isLet = this.isLet();
      if (this.type === types._var || this.type === types._const || isLet) {
        var init$1 = this.startNode(), kind = isLet ? "let" : this.value;
        this.next();
        this.parseVar(init$1, true, kind);
        this.finishNode(init$1, "VariableDeclaration");
        if ((this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1 &&
            !(kind !== "var" && init$1.declarations[0].init)) {
          if (this.options.ecmaVersion >= 9) {
            if (this.type === types._in) {
              if (awaitAt > -1) { this.unexpected(awaitAt); }
            } else { node.await = awaitAt > -1; }
          }
          return this.parseForIn(node, init$1)
        }
        if (awaitAt > -1) { this.unexpected(awaitAt); }
        return this.parseFor(node, init$1)
      }
      var refDestructuringErrors = new DestructuringErrors;
      var init = this.parseExpression(true, refDestructuringErrors);
      if (this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) {
        if (this.options.ecmaVersion >= 9) {
          if (this.type === types._in) {
            if (awaitAt > -1) { this.unexpected(awaitAt); }
          } else { node.await = awaitAt > -1; }
        }
        this.toAssignable(init, false, refDestructuringErrors);
        this.checkLVal(init);
        return this.parseForIn(node, init)
      } else {
        this.checkExpressionErrors(refDestructuringErrors, true);
      }
      if (awaitAt > -1) { this.unexpected(awaitAt); }
      return this.parseFor(node, init)
    };

    pp$1.parseFunctionStatement = function(node, isAsync) {
      this.next();
      return this.parseFunction(node, true, false, isAsync)
    };

    pp$1.parseIfStatement = function(node) {
      this.next();
      node.test = this.parseParenExpression();
      // allow function declarations in branches, but only in non-strict mode
      node.consequent = this.parseStatement(!this.strict && this.type == types._function);
      node.alternate = this.eat(types._else) ? this.parseStatement(!this.strict && this.type == types._function) : null;
      return this.finishNode(node, "IfStatement")
    };

    pp$1.parseReturnStatement = function(node) {
      if (!this.inFunction && !this.options.allowReturnOutsideFunction)
        { this.raise(this.start, "'return' outside of function"); }
      this.next();

      // In `return` (and `break`/`continue`), the keywords with
      // optional arguments, we eagerly look for a semicolon or the
      // possibility to insert one.

      if (this.eat(types.semi) || this.insertSemicolon()) { node.argument = null; }
      else { node.argument = this.parseExpression(); this.semicolon(); }
      return this.finishNode(node, "ReturnStatement")
    };

    pp$1.parseSwitchStatement = function(node) {
      var this$1 = this;

      this.next();
      node.discriminant = this.parseParenExpression();
      node.cases = [];
      this.expect(types.braceL);
      this.labels.push(switchLabel);
      this.enterLexicalScope();

      // Statements under must be grouped (by label) in SwitchCase
      // nodes. `cur` is used to keep the node that we are currently
      // adding statements to.

      var cur;
      for (var sawDefault = false; this.type != types.braceR;) {
        if (this$1.type === types._case || this$1.type === types._default) {
          var isCase = this$1.type === types._case;
          if (cur) { this$1.finishNode(cur, "SwitchCase"); }
          node.cases.push(cur = this$1.startNode());
          cur.consequent = [];
          this$1.next();
          if (isCase) {
            cur.test = this$1.parseExpression();
          } else {
            if (sawDefault) { this$1.raiseRecoverable(this$1.lastTokStart, "Multiple default clauses"); }
            sawDefault = true;
            cur.test = null;
          }
          this$1.expect(types.colon);
        } else {
          if (!cur) { this$1.unexpected(); }
          cur.consequent.push(this$1.parseStatement(true));
        }
      }
      this.exitLexicalScope();
      if (cur) { this.finishNode(cur, "SwitchCase"); }
      this.next(); // Closing brace
      this.labels.pop();
      return this.finishNode(node, "SwitchStatement")
    };

    pp$1.parseThrowStatement = function(node) {
      this.next();
      if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start)))
        { this.raise(this.lastTokEnd, "Illegal newline after throw"); }
      node.argument = this.parseExpression();
      this.semicolon();
      return this.finishNode(node, "ThrowStatement")
    };

    // Reused empty array added for node fields that are always empty.

    var empty = [];

    pp$1.parseTryStatement = function(node) {
      this.next();
      node.block = this.parseBlock();
      node.handler = null;
      if (this.type === types._catch) {
        var clause = this.startNode();
        this.next();
        this.expect(types.parenL);
        clause.param = this.parseBindingAtom();
        this.enterLexicalScope();
        this.checkLVal(clause.param, "let");
        this.expect(types.parenR);
        clause.body = this.parseBlock(false);
        this.exitLexicalScope();
        node.handler = this.finishNode(clause, "CatchClause");
      }
      node.finalizer = this.eat(types._finally) ? this.parseBlock() : null;
      if (!node.handler && !node.finalizer)
        { this.raise(node.start, "Missing catch or finally clause"); }
      return this.finishNode(node, "TryStatement")
    };

    pp$1.parseVarStatement = function(node, kind) {
      this.next();
      this.parseVar(node, false, kind);
      this.semicolon();
      return this.finishNode(node, "VariableDeclaration")
    };

    pp$1.parseWhileStatement = function(node) {
      this.next();
      node.test = this.parseParenExpression();
      this.labels.push(loopLabel);
      node.body = this.parseStatement(false);
      this.labels.pop();
      return this.finishNode(node, "WhileStatement")
    };

    pp$1.parseWithStatement = function(node) {
      if (this.strict) { this.raise(this.start, "'with' in strict mode"); }
      this.next();
      node.object = this.parseParenExpression();
      node.body = this.parseStatement(false);
      return this.finishNode(node, "WithStatement")
    };

    pp$1.parseEmptyStatement = function(node) {
      this.next();
      return this.finishNode(node, "EmptyStatement")
    };

    pp$1.parseLabeledStatement = function(node, maybeName, expr) {
      var this$1 = this;

      for (var i$1 = 0, list = this$1.labels; i$1 < list.length; i$1 += 1)
        {
        var label = list[i$1];

        if (label.name === maybeName)
          { this$1.raise(expr.start, "Label '" + maybeName + "' is already declared");
      } }
      var kind = this.type.isLoop ? "loop" : this.type === types._switch ? "switch" : null;
      for (var i = this.labels.length - 1; i >= 0; i--) {
        var label$1 = this$1.labels[i];
        if (label$1.statementStart == node.start) {
          // Update information about previous labels on this node
          label$1.statementStart = this$1.start;
          label$1.kind = kind;
        } else { break }
      }
      this.labels.push({name: maybeName, kind: kind, statementStart: this.start});
      node.body = this.parseStatement(true);
      if (node.body.type == "ClassDeclaration" ||
          node.body.type == "VariableDeclaration" && node.body.kind != "var" ||
          node.body.type == "FunctionDeclaration" && (this.strict || node.body.generator))
        { this.raiseRecoverable(node.body.start, "Invalid labeled declaration"); }
      this.labels.pop();
      node.label = expr;
      return this.finishNode(node, "LabeledStatement")
    };

    pp$1.parseExpressionStatement = function(node, expr) {
      node.expression = expr;
      this.semicolon();
      return this.finishNode(node, "ExpressionStatement")
    };

    // Parse a semicolon-enclosed block of statements, handling `"use
    // strict"` declarations when `allowStrict` is true (used for
    // function bodies).

    pp$1.parseBlock = function(createNewLexicalScope) {
      var this$1 = this;
      if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true;

      var node = this.startNode();
      node.body = [];
      this.expect(types.braceL);
      if (createNewLexicalScope) {
        this.enterLexicalScope();
      }
      while (!this.eat(types.braceR)) {
        var stmt = this$1.parseStatement(true);
        node.body.push(stmt);
      }
      if (createNewLexicalScope) {
        this.exitLexicalScope();
      }
      return this.finishNode(node, "BlockStatement")
    };

    // Parse a regular `for` loop. The disambiguation code in
    // `parseStatement` will already have parsed the init statement or
    // expression.

    pp$1.parseFor = function(node, init) {
      node.init = init;
      this.expect(types.semi);
      node.test = this.type === types.semi ? null : this.parseExpression();
      this.expect(types.semi);
      node.update = this.type === types.parenR ? null : this.parseExpression();
      this.expect(types.parenR);
      this.exitLexicalScope();
      node.body = this.parseStatement(false);
      this.labels.pop();
      return this.finishNode(node, "ForStatement")
    };

    // Parse a `for`/`in` and `for`/`of` loop, which are almost
    // same from parser's perspective.

    pp$1.parseForIn = function(node, init) {
      var type = this.type === types._in ? "ForInStatement" : "ForOfStatement";
      this.next();
      if (type == "ForInStatement") {
        if (init.type === "AssignmentPattern" ||
          (init.type === "VariableDeclaration" && init.declarations[0].init != null &&
           (this.strict || init.declarations[0].id.type !== "Identifier")))
          { this.raise(init.start, "Invalid assignment in for-in loop head"); }
      }
      node.left = init;
      node.right = type == "ForInStatement" ? this.parseExpression() : this.parseMaybeAssign();
      this.expect(types.parenR);
      this.exitLexicalScope();
      node.body = this.parseStatement(false);
      this.labels.pop();
      return this.finishNode(node, type)
    };

    // Parse a list of variable declarations.

    pp$1.parseVar = function(node, isFor, kind) {
      var this$1 = this;

      node.declarations = [];
      node.kind = kind;
      for (;;) {
        var decl = this$1.startNode();
        this$1.parseVarId(decl, kind);
        if (this$1.eat(types.eq)) {
          decl.init = this$1.parseMaybeAssign(isFor);
        } else if (kind === "const" && !(this$1.type === types._in || (this$1.options.ecmaVersion >= 6 && this$1.isContextual("of")))) {
          this$1.unexpected();
        } else if (decl.id.type != "Identifier" && !(isFor && (this$1.type === types._in || this$1.isContextual("of")))) {
          this$1.raise(this$1.lastTokEnd, "Complex binding patterns require an initialization value");
        } else {
          decl.init = null;
        }
        node.declarations.push(this$1.finishNode(decl, "VariableDeclarator"));
        if (!this$1.eat(types.comma)) { break }
      }
      return node
    };

    pp$1.parseVarId = function(decl, kind) {
      decl.id = this.parseBindingAtom(kind);
      this.checkLVal(decl.id, kind, false);
    };

    // Parse a function declaration or literal (depending on the
    // `isStatement` parameter).

    pp$1.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) {
      this.initFunction(node);
      if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync)
        { node.generator = this.eat(types.star); }
      if (this.options.ecmaVersion >= 8)
        { node.async = !!isAsync; }

      if (isStatement) {
        node.id = isStatement === "nullableID" && this.type != types.name ? null : this.parseIdent();
        if (node.id) {
          this.checkLVal(node.id, "var");
        }
      }

      var oldInGen = this.inGenerator, oldInAsync = this.inAsync,
          oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction;
      this.inGenerator = node.generator;
      this.inAsync = node.async;
      this.yieldPos = 0;
      this.awaitPos = 0;
      this.inFunction = true;
      this.enterFunctionScope();

      if (!isStatement)
        { node.id = this.type == types.name ? this.parseIdent() : null; }

      this.parseFunctionParams(node);
      this.parseFunctionBody(node, allowExpressionBody);

      this.inGenerator = oldInGen;
      this.inAsync = oldInAsync;
      this.yieldPos = oldYieldPos;
      this.awaitPos = oldAwaitPos;
      this.inFunction = oldInFunc;
      return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression")
    };

    pp$1.parseFunctionParams = function(node) {
      this.expect(types.parenL);
      node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8);
      this.checkYieldAwaitInDefaultParams();
    };

    // Parse a class declaration or literal (depending on the
    // `isStatement` parameter).

    pp$1.parseClass = function(node, isStatement) {
      var this$1 = this;

      this.next();

      this.parseClassId(node, isStatement);
      this.parseClassSuper(node);
      var classBody = this.startNode();
      var hadConstructor = false;
      classBody.body = [];
      this.expect(types.braceL);
      while (!this.eat(types.braceR)) {
        var member = this$1.parseClassMember(classBody);
        if (member && member.type === "MethodDefinition" && member.kind === "constructor") {
          if (hadConstructor) { this$1.raise(member.start, "Duplicate constructor in the same class"); }
          hadConstructor = true;
        }
      }
      node.body = this.finishNode(classBody, "ClassBody");
      return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
    };

    pp$1.parseClassMember = function(classBody) {
      var this$1 = this;

      if (this.eat(types.semi)) { return null }

      var method = this.startNode();
      var tryContextual = function (k, noLineBreak) {
        if ( noLineBreak === void 0 ) noLineBreak = false;

        var start = this$1.start, startLoc = this$1.startLoc;
        if (!this$1.eatContextual(k)) { return false }
        if (this$1.type !== types.parenL && (!noLineBreak || !this$1.canInsertSemicolon())) { return true }
        if (method.key) { this$1.unexpected(); }
        method.computed = false;
        method.key = this$1.startNodeAt(start, startLoc);
        method.key.name = k;
        this$1.finishNode(method.key, "Identifier");
        return false
      };

      method.kind = "method";
      method.static = tryContextual("static");
      var isGenerator = this.eat(types.star);
      var isAsync = false;
      if (!isGenerator) {
        if (this.options.ecmaVersion >= 8 && tryContextual("async", true)) {
          isAsync = true;
          isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star);
        } else if (tryContextual("get")) {
          method.kind = "get";
        } else if (tryContextual("set")) {
          method.kind = "set";
        }
      }
      if (!method.key) { this.parsePropertyName(method); }
      var key = method.key;
      if (!method.computed && !method.static && (key.type === "Identifier" && key.name === "constructor" ||
          key.type === "Literal" && key.value === "constructor")) {
        if (method.kind !== "method") { this.raise(key.start, "Constructor can't have get/set modifier"); }
        if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); }
        if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); }
        method.kind = "constructor";
      } else if (method.static && key.type === "Identifier" && key.name === "prototype") {
        this.raise(key.start, "Classes may not have a static property named prototype");
      }
      this.parseClassMethod(classBody, method, isGenerator, isAsync);
      if (method.kind === "get" && method.value.params.length !== 0)
        { this.raiseRecoverable(method.value.start, "getter should have no params"); }
      if (method.kind === "set" && method.value.params.length !== 1)
        { this.raiseRecoverable(method.value.start, "setter should have exactly one param"); }
      if (method.kind === "set" && method.value.params[0].type === "RestElement")
        { this.raiseRecoverable(method.value.params[0].start, "Setter cannot use rest params"); }
      return method
    };

    pp$1.parseClassMethod = function(classBody, method, isGenerator, isAsync) {
      method.value = this.parseMethod(isGenerator, isAsync);
      classBody.body.push(this.finishNode(method, "MethodDefinition"));
    };

    pp$1.parseClassId = function(node, isStatement) {
      node.id = this.type === types.name ? this.parseIdent() : isStatement === true ? this.unexpected() : null;
    };

    pp$1.parseClassSuper = function(node) {
      node.superClass = this.eat(types._extends) ? this.parseExprSubscripts() : null;
    };

    // Parses module export declaration.

    pp$1.parseExport = function(node, exports) {
      var this$1 = this;

      this.next();
      // export * from '...'
      if (this.eat(types.star)) {
        this.expectContextual("from");
        if (this.type !== types.string) { this.unexpected(); }
        node.source = this.parseExprAtom();
        this.semicolon();
        return this.finishNode(node, "ExportAllDeclaration")
      }
      if (this.eat(types._default)) { // export default ...
        this.checkExport(exports, "default", this.lastTokStart);
        var isAsync;
        if (this.type === types._function || (isAsync = this.isAsyncFunction())) {
          var fNode = this.startNode();
          this.next();
          if (isAsync) { this.next(); }
          node.declaration = this.parseFunction(fNode, "nullableID", false, isAsync);
        } else if (this.type === types._class) {
          var cNode = this.startNode();
          node.declaration = this.parseClass(cNode, "nullableID");
        } else {
          node.declaration = this.parseMaybeAssign();
          this.semicolon();
        }
        return this.finishNode(node, "ExportDefaultDeclaration")
      }
      // export var|const|let|function|class ...
      if (this.shouldParseExportStatement()) {
        node.declaration = this.parseStatement(true);
        if (node.declaration.type === "VariableDeclaration")
          { this.checkVariableExport(exports, node.declaration.declarations); }
        else
          { this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); }
        node.specifiers = [];
        node.source = null;
      } else { // export { x, y as z } [from '...']
        node.declaration = null;
        node.specifiers = this.parseExportSpecifiers(exports);
        if (this.eatContextual("from")) {
          if (this.type !== types.string) { this.unexpected(); }
          node.source = this.parseExprAtom();
        } else {
          // check for keywords used as local names
          for (var i = 0, list = node.specifiers; i < list.length; i += 1) {
            var spec = list[i];

            this$1.checkUnreserved(spec.local);
          }

          node.source = null;
        }
        this.semicolon();
      }
      return this.finishNode(node, "ExportNamedDeclaration")
    };

    pp$1.checkExport = function(exports, name, pos) {
      if (!exports) { return }
      if (has(exports, name))
        { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); }
      exports[name] = true;
    };

    pp$1.checkPatternExport = function(exports, pat) {
      var this$1 = this;

      var type = pat.type;
      if (type == "Identifier")
        { this.checkExport(exports, pat.name, pat.start); }
      else if (type == "ObjectPattern")
        { for (var i = 0, list = pat.properties; i < list.length; i += 1)
          {
            var prop = list[i];

            this$1.checkPatternExport(exports, prop);
          } }
      else if (type == "ArrayPattern")
        { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) {
          var elt = list$1[i$1];

            if (elt) { this$1.checkPatternExport(exports, elt); }
        } }
      else if (type == "Property")
        { this.checkPatternExport(exports, pat.value); }
      else if (type == "AssignmentPattern")
        { this.checkPatternExport(exports, pat.left); }
      else if (type == "RestElement")
        { this.checkPatternExport(exports, pat.argument); }
      else if (type == "ParenthesizedExpression")
        { this.checkPatternExport(exports, pat.expression); }
    };

    pp$1.checkVariableExport = function(exports, decls) {
      var this$1 = this;

      if (!exports) { return }
      for (var i = 0, list = decls; i < list.length; i += 1)
        {
        var decl = list[i];

        this$1.checkPatternExport(exports, decl.id);
      }
    };

    pp$1.shouldParseExportStatement = function() {
      return this.type.keyword === "var" ||
        this.type.keyword === "const" ||
        this.type.keyword === "class" ||
        this.type.keyword === "function" ||
        this.isLet() ||
        this.isAsyncFunction()
    };

    // Parses a comma-separated list of module exports.

    pp$1.parseExportSpecifiers = function(exports) {
      var this$1 = this;

      var nodes = [], first = true;
      // export { x, y as z } [from '...']
      this.expect(types.braceL);
      while (!this.eat(types.braceR)) {
        if (!first) {
          this$1.expect(types.comma);
          if (this$1.afterTrailingComma(types.braceR)) { break }
        } else { first = false; }

        var node = this$1.startNode();
        node.local = this$1.parseIdent(true);
        node.exported = this$1.eatContextual("as") ? this$1.parseIdent(true) : node.local;
        this$1.checkExport(exports, node.exported.name, node.exported.start);
        nodes.push(this$1.finishNode(node, "ExportSpecifier"));
      }
      return nodes
    };

    // Parses import declaration.

    pp$1.parseImport = function(node) {
      this.next();
      // import '...'
      if (this.type === types.string) {
        node.specifiers = empty;
        node.source = this.parseExprAtom();
      } else {
        node.specifiers = this.parseImportSpecifiers();
        this.expectContextual("from");
        node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected();
      }
      this.semicolon();
      return this.finishNode(node, "ImportDeclaration")
    };

    // Parses a comma-separated list of module imports.

    pp$1.parseImportSpecifiers = function() {
      var this$1 = this;

      var nodes = [], first = true;
      if (this.type === types.name) {
        // import defaultObj, { x, y as z } from '...'
        var node = this.startNode();
        node.local = this.parseIdent();
        this.checkLVal(node.local, "let");
        nodes.push(this.finishNode(node, "ImportDefaultSpecifier"));
        if (!this.eat(types.comma)) { return nodes }
      }
      if (this.type === types.star) {
        var node$1 = this.startNode();
        this.next();
        this.expectContextual("as");
        node$1.local = this.parseIdent();
        this.checkLVal(node$1.local, "let");
        nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier"));
        return nodes
      }
      this.expect(types.braceL);
      while (!this.eat(types.braceR)) {
        if (!first) {
          this$1.expect(types.comma);
          if (this$1.afterTrailingComma(types.braceR)) { break }
        } else { first = false; }

        var node$2 = this$1.startNode();
        node$2.imported = this$1.parseIdent(true);
        if (this$1.eatContextual("as")) {
          node$2.local = this$1.parseIdent();
        } else {
          this$1.checkUnreserved(node$2.imported);
          node$2.local = node$2.imported;
        }
        this$1.checkLVal(node$2.local, "let");
        nodes.push(this$1.finishNode(node$2, "ImportSpecifier"));
      }
      return nodes
    };

    // Set `ExpressionStatement#directive` property for directive prologues.
    pp$1.adaptDirectivePrologue = function(statements) {
      for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) {
        statements[i].directive = statements[i].expression.raw.slice(1, -1);
      }
    };
    pp$1.isDirectiveCandidate = function(statement) {
      return (
        statement.type === "ExpressionStatement" &&
        statement.expression.type === "Literal" &&
        typeof statement.expression.value === "string" &&
        // Reject parenthesized strings.
        (this.input[statement.start] === "\"" || this.input[statement.start] === "'")
      )
    };

    var pp$2 = Parser.prototype;

    // Convert existing expression atom to assignable pattern
    // if possible.

    pp$2.toAssignable = function(node, isBinding, refDestructuringErrors) {
      var this$1 = this;

      if (this.options.ecmaVersion >= 6 && node) {
        switch (node.type) {
        case "Identifier":
          if (this.inAsync && node.name === "await")
            { this.raise(node.start, "Can not use 'await' as identifier inside an async function"); }
          break

        case "ObjectPattern":
        case "ArrayPattern":
        case "RestElement":
          break

        case "ObjectExpression":
          node.type = "ObjectPattern";
          if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
          for (var i = 0, list = node.properties; i < list.length; i += 1) {
            var prop = list[i];

          this$1.toAssignable(prop, isBinding);
            // Early error:
            //   AssignmentRestProperty[Yield, Await] :
            //     `...` DestructuringAssignmentTarget[Yield, Await]
            //
            //   It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|.
            if (
              prop.type === "RestElement" &&
              (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern")
            ) {
              this$1.raise(prop.argument.start, "Unexpected token");
            }
          }
          break

        case "Property":
          // AssignmentProperty has type == "Property"
          if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); }
          this.toAssignable(node.value, isBinding);
          break

        case "ArrayExpression":
          node.type = "ArrayPattern";
          if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
          this.toAssignableList(node.elements, isBinding);
          break

        case "SpreadElement":
          node.type = "RestElement";
          this.toAssignable(node.argument, isBinding);
          if (node.argument.type === "AssignmentPattern")
            { this.raise(node.argument.start, "Rest elements cannot have a default value"); }
          break

        case "AssignmentExpression":
          if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); }
          node.type = "AssignmentPattern";
          delete node.operator;
          this.toAssignable(node.left, isBinding);
          // falls through to AssignmentPattern

        case "AssignmentPattern":
          break

        case "ParenthesizedExpression":
          this.toAssignable(node.expression, isBinding);
          break

        case "MemberExpression":
          if (!isBinding) { break }

        default:
          this.raise(node.start, "Assigning to rvalue");
        }
      } else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
      return node
    };

    // Convert list of expression atoms to binding list.

    pp$2.toAssignableList = function(exprList, isBinding) {
      var this$1 = this;

      var end = exprList.length;
      for (var i = 0; i < end; i++) {
        var elt = exprList[i];
        if (elt) { this$1.toAssignable(elt, isBinding); }
      }
      if (end) {
        var last = exprList[end - 1];
        if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier")
          { this.unexpected(last.argument.start); }
      }
      return exprList
    };

    // Parses spread element.

    pp$2.parseSpread = function(refDestructuringErrors) {
      var node = this.startNode();
      this.next();
      node.argument = this.parseMaybeAssign(false, refDestructuringErrors);
      return this.finishNode(node, "SpreadElement")
    };

    pp$2.parseRestBinding = function() {
      var node = this.startNode();
      this.next();

      // RestElement inside of a function parameter must be an identifier
      if (this.options.ecmaVersion === 6 && this.type !== types.name)
        { this.unexpected(); }

      node.argument = this.parseBindingAtom();

      return this.finishNode(node, "RestElement")
    };

    // Parses lvalue (assignable) atom.

    pp$2.parseBindingAtom = function() {
      if (this.options.ecmaVersion >= 6) {
        switch (this.type) {
        case types.bracketL:
          var node = this.startNode();
          this.next();
          node.elements = this.parseBindingList(types.bracketR, true, true);
          return this.finishNode(node, "ArrayPattern")

        case types.braceL:
          return this.parseObj(true)
        }
      }
      return this.parseIdent()
    };

    pp$2.parseBindingList = function(close, allowEmpty, allowTrailingComma) {
      var this$1 = this;

      var elts = [], first = true;
      while (!this.eat(close)) {
        if (first) { first = false; }
        else { this$1.expect(types.comma); }
        if (allowEmpty && this$1.type === types.comma) {
          elts.push(null);
        } else if (allowTrailingComma && this$1.afterTrailingComma(close)) {
          break
        } else if (this$1.type === types.ellipsis) {
          var rest = this$1.parseRestBinding();
          this$1.parseBindingListItem(rest);
          elts.push(rest);
          if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); }
          this$1.expect(close);
          break
        } else {
          var elem = this$1.parseMaybeDefault(this$1.start, this$1.startLoc);
          this$1.parseBindingListItem(elem);
          elts.push(elem);
        }
      }
      return elts
    };

    pp$2.parseBindingListItem = function(param) {
      return param
    };

    // Parses assignment pattern around given atom if possible.

    pp$2.parseMaybeDefault = function(startPos, startLoc, left) {
      left = left || this.parseBindingAtom();
      if (this.options.ecmaVersion < 6 || !this.eat(types.eq)) { return left }
      var node = this.startNodeAt(startPos, startLoc);
      node.left = left;
      node.right = this.parseMaybeAssign();
      return this.finishNode(node, "AssignmentPattern")
    };

    // Verify that a node is an lval — something that can be assigned
    // to.
    // bindingType can be either:
    // 'var' indicating that the lval creates a 'var' binding
    // 'let' indicating that the lval creates a lexical ('let' or 'const') binding
    // 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references

    pp$2.checkLVal = function(expr, bindingType, checkClashes) {
      var this$1 = this;

      switch (expr.type) {
      case "Identifier":
        if (this.strict && this.reservedWordsStrictBind.test(expr.name))
          { this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); }
        if (checkClashes) {
          if (has(checkClashes, expr.name))
            { this.raiseRecoverable(expr.start, "Argument name clash"); }
          checkClashes[expr.name] = true;
        }
        if (bindingType && bindingType !== "none") {
          if (
            bindingType === "var" && !this.canDeclareVarName(expr.name) ||
            bindingType !== "var" && !this.canDeclareLexicalName(expr.name)
          ) {
            this.raiseRecoverable(expr.start, ("Identifier '" + (expr.name) + "' has already been declared"));
          }
          if (bindingType === "var") {
            this.declareVarName(expr.name);
          } else {
            this.declareLexicalName(expr.name);
          }
        }
        break

      case "MemberExpression":
        if (bindingType) { this.raiseRecoverable(expr.start, "Binding member expression"); }
        break

      case "ObjectPattern":
        for (var i = 0, list = expr.properties; i < list.length; i += 1)
          {
        var prop = list[i];

        this$1.checkLVal(prop, bindingType, checkClashes);
      }
        break

      case "Property":
        // AssignmentProperty has type == "Property"
        this.checkLVal(expr.value, bindingType, checkClashes);
        break

      case "ArrayPattern":
        for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) {
          var elem = list$1[i$1];

        if (elem) { this$1.checkLVal(elem, bindingType, checkClashes); }
        }
        break

      case "AssignmentPattern":
        this.checkLVal(expr.left, bindingType, checkClashes);
        break

      case "RestElement":
        this.checkLVal(expr.argument, bindingType, checkClashes);
        break

      case "ParenthesizedExpression":
        this.checkLVal(expr.expression, bindingType, checkClashes);
        break

      default:
        this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue");
      }
    };

    // A recursive descent parser operates by defining functions for all
    // syntactic elements, and recursively calling those, each function
    // advancing the input stream and returning an AST node. Precedence
    // of constructs (for example, the fact that `!x[1]` means `!(x[1])`
    // instead of `(!x)[1]` is handled by the fact that the parser
    // function that parses unary prefix operators is called first, and
    // in turn calls the function that parses `[]` subscripts — that
    // way, it'll receive the node for `x[1]` already parsed, and wraps
    // *that* in the unary operator node.
    //
    // Acorn uses an [operator precedence parser][opp] to handle binary
    // operator precedence, because it is much more compact than using
    // the technique outlined above, which uses different, nesting
    // functions to specify precedence, for all of the ten binary
    // precedence levels that JavaScript defines.
    //
    // [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser

    var pp$3 = Parser.prototype;

    // Check if property name clashes with already added.
    // Object/class getters and setters are not allowed to clash —
    // either with each other or with an init property — and in
    // strict mode, init properties are also not allowed to be repeated.

    pp$3.checkPropClash = function(prop, propHash, refDestructuringErrors) {
      if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement")
        { return }
      if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand))
        { return }
      var key = prop.key;
      var name;
      switch (key.type) {
      case "Identifier": name = key.name; break
      case "Literal": name = String(key.value); break
      default: return
      }
      var kind = prop.kind;
      if (this.options.ecmaVersion >= 6) {
        if (name === "__proto__" && kind === "init") {
          if (propHash.proto) {
            if (refDestructuringErrors && refDestructuringErrors.doubleProto < 0) { refDestructuringErrors.doubleProto = key.start; }
            // Backwards-compat kludge. Can be removed in version 6.0
            else { this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); }
          }
          propHash.proto = true;
        }
        return
      }
      name = "$" + name;
      var other = propHash[name];
      if (other) {
        var redefinition;
        if (kind === "init") {
          redefinition = this.strict && other.init || other.get || other.set;
        } else {
          redefinition = other.init || other[kind];
        }
        if (redefinition)
          { this.raiseRecoverable(key.start, "Redefinition of property"); }
      } else {
        other = propHash[name] = {
          init: false,
          get: false,
          set: false
        };
      }
      other[kind] = true;
    };

    // ### Expression parsing

    // These nest, from the most general expression type at the top to
    // 'atomic', nondivisible expression types at the bottom. Most of
    // the functions will simply let the function(s) below them parse,
    // and, *if* the syntactic construct they handle is present, wrap
    // the AST node that the inner parser gave them in another node.

    // Parse a full expression. The optional arguments are used to
    // forbid the `in` operator (in for loops initalization expressions)
    // and provide reference for storing '=' operator inside shorthand
    // property assignment in contexts where both object expression
    // and object pattern might appear (so it's possible to raise
    // delayed syntax error at correct position).

    pp$3.parseExpression = function(noIn, refDestructuringErrors) {
      var this$1 = this;

      var startPos = this.start, startLoc = this.startLoc;
      var expr = this.parseMaybeAssign(noIn, refDestructuringErrors);
      if (this.type === types.comma) {
        var node = this.startNodeAt(startPos, startLoc);
        node.expressions = [expr];
        while (this.eat(types.comma)) { node.expressions.push(this$1.parseMaybeAssign(noIn, refDestructuringErrors)); }
        return this.finishNode(node, "SequenceExpression")
      }
      return expr
    };

    // Parse an assignment expression. This includes applications of
    // operators like `+=`.

    pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) {
      if (this.inGenerator && this.isContextual("yield")) { return this.parseYield() }

      var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1;
      if (refDestructuringErrors) {
        oldParenAssign = refDestructuringErrors.parenthesizedAssign;
        oldTrailingComma = refDestructuringErrors.trailingComma;
        refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1;
      } else {
        refDestructuringErrors = new DestructuringErrors;
        ownDestructuringErrors = true;
      }

      var startPos = this.start, startLoc = this.startLoc;
      if (this.type == types.parenL || this.type == types.name)
        { this.potentialArrowAt = this.start; }
      var left = this.parseMaybeConditional(noIn, refDestructuringErrors);
      if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); }
      if (this.type.isAssign) {
        var node = this.startNodeAt(startPos, startLoc);
        node.operator = this.value;
        node.left = this.type === types.eq ? this.toAssignable(left, false, refDestructuringErrors) : left;
        if (!ownDestructuringErrors) { DestructuringErrors.call(refDestructuringErrors); }
        refDestructuringErrors.shorthandAssign = -1; // reset because shorthand default was used correctly
        this.checkLVal(left);
        this.next();
        node.right = this.parseMaybeAssign(noIn);
        return this.finishNode(node, "AssignmentExpression")
      } else {
        if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); }
      }
      if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; }
      if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; }
      return left
    };

    // Parse a ternary conditional (`?:`) operator.

    pp$3.parseMaybeConditional = function(noIn, refDestructuringErrors) {
      var startPos = this.start, startLoc = this.startLoc;
      var expr = this.parseExprOps(noIn, refDestructuringErrors);
      if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
      if (this.eat(types.question)) {
        var node = this.startNodeAt(startPos, startLoc);
        node.test = expr;
        node.consequent = this.parseMaybeAssign();
        this.expect(types.colon);
        node.alternate = this.parseMaybeAssign(noIn);
        return this.finishNode(node, "ConditionalExpression")
      }
      return expr
    };

    // Start the precedence parser.

    pp$3.parseExprOps = function(noIn, refDestructuringErrors) {
      var startPos = this.start, startLoc = this.startLoc;
      var expr = this.parseMaybeUnary(refDestructuringErrors, false);
      if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
      return expr.start == startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn)
    };

    // Parse binary operators with the operator precedence parsing
    // algorithm. `left` is the left-hand side of the operator.
    // `minPrec` provides context that allows the function to stop and
    // defer further parser to one of its callers when it encounters an
    // operator that has a lower precedence than the set it is parsing.

    pp$3.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) {
      var prec = this.type.binop;
      if (prec != null && (!noIn || this.type !== types._in)) {
        if (prec > minPrec) {
          var logical = this.type === types.logicalOR || this.type === types.logicalAND;
          var op = this.value;
          this.next();
          var startPos = this.start, startLoc = this.startLoc;
          var right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn);
          var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical);
          return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn)
        }
      }
      return left
    };

    pp$3.buildBinary = function(startPos, startLoc, left, right, op, logical) {
      var node = this.startNodeAt(startPos, startLoc);
      node.left = left;
      node.operator = op;
      node.right = right;
      return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression")
    };

    // Parse unary operators, both prefix and postfix.

    pp$3.parseMaybeUnary = function(refDestructuringErrors, sawUnary) {
      var this$1 = this;

      var startPos = this.start, startLoc = this.startLoc, expr;
      if (this.inAsync && this.isContextual("await")) {
        expr = this.parseAwait();
        sawUnary = true;
      } else if (this.type.prefix) {
        var node = this.startNode(), update = this.type === types.incDec;
        node.operator = this.value;
        node.prefix = true;
        this.next();
        node.argument = this.parseMaybeUnary(null, true);
        this.checkExpressionErrors(refDestructuringErrors, true);
        if (update) { this.checkLVal(node.argument); }
        else if (this.strict && node.operator === "delete" &&
                 node.argument.type === "Identifier")
          { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); }
        else { sawUnary = true; }
        expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
      } else {
        expr = this.parseExprSubscripts(refDestructuringErrors);
        if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
        while (this.type.postfix && !this.canInsertSemicolon()) {
          var node$1 = this$1.startNodeAt(startPos, startLoc);
          node$1.operator = this$1.value;
          node$1.prefix = false;
          node$1.argument = expr;
          this$1.checkLVal(expr);
          this$1.next();
          expr = this$1.finishNode(node$1, "UpdateExpression");
        }
      }

      if (!sawUnary && this.eat(types.starstar))
        { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false) }
      else
        { return expr }
    };

    // Parse call, dot, and `[]`-subscript expressions.

    pp$3.parseExprSubscripts = function(refDestructuringErrors) {
      var startPos = this.start, startLoc = this.startLoc;
      var expr = this.parseExprAtom(refDestructuringErrors);
      var skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")";
      if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) { return expr }
      var result = this.parseSubscripts(expr, startPos, startLoc);
      if (refDestructuringErrors && result.type === "MemberExpression") {
        if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; }
        if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; }
      }
      return result
    };

    pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) {
      var this$1 = this;

      var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" &&
          this.lastTokEnd == base.end && !this.canInsertSemicolon() && this.input.slice(base.start, base.end) === "async";
      for (var computed = (void 0);;) {
        if ((computed = this$1.eat(types.bracketL)) || this$1.eat(types.dot)) {
          var node = this$1.startNodeAt(startPos, startLoc);
          node.object = base;
          node.property = computed ? this$1.parseExpression() : this$1.parseIdent(true);
          node.computed = !!computed;
          if (computed) { this$1.expect(types.bracketR); }
          base = this$1.finishNode(node, "MemberExpression");
        } else if (!noCalls && this$1.eat(types.parenL)) {
          var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this$1.yieldPos, oldAwaitPos = this$1.awaitPos;
          this$1.yieldPos = 0;
          this$1.awaitPos = 0;
          var exprList = this$1.parseExprList(types.parenR, this$1.options.ecmaVersion >= 8, false, refDestructuringErrors);
          if (maybeAsyncArrow && !this$1.canInsertSemicolon() && this$1.eat(types.arrow)) {
            this$1.checkPatternErrors(refDestructuringErrors, false);
            this$1.checkYieldAwaitInDefaultParams();
            this$1.yieldPos = oldYieldPos;
            this$1.awaitPos = oldAwaitPos;
            return this$1.parseArrowExpression(this$1.startNodeAt(startPos, startLoc), exprList, true)
          }
          this$1.checkExpressionErrors(refDestructuringErrors, true);
          this$1.yieldPos = oldYieldPos || this$1.yieldPos;
          this$1.awaitPos = oldAwaitPos || this$1.awaitPos;
          var node$1 = this$1.startNodeAt(startPos, startLoc);
          node$1.callee = base;
          node$1.arguments = exprList;
          base = this$1.finishNode(node$1, "CallExpression");
        } else if (this$1.type === types.backQuote) {
          var node$2 = this$1.startNodeAt(startPos, startLoc);
          node$2.tag = base;
          node$2.quasi = this$1.parseTemplate({isTagged: true});
          base = this$1.finishNode(node$2, "TaggedTemplateExpression");
        } else {
          return base
        }
      }
    };

    // Parse an atomic expression — either a single token that is an
    // expression, an expression started by a keyword like `function` or
    // `new`, or an expression wrapped in punctuation like `()`, `[]`,
    // or `{}`.

    pp$3.parseExprAtom = function(refDestructuringErrors) {
      var node, canBeArrow = this.potentialArrowAt == this.start;
      switch (this.type) {
      case types._super:
        if (!this.inFunction)
          { this.raise(this.start, "'super' outside of function or class"); }
        node = this.startNode();
        this.next();
        // The `super` keyword can appear at below:
        // SuperProperty:
        //     super [ Expression ]
        //     super . IdentifierName
        // SuperCall:
        //     super Arguments
        if (this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL)
          { this.unexpected(); }
        return this.finishNode(node, "Super")

      case types._this:
        node = this.startNode();
        this.next();
        return this.finishNode(node, "ThisExpression")

      case types.name:
        var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc;
        var id = this.parseIdent(this.type !== types.name);
        if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types._function))
          { return this.parseFunction(this.startNodeAt(startPos, startLoc), false, false, true) }
        if (canBeArrow && !this.canInsertSemicolon()) {
          if (this.eat(types.arrow))
            { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false) }
          if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types.name && !containsEsc) {
            id = this.parseIdent();
            if (this.canInsertSemicolon() || !this.eat(types.arrow))
              { this.unexpected(); }
            return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true)
          }
        }
        return id

      case types.regexp:
        var value = this.value;
        node = this.parseLiteral(value.value);
        node.regex = {pattern: value.pattern, flags: value.flags};
        return node

      case types.num: case types.string:
        return this.parseLiteral(this.value)

      case types._null: case types._true: case types._false:
        node = this.startNode();
        node.value = this.type === types._null ? null : this.type === types._true;
        node.raw = this.type.keyword;
        this.next();
        return this.finishNode(node, "Literal")

      case types.parenL:
        var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow);
        if (refDestructuringErrors) {
          if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr))
            { refDestructuringErrors.parenthesizedAssign = start; }
          if (refDestructuringErrors.parenthesizedBind < 0)
            { refDestructuringErrors.parenthesizedBind = start; }
        }
        return expr

      case types.bracketL:
        node = this.startNode();
        this.next();
        node.elements = this.parseExprList(types.bracketR, true, true, refDestructuringErrors);
        return this.finishNode(node, "ArrayExpression")

      case types.braceL:
        return this.parseObj(false, refDestructuringErrors)

      case types._function:
        node = this.startNode();
        this.next();
        return this.parseFunction(node, false)

      case types._class:
        return this.parseClass(this.startNode(), false)

      case types._new:
        return this.parseNew()

      case types.backQuote:
        return this.parseTemplate()

      default:
        this.unexpected();
      }
    };

    pp$3.parseLiteral = function(value) {
      var node = this.startNode();
      node.value = value;
      node.raw = this.input.slice(this.start, this.end);
      this.next();
      return this.finishNode(node, "Literal")
    };

    pp$3.parseParenExpression = function() {
      this.expect(types.parenL);
      var val = this.parseExpression();
      this.expect(types.parenR);
      return val
    };

    pp$3.parseParenAndDistinguishExpression = function(canBeArrow) {
      var this$1 = this;

      var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8;
      if (this.options.ecmaVersion >= 6) {
        this.next();

        var innerStartPos = this.start, innerStartLoc = this.startLoc;
        var exprList = [], first = true, lastIsComma = false;
        var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart;
        this.yieldPos = 0;
        this.awaitPos = 0;
        while (this.type !== types.parenR) {
          first ? first = false : this$1.expect(types.comma);
          if (allowTrailingComma && this$1.afterTrailingComma(types.parenR, true)) {
            lastIsComma = true;
            break
          } else if (this$1.type === types.ellipsis) {
            spreadStart = this$1.start;
            exprList.push(this$1.parseParenItem(this$1.parseRestBinding()));
            if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); }
            break
          } else {
            exprList.push(this$1.parseMaybeAssign(false, refDestructuringErrors, this$1.parseParenItem));
          }
        }
        var innerEndPos = this.start, innerEndLoc = this.startLoc;
        this.expect(types.parenR);

        if (canBeArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) {
          this.checkPatternErrors(refDestructuringErrors, false);
          this.checkYieldAwaitInDefaultParams();
          this.yieldPos = oldYieldPos;
          this.awaitPos = oldAwaitPos;
          return this.parseParenArrowList(startPos, startLoc, exprList)
        }

        if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); }
        if (spreadStart) { this.unexpected(spreadStart); }
        this.checkExpressionErrors(refDestructuringErrors, true);
        this.yieldPos = oldYieldPos || this.yieldPos;
        this.awaitPos = oldAwaitPos || this.awaitPos;

        if (exprList.length > 1) {
          val = this.startNodeAt(innerStartPos, innerStartLoc);
          val.expressions = exprList;
          this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc);
        } else {
          val = exprList[0];
        }
      } else {
        val = this.parseParenExpression();
      }

      if (this.options.preserveParens) {
        var par = this.startNodeAt(startPos, startLoc);
        par.expression = val;
        return this.finishNode(par, "ParenthesizedExpression")
      } else {
        return val
      }
    };

    pp$3.parseParenItem = function(item) {
      return item
    };

    pp$3.parseParenArrowList = function(startPos, startLoc, exprList) {
      return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList)
    };

    // New's precedence is slightly tricky. It must allow its argument to
    // be a `[]` or dot subscript expression, but not a call — at least,
    // not without wrapping it in parentheses. Thus, it uses the noCalls
    // argument to parseSubscripts to prevent it from consuming the
    // argument list.

    var empty$1 = [];

    pp$3.parseNew = function() {
      var node = this.startNode();
      var meta = this.parseIdent(true);
      if (this.options.ecmaVersion >= 6 && this.eat(types.dot)) {
        node.meta = meta;
        var containsEsc = this.containsEsc;
        node.property = this.parseIdent(true);
        if (node.property.name !== "target" || containsEsc)
          { this.raiseRecoverable(node.property.start, "The only valid meta property for new is new.target"); }
        if (!this.inFunction)
          { this.raiseRecoverable(node.start, "new.target can only be used in functions"); }
        return this.finishNode(node, "MetaProperty")
      }
      var startPos = this.start, startLoc = this.startLoc;
      node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true);
      if (this.eat(types.parenL)) { node.arguments = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false); }
      else { node.arguments = empty$1; }
      return this.finishNode(node, "NewExpression")
    };

    // Parse template expression.

    pp$3.parseTemplateElement = function(ref) {
      var isTagged = ref.isTagged;

      var elem = this.startNode();
      if (this.type === types.invalidTemplate) {
        if (!isTagged) {
          this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal");
        }
        elem.value = {
          raw: this.value,
          cooked: null
        };
      } else {
        elem.value = {
          raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"),
          cooked: this.value
        };
      }
      this.next();
      elem.tail = this.type === types.backQuote;
      return this.finishNode(elem, "TemplateElement")
    };

    pp$3.parseTemplate = function(ref) {
      var this$1 = this;
      if ( ref === void 0 ) ref = {};
      var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false;

      var node = this.startNode();
      this.next();
      node.expressions = [];
      var curElt = this.parseTemplateElement({isTagged: isTagged});
      node.quasis = [curElt];
      while (!curElt.tail) {
        this$1.expect(types.dollarBraceL);
        node.expressions.push(this$1.parseExpression());
        this$1.expect(types.braceR);
        node.quasis.push(curElt = this$1.parseTemplateElement({isTagged: isTagged}));
      }
      this.next();
      return this.finishNode(node, "TemplateLiteral")
    };

    pp$3.isAsyncProp = function(prop) {
      return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" &&
        (this.type === types.name || this.type === types.num || this.type === types.string || this.type === types.bracketL || this.type.keyword || (this.options.ecmaVersion >= 9 && this.type === types.star)) &&
        !lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
    };

    // Parse an object literal or binding pattern.

    pp$3.parseObj = function(isPattern, refDestructuringErrors) {
      var this$1 = this;

      var node = this.startNode(), first = true, propHash = {};
      node.properties = [];
      this.next();
      while (!this.eat(types.braceR)) {
        if (!first) {
          this$1.expect(types.comma);
          if (this$1.afterTrailingComma(types.braceR)) { break }
        } else { first = false; }

        var prop = this$1.parseProperty(isPattern, refDestructuringErrors);
        if (!isPattern) { this$1.checkPropClash(prop, propHash, refDestructuringErrors); }
        node.properties.push(prop);
      }
      return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression")
    };

    pp$3.parseProperty = function(isPattern, refDestructuringErrors) {
      var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc;
      if (this.options.ecmaVersion >= 9 && this.eat(types.ellipsis)) {
        if (isPattern) {
          prop.argument = this.parseIdent(false);
          if (this.type === types.comma) {
            this.raise(this.start, "Comma is not permitted after the rest element");
          }
          return this.finishNode(prop, "RestElement")
        }
        // To disallow parenthesized identifier via `this.toAssignable()`.
        if (this.type === types.parenL && refDestructuringErrors) {
          if (refDestructuringErrors.parenthesizedAssign < 0) {
            refDestructuringErrors.parenthesizedAssign = this.start;
          }
          if (refDestructuringErrors.parenthesizedBind < 0) {
            refDestructuringErrors.parenthesizedBind = this.start;
          }
        }
        // Parse argument.
        prop.argument = this.parseMaybeAssign(false, refDestructuringErrors);
        // To disallow trailing comma via `this.toAssignable()`.
        if (this.type === types.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) {
          refDestructuringErrors.trailingComma = this.start;
        }
        // Finish
        return this.finishNode(prop, "SpreadElement")
      }
      if (this.options.ecmaVersion >= 6) {
        prop.method = false;
        prop.shorthand = false;
        if (isPattern || refDestructuringErrors) {
          startPos = this.start;
          startLoc = this.startLoc;
        }
        if (!isPattern)
          { isGenerator = this.eat(types.star); }
      }
      var containsEsc = this.containsEsc;
      this.parsePropertyName(prop);
      if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) {
        isAsync = true;
        isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star);
        this.parsePropertyName(prop, refDestructuringErrors);
      } else {
        isAsync = false;
      }
      this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc);
      return this.finishNode(prop, "Property")
    };

    pp$3.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) {
      if ((isGenerator || isAsync) && this.type === types.colon)
        { this.unexpected(); }

      if (this.eat(types.colon)) {
        prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors);
        prop.kind = "init";
      } else if (this.options.ecmaVersion >= 6 && this.type === types.parenL) {
        if (isPattern) { this.unexpected(); }
        prop.kind = "init";
        prop.method = true;
        prop.value = this.parseMethod(isGenerator, isAsync);
      } else if (!isPattern && !containsEsc &&
                 this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" &&
                 (prop.key.name === "get" || prop.key.name === "set") &&
                 (this.type != types.comma && this.type != types.braceR)) {
        if (isGenerator || isAsync) { this.unexpected(); }
        prop.kind = prop.key.name;
        this.parsePropertyName(prop);
        prop.value = this.parseMethod(false);
        var paramCount = prop.kind === "get" ? 0 : 1;
        if (prop.value.params.length !== paramCount) {
          var start = prop.value.start;
          if (prop.kind === "get")
            { this.raiseRecoverable(start, "getter should have no params"); }
          else
            { this.raiseRecoverable(start, "setter should have exactly one param"); }
        } else {
          if (prop.kind === "set" && prop.value.params[0].type === "RestElement")
            { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); }
        }
      } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
        this.checkUnreserved(prop.key);
        prop.kind = "init";
        if (isPattern) {
          prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
        } else if (this.type === types.eq && refDestructuringErrors) {
          if (refDestructuringErrors.shorthandAssign < 0)
            { refDestructuringErrors.shorthandAssign = this.start; }
          prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
        } else {
          prop.value = prop.key;
        }
        prop.shorthand = true;
      } else { this.unexpected(); }
    };

    pp$3.parsePropertyName = function(prop) {
      if (this.options.ecmaVersion >= 6) {
        if (this.eat(types.bracketL)) {
          prop.computed = true;
          prop.key = this.parseMaybeAssign();
          this.expect(types.bracketR);
          return prop.key
        } else {
          prop.computed = false;
        }
      }
      return prop.key = this.type === types.num || this.type === types.string ? this.parseExprAtom() : this.parseIdent(true)
    };

    // Initialize empty function node.

    pp$3.initFunction = function(node) {
      node.id = null;
      if (this.options.ecmaVersion >= 6) {
        node.generator = false;
        node.expression = false;
      }
      if (this.options.ecmaVersion >= 8)
        { node.async = false; }
    };

    // Parse object or class method.

    pp$3.parseMethod = function(isGenerator, isAsync) {
      var node = this.startNode(), oldInGen = this.inGenerator, oldInAsync = this.inAsync,
          oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction;

      this.initFunction(node);
      if (this.options.ecmaVersion >= 6)
        { node.generator = isGenerator; }
      if (this.options.ecmaVersion >= 8)
        { node.async = !!isAsync; }

      this.inGenerator = node.generator;
      this.inAsync = node.async;
      this.yieldPos = 0;
      this.awaitPos = 0;
      this.inFunction = true;
      this.enterFunctionScope();

      this.expect(types.parenL);
      node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8);
      this.checkYieldAwaitInDefaultParams();
      this.parseFunctionBody(node, false);

      this.inGenerator = oldInGen;
      this.inAsync = oldInAsync;
      this.yieldPos = oldYieldPos;
      this.awaitPos = oldAwaitPos;
      this.inFunction = oldInFunc;
      return this.finishNode(node, "FunctionExpression")
    };

    // Parse arrow function expression with given parameters.

    pp$3.parseArrowExpression = function(node, params, isAsync) {
      var oldInGen = this.inGenerator, oldInAsync = this.inAsync,
          oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction;

      this.enterFunctionScope();
      this.initFunction(node);
      if (this.options.ecmaVersion >= 8)
        { node.async = !!isAsync; }

      this.inGenerator = false;
      this.inAsync = node.async;
      this.yieldPos = 0;
      this.awaitPos = 0;
      this.inFunction = true;

      node.params = this.toAssignableList(params, true);
      this.parseFunctionBody(node, true);

      this.inGenerator = oldInGen;
      this.inAsync = oldInAsync;
      this.yieldPos = oldYieldPos;
      this.awaitPos = oldAwaitPos;
      this.inFunction = oldInFunc;
      return this.finishNode(node, "ArrowFunctionExpression")
    };

    // Parse function body and check parameters.

    pp$3.parseFunctionBody = function(node, isArrowFunction) {
      var isExpression = isArrowFunction && this.type !== types.braceL;
      var oldStrict = this.strict, useStrict = false;

      if (isExpression) {
        node.body = this.parseMaybeAssign();
        node.expression = true;
        this.checkParams(node, false);
      } else {
        var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params);
        if (!oldStrict || nonSimple) {
          useStrict = this.strictDirective(this.end);
          // If this is a strict mode function, verify that argument names
          // are not repeated, and it does not try to bind the words `eval`
          // or `arguments`.
          if (useStrict && nonSimple)
            { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); }
        }
        // Start a new scope with regard to labels and the `inFunction`
        // flag (restore them to their old value afterwards).
        var oldLabels = this.labels;
        this.labels = [];
        if (useStrict) { this.strict = true; }

        // Add the params to varDeclaredNames to ensure that an error is thrown
        // if a let/const declaration in the function clashes with one of the params.
        this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && this.isSimpleParamList(node.params));
        node.body = this.parseBlock(false);
        node.expression = false;
        this.adaptDirectivePrologue(node.body.body);
        this.labels = oldLabels;
      }
      this.exitFunctionScope();

      if (this.strict && node.id) {
        // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval'
        this.checkLVal(node.id, "none");
      }
      this.strict = oldStrict;
    };

    pp$3.isSimpleParamList = function(params) {
      for (var i = 0, list = params; i < list.length; i += 1)
        {
        var param = list[i];

        if (param.type !== "Identifier") { return false
      } }
      return true
    };

    // Checks function params for various disallowed patterns such as using "eval"
    // or "arguments" and duplicate parameters.

    pp$3.checkParams = function(node, allowDuplicates) {
      var this$1 = this;

      var nameHash = {};
      for (var i = 0, list = node.params; i < list.length; i += 1)
        {
        var param = list[i];

        this$1.checkLVal(param, "var", allowDuplicates ? null : nameHash);
      }
    };

    // Parses a comma-separated list of expressions, and returns them as
    // an array. `close` is the token type that ends the list, and
    // `allowEmpty` can be turned on to allow subsequent commas with
    // nothing in between them to be parsed as `null` (which is needed
    // for array literals).

    pp$3.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) {
      var this$1 = this;

      var elts = [], first = true;
      while (!this.eat(close)) {
        if (!first) {
          this$1.expect(types.comma);
          if (allowTrailingComma && this$1.afterTrailingComma(close)) { break }
        } else { first = false; }

        var elt = (void 0);
        if (allowEmpty && this$1.type === types.comma)
          { elt = null; }
        else if (this$1.type === types.ellipsis) {
          elt = this$1.parseSpread(refDestructuringErrors);
          if (refDestructuringErrors && this$1.type === types.comma && refDestructuringErrors.trailingComma < 0)
            { refDestructuringErrors.trailingComma = this$1.start; }
        } else {
          elt = this$1.parseMaybeAssign(false, refDestructuringErrors);
        }
        elts.push(elt);
      }
      return elts
    };

    pp$3.checkUnreserved = function(ref) {
      var start = ref.start;
      var end = ref.end;
      var name = ref.name;

      if (this.inGenerator && name === "yield")
        { this.raiseRecoverable(start, "Can not use 'yield' as identifier inside a generator"); }
      if (this.inAsync && name === "await")
        { this.raiseRecoverable(start, "Can not use 'await' as identifier inside an async function"); }
      if (this.isKeyword(name))
        { this.raise(start, ("Unexpected keyword '" + name + "'")); }
      if (this.options.ecmaVersion < 6 &&
        this.input.slice(start, end).indexOf("\\") != -1) { return }
      var re = this.strict ? this.reservedWordsStrict : this.reservedWords;
      if (re.test(name)) {
        if (!this.inAsync && name === "await")
          { this.raiseRecoverable(start, "Can not use keyword 'await' outside an async function"); }
        this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved"));
      }
    };

    // Parse the next token as an identifier. If `liberal` is true (used
    // when parsing properties), it will also convert keywords into
    // identifiers.

    pp$3.parseIdent = function(liberal, isBinding) {
      var node = this.startNode();
      if (liberal && this.options.allowReserved == "never") { liberal = false; }
      if (this.type === types.name) {
        node.name = this.value;
      } else if (this.type.keyword) {
        node.name = this.type.keyword;

        // To fix https://github.com/acornjs/acorn/issues/575
        // `class` and `function` keywords push new context into this.context.
        // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name.
        // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword
        if ((node.name === "class" || node.name === "function") &&
            (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) {
          this.context.pop();
        }
      } else {
        this.unexpected();
      }
      this.next();
      this.finishNode(node, "Identifier");
      if (!liberal) { this.checkUnreserved(node); }
      return node
    };

    // Parses yield expression inside generator.

    pp$3.parseYield = function() {
      if (!this.yieldPos) { this.yieldPos = this.start; }

      var node = this.startNode();
      this.next();
      if (this.type == types.semi || this.canInsertSemicolon() || (this.type != types.star && !this.type.startsExpr)) {
        node.delegate = false;
        node.argument = null;
      } else {
        node.delegate = this.eat(types.star);
        node.argument = this.parseMaybeAssign();
      }
      return this.finishNode(node, "YieldExpression")
    };

    pp$3.parseAwait = function() {
      if (!this.awaitPos) { this.awaitPos = this.start; }

      var node = this.startNode();
      this.next();
      node.argument = this.parseMaybeUnary(null, true);
      return this.finishNode(node, "AwaitExpression")
    };

    var pp$4 = Parser.prototype;

    // This function is used to raise exceptions on parse errors. It
    // takes an offset integer (into the current `input`) to indicate
    // the location of the error, attaches the position to the end
    // of the error message, and then raises a `SyntaxError` with that
    // message.

    pp$4.raise = function(pos, message) {
      var loc = getLineInfo(this.input, pos);
      message += " (" + loc.line + ":" + loc.column + ")";
      var err = new SyntaxError(message);
      err.pos = pos; err.loc = loc; err.raisedAt = this.pos;
      throw err
    };

    pp$4.raiseRecoverable = pp$4.raise;

    pp$4.curPosition = function() {
      if (this.options.locations) {
        return new Position(this.curLine, this.pos - this.lineStart)
      }
    };

    var pp$5 = Parser.prototype;

    // Object.assign polyfill
    var assign = Object.assign || function(target) {
      var sources = [], len = arguments.length - 1;
      while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ];

      for (var i = 0, list = sources; i < list.length; i += 1) {
        var source = list[i];

        for (var key in source) {
          if (has(source, key)) {
            target[key] = source[key];
          }
        }
      }
      return target
    };

    // The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names.

    pp$5.enterFunctionScope = function() {
      // var: a hash of var-declared names in the current lexical scope
      // lexical: a hash of lexically-declared names in the current lexical scope
      // childVar: a hash of var-declared names in all child lexical scopes of the current lexical scope (within the current function scope)
      // parentLexical: a hash of lexically-declared names in all parent lexical scopes of the current lexical scope (within the current function scope)
      this.scopeStack.push({var: {}, lexical: {}, childVar: {}, parentLexical: {}});
    };

    pp$5.exitFunctionScope = function() {
      this.scopeStack.pop();
    };

    pp$5.enterLexicalScope = function() {
      var parentScope = this.scopeStack[this.scopeStack.length - 1];
      var childScope = {var: {}, lexical: {}, childVar: {}, parentLexical: {}};

      this.scopeStack.push(childScope);
      assign(childScope.parentLexical, parentScope.lexical, parentScope.parentLexical);
    };

    pp$5.exitLexicalScope = function() {
      var childScope = this.scopeStack.pop();
      var parentScope = this.scopeStack[this.scopeStack.length - 1];

      assign(parentScope.childVar, childScope.var, childScope.childVar);
    };

    /**
     * A name can be declared with `var` if there are no variables with the same name declared with `let`/`const`
     * in the current lexical scope or any of the parent lexical scopes in this function.
     */
    pp$5.canDeclareVarName = function(name) {
      var currentScope = this.scopeStack[this.scopeStack.length - 1];

      return !has(currentScope.lexical, name) && !has(currentScope.parentLexical, name)
    };

    /**
     * A name can be declared with `let`/`const` if there are no variables with the same name declared with `let`/`const`
     * in the current scope, and there are no variables with the same name declared with `var` in the current scope or in
     * any child lexical scopes in this function.
     */
    pp$5.canDeclareLexicalName = function(name) {
      var currentScope = this.scopeStack[this.scopeStack.length - 1];

      return !has(currentScope.lexical, name) && !has(currentScope.var, name) && !has(currentScope.childVar, name)
    };

    pp$5.declareVarName = function(name) {
      this.scopeStack[this.scopeStack.length - 1].var[name] = true;
    };

    pp$5.declareLexicalName = function(name) {
      this.scopeStack[this.scopeStack.length - 1].lexical[name] = true;
    };

    var Node = function Node(parser, pos, loc) {
      this.type = "";
      this.start = pos;
      this.end = 0;
      if (parser.options.locations)
        { this.loc = new SourceLocation(parser, loc); }
      if (parser.options.directSourceFile)
        { this.sourceFile = parser.options.directSourceFile; }
      if (parser.options.ranges)
        { this.range = [pos, 0]; }
    };

    // Start an AST node, attaching a start offset.

    var pp$6 = Parser.prototype;

    pp$6.startNode = function() {
      return new Node(this, this.start, this.startLoc)
    };

    pp$6.startNodeAt = function(pos, loc) {
      return new Node(this, pos, loc)
    };

    // Finish an AST node, adding `type` and `end` properties.

    function finishNodeAt(node, type, pos, loc) {
      node.type = type;
      node.end = pos;
      if (this.options.locations)
        { node.loc.end = loc; }
      if (this.options.ranges)
        { node.range[1] = pos; }
      return node
    }

    pp$6.finishNode = function(node, type) {
      return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc)
    };

    // Finish node at given position

    pp$6.finishNodeAt = function(node, type, pos, loc) {
      return finishNodeAt.call(this, node, type, pos, loc)
    };

    // The algorithm used to determine whether a regexp can appear at a
    // given point in the program is loosely based on sweet.js' approach.
    // See https://github.com/mozilla/sweet.js/wiki/design

    var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) {
      this.token = token;
      this.isExpr = !!isExpr;
      this.preserveSpace = !!preserveSpace;
      this.override = override;
      this.generator = !!generator;
    };

    var types$1 = {
      b_stat: new TokContext("{", false),
      b_expr: new TokContext("{", true),
      b_tmpl: new TokContext("${", false),
      p_stat: new TokContext("(", false),
      p_expr: new TokContext("(", true),
      q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }),
      f_stat: new TokContext("function", false),
      f_expr: new TokContext("function", true),
      f_expr_gen: new TokContext("function", true, false, null, true),
      f_gen: new TokContext("function", false, false, null, true)
    };

    var pp$7 = Parser.prototype;

    pp$7.initialContext = function() {
      return [types$1.b_stat]
    };

    pp$7.braceIsBlock = function(prevType) {
      var parent = this.curContext();
      if (parent === types$1.f_expr || parent === types$1.f_stat)
        { return true }
      if (prevType === types.colon && (parent === types$1.b_stat || parent === types$1.b_expr))
        { return !parent.isExpr }

      // The check for `tt.name && exprAllowed` detects whether we are
      // after a `yield` or `of` construct. See the `updateContext` for
      // `tt.name`.
      if (prevType === types._return || prevType == types.name && this.exprAllowed)
        { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) }
      if (prevType === types._else || prevType === types.semi || prevType === types.eof || prevType === types.parenR || prevType == types.arrow)
        { return true }
      if (prevType == types.braceL)
        { return parent === types$1.b_stat }
      if (prevType == types._var || prevType == types.name)
        { return false }
      return !this.exprAllowed
    };

    pp$7.inGeneratorContext = function() {
      var this$1 = this;

      for (var i = this.context.length - 1; i >= 1; i--) {
        var context = this$1.context[i];
        if (context.token === "function")
          { return context.generator }
      }
      return false
    };

    pp$7.updateContext = function(prevType) {
      var update, type = this.type;
      if (type.keyword && prevType == types.dot)
        { this.exprAllowed = false; }
      else if (update = type.updateContext)
        { update.call(this, prevType); }
      else
        { this.exprAllowed = type.beforeExpr; }
    };

    // Token-specific context update code

    types.parenR.updateContext = types.braceR.updateContext = function() {
      if (this.context.length == 1) {
        this.exprAllowed = true;
        return
      }
      var out = this.context.pop();
      if (out === types$1.b_stat && this.curContext().token === "function") {
        out = this.context.pop();
      }
      this.exprAllowed = !out.isExpr;
    };

    types.braceL.updateContext = function(prevType) {
      this.context.push(this.braceIsBlock(prevType) ? types$1.b_stat : types$1.b_expr);
      this.exprAllowed = true;
    };

    types.dollarBraceL.updateContext = function() {
      this.context.push(types$1.b_tmpl);
      this.exprAllowed = true;
    };

    types.parenL.updateContext = function(prevType) {
      var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while;
      this.context.push(statementParens ? types$1.p_stat : types$1.p_expr);
      this.exprAllowed = true;
    };

    types.incDec.updateContext = function() {
      // tokExprAllowed stays unchanged
    };

    types._function.updateContext = types._class.updateContext = function(prevType) {
      if (prevType.beforeExpr && prevType !== types.semi && prevType !== types._else &&
          !((prevType === types.colon || prevType === types.braceL) && this.curContext() === types$1.b_stat))
        { this.context.push(types$1.f_expr); }
      else
        { this.context.push(types$1.f_stat); }
      this.exprAllowed = false;
    };

    types.backQuote.updateContext = function() {
      if (this.curContext() === types$1.q_tmpl)
        { this.context.pop(); }
      else
        { this.context.push(types$1.q_tmpl); }
      this.exprAllowed = false;
    };

    types.star.updateContext = function(prevType) {
      if (prevType == types._function) {
        var index = this.context.length - 1;
        if (this.context[index] === types$1.f_expr)
          { this.context[index] = types$1.f_expr_gen; }
        else
          { this.context[index] = types$1.f_gen; }
      }
      this.exprAllowed = true;
    };

    types.name.updateContext = function(prevType) {
      var allowed = false;
      if (this.options.ecmaVersion >= 6) {
        if (this.value == "of" && !this.exprAllowed ||
            this.value == "yield" && this.inGeneratorContext())
          { allowed = true; }
      }
      this.exprAllowed = allowed;
    };

    var data = {
      "$LONE": [
        "ASCII",
        "ASCII_Hex_Digit",
        "AHex",
        "Alphabetic",
        "Alpha",
        "Any",
        "Assigned",
        "Bidi_Control",
        "Bidi_C",
        "Bidi_Mirrored",
        "Bidi_M",
        "Case_Ignorable",
        "CI",
        "Cased",
        "Changes_When_Casefolded",
        "CWCF",
        "Changes_When_Casemapped",
        "CWCM",
        "Changes_When_Lowercased",
        "CWL",
        "Changes_When_NFKC_Casefolded",
        "CWKCF",
        "Changes_When_Titlecased",
        "CWT",
        "Changes_When_Uppercased",
        "CWU",
        "Dash",
        "Default_Ignorable_Code_Point",
        "DI",
        "Deprecated",
        "Dep",
        "Diacritic",
        "Dia",
        "Emoji",
        "Emoji_Component",
        "Emoji_Modifier",
        "Emoji_Modifier_Base",
        "Emoji_Presentation",
        "Extender",
        "Ext",
        "Grapheme_Base",
        "Gr_Base",
        "Grapheme_Extend",
        "Gr_Ext",
        "Hex_Digit",
        "Hex",
        "IDS_Binary_Operator",
        "IDSB",
        "IDS_Trinary_Operator",
        "IDST",
        "ID_Continue",
        "IDC",
        "ID_Start",
        "IDS",
        "Ideographic",
        "Ideo",
        "Join_Control",
        "Join_C",
        "Logical_Order_Exception",
        "LOE",
        "Lowercase",
        "Lower",
        "Math",
        "Noncharacter_Code_Point",
        "NChar",
        "Pattern_Syntax",
        "Pat_Syn",
        "Pattern_White_Space",
        "Pat_WS",
        "Quotation_Mark",
        "QMark",
        "Radical",
        "Regional_Indicator",
        "RI",
        "Sentence_Terminal",
        "STerm",
        "Soft_Dotted",
        "SD",
        "Terminal_Punctuation",
        "Term",
        "Unified_Ideograph",
        "UIdeo",
        "Uppercase",
        "Upper",
        "Variation_Selector",
        "VS",
        "White_Space",
        "space",
        "XID_Continue",
        "XIDC",
        "XID_Start",
        "XIDS"
      ],
      "General_Category": [
        "Cased_Letter",
        "LC",
        "Close_Punctuation",
        "Pe",
        "Connector_Punctuation",
        "Pc",
        "Control",
        "Cc",
        "cntrl",
        "Currency_Symbol",
        "Sc",
        "Dash_Punctuation",
        "Pd",
        "Decimal_Number",
        "Nd",
        "digit",
        "Enclosing_Mark",
        "Me",
        "Final_Punctuation",
        "Pf",
        "Format",
        "Cf",
        "Initial_Punctuation",
        "Pi",
        "Letter",
        "L",
        "Letter_Number",
        "Nl",
        "Line_Separator",
        "Zl",
        "Lowercase_Letter",
        "Ll",
        "Mark",
        "M",
        "Combining_Mark",
        "Math_Symbol",
        "Sm",
        "Modifier_Letter",
        "Lm",
        "Modifier_Symbol",
        "Sk",
        "Nonspacing_Mark",
        "Mn",
        "Number",
        "N",
        "Open_Punctuation",
        "Ps",
        "Other",
        "C",
        "Other_Letter",
        "Lo",
        "Other_Number",
        "No",
        "Other_Punctuation",
        "Po",
        "Other_Symbol",
        "So",
        "Paragraph_Separator",
        "Zp",
        "Private_Use",
        "Co",
        "Punctuation",
        "P",
        "punct",
        "Separator",
        "Z",
        "Space_Separator",
        "Zs",
        "Spacing_Mark",
        "Mc",
        "Surrogate",
        "Cs",
        "Symbol",
        "S",
        "Titlecase_Letter",
        "Lt",
        "Unassigned",
        "Cn",
        "Uppercase_Letter",
        "Lu"
      ],
      "Script": [
        "Adlam",
        "Adlm",
        "Ahom",
        "Anatolian_Hieroglyphs",
        "Hluw",
        "Arabic",
        "Arab",
        "Armenian",
        "Armn",
        "Avestan",
        "Avst",
        "Balinese",
        "Bali",
        "Bamum",
        "Bamu",
        "Bassa_Vah",
        "Bass",
        "Batak",
        "Batk",
        "Bengali",
        "Beng",
        "Bhaiksuki",
        "Bhks",
        "Bopomofo",
        "Bopo",
        "Brahmi",
        "Brah",
        "Braille",
        "Brai",
        "Buginese",
        "Bugi",
        "Buhid",
        "Buhd",
        "Canadian_Aboriginal",
        "Cans",
        "Carian",
        "Cari",
        "Caucasian_Albanian",
        "Aghb",
        "Chakma",
        "Cakm",
        "Cham",
        "Cherokee",
        "Cher",
        "Common",
        "Zyyy",
        "Coptic",
        "Copt",
        "Qaac",
        "Cuneiform",
        "Xsux",
        "Cypriot",
        "Cprt",
        "Cyrillic",
        "Cyrl",
        "Deseret",
        "Dsrt",
        "Devanagari",
        "Deva",
        "Duployan",
        "Dupl",
        "Egyptian_Hieroglyphs",
        "Egyp",
        "Elbasan",
        "Elba",
        "Ethiopic",
        "Ethi",
        "Georgian",
        "Geor",
        "Glagolitic",
        "Glag",
        "Gothic",
        "Goth",
        "Grantha",
        "Gran",
        "Greek",
        "Grek",
        "Gujarati",
        "Gujr",
        "Gurmukhi",
        "Guru",
        "Han",
        "Hani",
        "Hangul",
        "Hang",
        "Hanunoo",
        "Hano",
        "Hatran",
        "Hatr",
        "Hebrew",
        "Hebr",
        "Hiragana",
        "Hira",
        "Imperial_Aramaic",
        "Armi",
        "Inherited",
        "Zinh",
        "Qaai",
        "Inscriptional_Pahlavi",
        "Phli",
        "Inscriptional_Parthian",
        "Prti",
        "Javanese",
        "Java",
        "Kaithi",
        "Kthi",
        "Kannada",
        "Knda",
        "Katakana",
        "Kana",
        "Kayah_Li",
        "Kali",
        "Kharoshthi",
        "Khar",
        "Khmer",
        "Khmr",
        "Khojki",
        "Khoj",
        "Khudawadi",
        "Sind",
        "Lao",
        "Laoo",
        "Latin",
        "Latn",
        "Lepcha",
        "Lepc",
        "Limbu",
        "Limb",
        "Linear_A",
        "Lina",
        "Linear_B",
        "Linb",
        "Lisu",
        "Lycian",
        "Lyci",
        "Lydian",
        "Lydi",
        "Mahajani",
        "Mahj",
        "Malayalam",
        "Mlym",
        "Mandaic",
        "Mand",
        "Manichaean",
        "Mani",
        "Marchen",
        "Marc",
        "Masaram_Gondi",
        "Gonm",
        "Meetei_Mayek",
        "Mtei",
        "Mende_Kikakui",
        "Mend",
        "Meroitic_Cursive",
        "Merc",
        "Meroitic_Hieroglyphs",
        "Mero",
        "Miao",
        "Plrd",
        "Modi",
        "Mongolian",
        "Mong",
        "Mro",
        "Mroo",
        "Multani",
        "Mult",
        "Myanmar",
        "Mymr",
        "Nabataean",
        "Nbat",
        "New_Tai_Lue",
        "Talu",
        "Newa",
        "Nko",
        "Nkoo",
        "Nushu",
        "Nshu",
        "Ogham",
        "Ogam",
        "Ol_Chiki",
        "Olck",
        "Old_Hungarian",
        "Hung",
        "Old_Italic",
        "Ital",
        "Old_North_Arabian",
        "Narb",
        "Old_Permic",
        "Perm",
        "Old_Persian",
        "Xpeo",
        "Old_South_Arabian",
        "Sarb",
        "Old_Turkic",
        "Orkh",
        "Oriya",
        "Orya",
        "Osage",
        "Osge",
        "Osmanya",
        "Osma",
        "Pahawh_Hmong",
        "Hmng",
        "Palmyrene",
        "Palm",
        "Pau_Cin_Hau",
        "Pauc",
        "Phags_Pa",
        "Phag",
        "Phoenician",
        "Phnx",
        "Psalter_Pahlavi",
        "Phlp",
        "Rejang",
        "Rjng",
        "Runic",
        "Runr",
        "Samaritan",
        "Samr",
        "Saurashtra",
        "Saur",
        "Sharada",
        "Shrd",
        "Shavian",
        "Shaw",
        "Siddham",
        "Sidd",
        "SignWriting",
        "Sgnw",
        "Sinhala",
        "Sinh",
        "Sora_Sompeng",
        "Sora",
        "Soyombo",
        "Soyo",
        "Sundanese",
        "Sund",
        "Syloti_Nagri",
        "Sylo",
        "Syriac",
        "Syrc",
        "Tagalog",
        "Tglg",
        "Tagbanwa",
        "Tagb",
        "Tai_Le",
        "Tale",
        "Tai_Tham",
        "Lana",
        "Tai_Viet",
        "Tavt",
        "Takri",
        "Takr",
        "Tamil",
        "Taml",
        "Tangut",
        "Tang",
        "Telugu",
        "Telu",
        "Thaana",
        "Thaa",
        "Thai",
        "Tibetan",
        "Tibt",
        "Tifinagh",
        "Tfng",
        "Tirhuta",
        "Tirh",
        "Ugaritic",
        "Ugar",
        "Vai",
        "Vaii",
        "Warang_Citi",
        "Wara",
        "Yi",
        "Yiii",
        "Zanabazar_Square",
        "Zanb"
      ]
    };
    Array.prototype.push.apply(data.$LONE, data.General_Category);
    data.gc = data.General_Category;
    data.sc = data.Script_Extensions = data.scx = data.Script;

    var pp$9 = Parser.prototype;

    var RegExpValidationState = function RegExpValidationState(parser) {
      this.parser = parser;
      this.validFlags = "gim" + (parser.options.ecmaVersion >= 6 ? "uy" : "") + (parser.options.ecmaVersion >= 9 ? "s" : "");
      this.source = "";
      this.flags = "";
      this.start = 0;
      this.switchU = false;
      this.switchN = false;
      this.pos = 0;
      this.lastIntValue = 0;
      this.lastStringValue = "";
      this.lastAssertionIsQuantifiable = false;
      this.numCapturingParens = 0;
      this.maxBackReference = 0;
      this.groupNames = [];
      this.backReferenceNames = [];
    };

    RegExpValidationState.prototype.reset = function reset (start, pattern, flags) {
      var unicode = flags.indexOf("u") !== -1;
      this.start = start | 0;
      this.source = pattern + "";
      this.flags = flags;
      this.switchU = unicode && this.parser.options.ecmaVersion >= 6;
      this.switchN = unicode && this.parser.options.ecmaVersion >= 9;
    };

    RegExpValidationState.prototype.raise = function raise (message) {
      this.parser.raiseRecoverable(this.start, ("Invalid regular expression: /" + (this.source) + "/: " + message));
    };

    // If u flag is given, this returns the code point at the index (it combines a surrogate pair).
    // Otherwise, this returns the code unit of the index (can be a part of a surrogate pair).
    RegExpValidationState.prototype.at = function at (i) {
      var s = this.source;
      var l = s.length;
      if (i >= l) {
        return -1
      }
      var c = s.charCodeAt(i);
      if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) {
        return c
      }
      return (c << 10) + s.charCodeAt(i + 1) - 0x35FDC00
    };

    RegExpValidationState.prototype.nextIndex = function nextIndex (i) {
      var s = this.source;
      var l = s.length;
      if (i >= l) {
        return l
      }
      var c = s.charCodeAt(i);
      if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) {
        return i + 1
      }
      return i + 2
    };

    RegExpValidationState.prototype.current = function current () {
      return this.at(this.pos)
    };

    RegExpValidationState.prototype.lookahead = function lookahead () {
      return this.at(this.nextIndex(this.pos))
    };

    RegExpValidationState.prototype.advance = function advance () {
      this.pos = this.nextIndex(this.pos);
    };

    RegExpValidationState.prototype.eat = function eat (ch) {
      if (this.current() === ch) {
        this.advance();
        return true
      }
      return false
    };

    function codePointToString$1(ch) {
      if (ch <= 0xFFFF) { return String.fromCharCode(ch) }
      ch -= 0x10000;
      return String.fromCharCode((ch >> 10) + 0xD800, (ch & 0x03FF) + 0xDC00)
    }

    /**
     * Validate the flags part of a given RegExpLiteral.
     *
     * @param {RegExpValidationState} state The state to validate RegExp.
     * @returns {void}
     */
    pp$9.validateRegExpFlags = function(state) {
      var this$1 = this;

      var validFlags = state.validFlags;
      var flags = state.flags;

      for (var i = 0; i < flags.length; i++) {
        var flag = flags.charAt(i);
        if (validFlags.indexOf(flag) == -1) {
          this$1.raise(state.start, "Invalid regular expression flag");
        }
        if (flags.indexOf(flag, i + 1) > -1) {
          this$1.raise(state.start, "Duplicate regular expression flag");
        }
      }
    };

    /**
     * Validate the pattern part of a given RegExpLiteral.
     *
     * @param {RegExpValidationState} state The state to validate RegExp.
     * @returns {void}
     */
    pp$9.validateRegExpPattern = function(state) {
      this.regexp_pattern(state);

      // The goal symbol for the parse is |Pattern[~U, ~N]|. If the result of
      // parsing contains a |GroupName|, reparse with the goal symbol
      // |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError*
      // exception if _P_ did not conform to the grammar, if any elements of _P_
      // were not matched by the parse, or if any Early Error conditions exist.
      if (!state.switchN && this.options.ecmaVersion >= 9 && state.groupNames.length > 0) {
        state.switchN = true;
        this.regexp_pattern(state);
      }
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-Pattern
    pp$9.regexp_pattern = function(state) {
      state.pos = 0;
      state.lastIntValue = 0;
      state.lastStringValue = "";
      state.lastAssertionIsQuantifiable = false;
      state.numCapturingParens = 0;
      state.maxBackReference = 0;
      state.groupNames.length = 0;
      state.backReferenceNames.length = 0;

      this.regexp_disjunction(state);

      if (state.pos !== state.source.length) {
        // Make the same messages as V8.
        if (state.eat(0x29 /* ) */)) {
          state.raise("Unmatched ')'");
        }
        if (state.eat(0x5D /* [ */) || state.eat(0x7D /* } */)) {
          state.raise("Lone quantifier brackets");
        }
      }
      if (state.maxBackReference > state.numCapturingParens) {
        state.raise("Invalid escape");
      }
      for (var i = 0, list = state.backReferenceNames; i < list.length; i += 1) {
        var name = list[i];

        if (state.groupNames.indexOf(name) === -1) {
          state.raise("Invalid named capture referenced");
        }
      }
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction
    pp$9.regexp_disjunction = function(state) {
      var this$1 = this;

      this.regexp_alternative(state);
      while (state.eat(0x7C /* | */)) {
        this$1.regexp_alternative(state);
      }

      // Make the same message as V8.
      if (this.regexp_eatQuantifier(state, true)) {
        state.raise("Nothing to repeat");
      }
      if (state.eat(0x7B /* { */)) {
        state.raise("Lone quantifier brackets");
      }
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative
    pp$9.regexp_alternative = function(state) {
      while (state.pos < state.source.length && this.regexp_eatTerm(state))
        {  }
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term
    pp$9.regexp_eatTerm = function(state) {
      if (this.regexp_eatAssertion(state)) {
        // Handle `QuantifiableAssertion Quantifier` alternative.
        // `state.lastAssertionIsQuantifiable` is true if the last eaten Assertion
        // is a QuantifiableAssertion.
        if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) {
          // Make the same message as V8.
          if (state.switchU) {
            state.raise("Invalid quantifier");
          }
        }
        return true
      }

      if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) {
        this.regexp_eatQuantifier(state);
        return true
      }

      return false
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion
    pp$9.regexp_eatAssertion = function(state) {
      var start = state.pos;
      state.lastAssertionIsQuantifiable = false;

      // ^, $
      if (state.eat(0x5E /* ^ */) || state.eat(0x24 /* $ */)) {
        return true
      }

      // \b \B
      if (state.eat(0x5C /* \ */)) {
        if (state.eat(0x42 /* B */) || state.eat(0x62 /* b */)) {
          return true
        }
        state.pos = start;
      }

      // Lookahead / Lookbehind
      if (state.eat(0x28 /* ( */) && state.eat(0x3F /* ? */)) {
        var lookbehind = false;
        if (this.options.ecmaVersion >= 9) {
          lookbehind = state.eat(0x3C /* < */);
        }
        if (state.eat(0x3D /* = */) || state.eat(0x21 /* ! */)) {
          this.regexp_disjunction(state);
          if (!state.eat(0x29 /* ) */)) {
            state.raise("Unterminated group");
          }
          state.lastAssertionIsQuantifiable = !lookbehind;
          return true
        }
      }

      state.pos = start;
      return false
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier
    pp$9.regexp_eatQuantifier = function(state, noError) {
      if ( noError === void 0 ) noError = false;

      if (this.regexp_eatQuantifierPrefix(state, noError)) {
        state.eat(0x3F /* ? */);
        return true
      }
      return false
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix
    pp$9.regexp_eatQuantifierPrefix = function(state, noError) {
      return (
        state.eat(0x2A /* * */) ||
        state.eat(0x2B /* + */) ||
        state.eat(0x3F /* ? */) ||
        this.regexp_eatBracedQuantifier(state, noError)
      )
    };
    pp$9.regexp_eatBracedQuantifier = function(state, noError) {
      var start = state.pos;
      if (state.eat(0x7B /* { */)) {
        var min = 0, max = -1;
        if (this.regexp_eatDecimalDigits(state)) {
          min = state.lastIntValue;
          if (state.eat(0x2C /* , */) && this.regexp_eatDecimalDigits(state)) {
            max = state.lastIntValue;
          }
          if (state.eat(0x7D /* } */)) {
            // SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term
            if (max !== -1 && max < min && !noError) {
              state.raise("numbers out of order in {} quantifier");
            }
            return true
          }
        }
        if (state.switchU && !noError) {
          state.raise("Incomplete quantifier");
        }
        state.pos = start;
      }
      return false
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-Atom
    pp$9.regexp_eatAtom = function(state) {
      return (
        this.regexp_eatPatternCharacters(state) ||
        state.eat(0x2E /* . */) ||
        this.regexp_eatReverseSolidusAtomEscape(state) ||
        this.regexp_eatCharacterClass(state) ||
        this.regexp_eatUncapturingGroup(state) ||
        this.regexp_eatCapturingGroup(state)
      )
    };
    pp$9.regexp_eatReverseSolidusAtomEscape = function(state) {
      var start = state.pos;
      if (state.eat(0x5C /* \ */)) {
        if (this.regexp_eatAtomEscape(state)) {
          return true
        }
        state.pos = start;
      }
      return false
    };
    pp$9.regexp_eatUncapturingGroup = function(state) {
      var start = state.pos;
      if (state.eat(0x28 /* ( */)) {
        if (state.eat(0x3F /* ? */) && state.eat(0x3A /* : */)) {
          this.regexp_disjunction(state);
          if (state.eat(0x29 /* ) */)) {
            return true
          }
          state.raise("Unterminated group");
        }
        state.pos = start;
      }
      return false
    };
    pp$9.regexp_eatCapturingGroup = function(state) {
      if (state.eat(0x28 /* ( */)) {
        if (this.options.ecmaVersion >= 9) {
          this.regexp_groupSpecifier(state);
        } else if (state.current() === 0x3F /* ? */) {
          state.raise("Invalid group");
        }
        this.regexp_disjunction(state);
        if (state.eat(0x29 /* ) */)) {
          state.numCapturingParens += 1;
          return true
        }
        state.raise("Unterminated group");
      }
      return false
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom
    pp$9.regexp_eatExtendedAtom = function(state) {
      return (
        state.eat(0x2E /* . */) ||
        this.regexp_eatReverseSolidusAtomEscape(state) ||
        this.regexp_eatCharacterClass(state) ||
        this.regexp_eatUncapturingGroup(state) ||
        this.regexp_eatCapturingGroup(state) ||
        this.regexp_eatInvalidBracedQuantifier(state) ||
        this.regexp_eatExtendedPatternCharacter(state)
      )
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier
    pp$9.regexp_eatInvalidBracedQuantifier = function(state) {
      if (this.regexp_eatBracedQuantifier(state, true)) {
        state.raise("Nothing to repeat");
      }
      return false
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter
    pp$9.regexp_eatSyntaxCharacter = function(state) {
      var ch = state.current();
      if (isSyntaxCharacter(ch)) {
        state.lastIntValue = ch;
        state.advance();
        return true
      }
      return false
    };
    function isSyntaxCharacter(ch) {
      return (
        ch === 0x24 /* $ */ ||
        ch >= 0x28 /* ( */ && ch <= 0x2B /* + */ ||
        ch === 0x2E /* . */ ||
        ch === 0x3F /* ? */ ||
        ch >= 0x5B /* [ */ && ch <= 0x5E /* ^ */ ||
        ch >= 0x7B /* { */ && ch <= 0x7D /* } */
      )
    }

    // https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter
    // But eat eager.
    pp$9.regexp_eatPatternCharacters = function(state) {
      var start = state.pos;
      var ch = 0;
      while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) {
        state.advance();
      }
      return state.pos !== start
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter
    pp$9.regexp_eatExtendedPatternCharacter = function(state) {
      var ch = state.current();
      if (
        ch !== -1 &&
        ch !== 0x24 /* $ */ &&
        !(ch >= 0x28 /* ( */ && ch <= 0x2B /* + */) &&
        ch !== 0x2E /* . */ &&
        ch !== 0x3F /* ? */ &&
        ch !== 0x5B /* [ */ &&
        ch !== 0x5E /* ^ */ &&
        ch !== 0x7C /* | */
      ) {
        state.advance();
        return true
      }
      return false
    };

    // GroupSpecifier[U] ::
    //   [empty]
    //   `?` GroupName[?U]
    pp$9.regexp_groupSpecifier = function(state) {
      if (state.eat(0x3F /* ? */)) {
        if (this.regexp_eatGroupName(state)) {
          if (state.groupNames.indexOf(state.lastStringValue) !== -1) {
            state.raise("Duplicate capture group name");
          }
          state.groupNames.push(state.lastStringValue);
          return
        }
        state.raise("Invalid group");
      }
    };

    // GroupName[U] ::
    //   `<` RegExpIdentifierName[?U] `>`
    // Note: this updates `state.lastStringValue` property with the eaten name.
    pp$9.regexp_eatGroupName = function(state) {
      state.lastStringValue = "";
      if (state.eat(0x3C /* < */)) {
        if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E /* > */)) {
          return true
        }
        state.raise("Invalid capture group name");
      }
      return false
    };

    // RegExpIdentifierName[U] ::
    //   RegExpIdentifierStart[?U]
    //   RegExpIdentifierName[?U] RegExpIdentifierPart[?U]
    // Note: this updates `state.lastStringValue` property with the eaten name.
    pp$9.regexp_eatRegExpIdentifierName = function(state) {
      state.lastStringValue = "";
      if (this.regexp_eatRegExpIdentifierStart(state)) {
        state.lastStringValue += codePointToString$1(state.lastIntValue);
        while (this.regexp_eatRegExpIdentifierPart(state)) {
          state.lastStringValue += codePointToString$1(state.lastIntValue);
        }
        return true
      }
      return false
    };

    // RegExpIdentifierStart[U] ::
    //   UnicodeIDStart
    //   `$`
    //   `_`
    //   `\` RegExpUnicodeEscapeSequence[?U]
    pp$9.regexp_eatRegExpIdentifierStart = function(state) {
      var start = state.pos;
      var ch = state.current();
      state.advance();

      if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state)) {
        ch = state.lastIntValue;
      }
      if (isRegExpIdentifierStart(ch)) {
        state.lastIntValue = ch;
        return true
      }

      state.pos = start;
      return false
    };
    function isRegExpIdentifierStart(ch) {
      return isIdentifierStart(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */
    }

    // RegExpIdentifierPart[U] ::
    //   UnicodeIDContinue
    //   `$`
    //   `_`
    //   `\` RegExpUnicodeEscapeSequence[?U]
    //   <ZWNJ>
    //   <ZWJ>
    pp$9.regexp_eatRegExpIdentifierPart = function(state) {
      var start = state.pos;
      var ch = state.current();
      state.advance();

      if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state)) {
        ch = state.lastIntValue;
      }
      if (isRegExpIdentifierPart(ch)) {
        state.lastIntValue = ch;
        return true
      }

      state.pos = start;
      return false
    };
    function isRegExpIdentifierPart(ch) {
      return isIdentifierChar(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ || ch === 0x200C /* <ZWNJ> */ || ch === 0x200D /* <ZWJ> */
    }

    // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape
    pp$9.regexp_eatAtomEscape = function(state) {
      if (
        this.regexp_eatBackReference(state) ||
        this.regexp_eatCharacterClassEscape(state) ||
        this.regexp_eatCharacterEscape(state) ||
        (state.switchN && this.regexp_eatKGroupName(state))
      ) {
        return true
      }
      if (state.switchU) {
        // Make the same message as V8.
        if (state.current() === 0x63 /* c */) {
          state.raise("Invalid unicode escape");
        }
        state.raise("Invalid escape");
      }
      return false
    };
    pp$9.regexp_eatBackReference = function(state) {
      var start = state.pos;
      if (this.regexp_eatDecimalEscape(state)) {
        var n = state.lastIntValue;
        if (state.switchU) {
          // For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape
          if (n > state.maxBackReference) {
            state.maxBackReference = n;
          }
          return true
        }
        if (n <= state.numCapturingParens) {
          return true
        }
        state.pos = start;
      }
      return false
    };
    pp$9.regexp_eatKGroupName = function(state) {
      if (state.eat(0x6B /* k */)) {
        if (this.regexp_eatGroupName(state)) {
          state.backReferenceNames.push(state.lastStringValue);
          return true
        }
        state.raise("Invalid named reference");
      }
      return false
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape
    pp$9.regexp_eatCharacterEscape = function(state) {
      return (
        this.regexp_eatControlEscape(state) ||
        this.regexp_eatCControlLetter(state) ||
        this.regexp_eatZero(state) ||
        this.regexp_eatHexEscapeSequence(state) ||
        this.regexp_eatRegExpUnicodeEscapeSequence(state) ||
        (!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) ||
        this.regexp_eatIdentityEscape(state)
      )
    };
    pp$9.regexp_eatCControlLetter = function(state) {
      var start = state.pos;
      if (state.eat(0x63 /* c */)) {
        if (this.regexp_eatControlLetter(state)) {
          return true
        }
        state.pos = start;
      }
      return false
    };
    pp$9.regexp_eatZero = function(state) {
      if (state.current() === 0x30 /* 0 */ && !isDecimalDigit(state.lookahead())) {
        state.lastIntValue = 0;
        state.advance();
        return true
      }
      return false
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape
    pp$9.regexp_eatControlEscape = function(state) {
      var ch = state.current();
      if (ch === 0x74 /* t */) {
        state.lastIntValue = 0x09; /* \t */
        state.advance();
        return true
      }
      if (ch === 0x6E /* n */) {
        state.lastIntValue = 0x0A; /* \n */
        state.advance();
        return true
      }
      if (ch === 0x76 /* v */) {
        state.lastIntValue = 0x0B; /* \v */
        state.advance();
        return true
      }
      if (ch === 0x66 /* f */) {
        state.lastIntValue = 0x0C; /* \f */
        state.advance();
        return true
      }
      if (ch === 0x72 /* r */) {
        state.lastIntValue = 0x0D; /* \r */
        state.advance();
        return true
      }
      return false
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter
    pp$9.regexp_eatControlLetter = function(state) {
      var ch = state.current();
      if (isControlLetter(ch)) {
        state.lastIntValue = ch % 0x20;
        state.advance();
        return true
      }
      return false
    };
    function isControlLetter(ch) {
      return (
        (ch >= 0x41 /* A */ && ch <= 0x5A /* Z */) ||
        (ch >= 0x61 /* a */ && ch <= 0x7A /* z */)
      )
    }

    // https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence
    pp$9.regexp_eatRegExpUnicodeEscapeSequence = function(state) {
      var start = state.pos;

      if (state.eat(0x75 /* u */)) {
        if (this.regexp_eatFixedHexDigits(state, 4)) {
          var lead = state.lastIntValue;
          if (state.switchU && lead >= 0xD800 && lead <= 0xDBFF) {
            var leadSurrogateEnd = state.pos;
            if (state.eat(0x5C /* \ */) && state.eat(0x75 /* u */) && this.regexp_eatFixedHexDigits(state, 4)) {
              var trail = state.lastIntValue;
              if (trail >= 0xDC00 && trail <= 0xDFFF) {
                state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000;
                return true
              }
            }
            state.pos = leadSurrogateEnd;
            state.lastIntValue = lead;
          }
          return true
        }
        if (
          state.switchU &&
          state.eat(0x7B /* { */) &&
          this.regexp_eatHexDigits(state) &&
          state.eat(0x7D /* } */) &&
          isValidUnicode(state.lastIntValue)
        ) {
          return true
        }
        if (state.switchU) {
          state.raise("Invalid unicode escape");
        }
        state.pos = start;
      }

      return false
    };
    function isValidUnicode(ch) {
      return ch >= 0 && ch <= 0x10FFFF
    }

    // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape
    pp$9.regexp_eatIdentityEscape = function(state) {
      if (state.switchU) {
        if (this.regexp_eatSyntaxCharacter(state)) {
          return true
        }
        if (state.eat(0x2F /* / */)) {
          state.lastIntValue = 0x2F; /* / */
          return true
        }
        return false
      }

      var ch = state.current();
      if (ch !== 0x63 /* c */ && (!state.switchN || ch !== 0x6B /* k */)) {
        state.lastIntValue = ch;
        state.advance();
        return true
      }

      return false
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape
    pp$9.regexp_eatDecimalEscape = function(state) {
      state.lastIntValue = 0;
      var ch = state.current();
      if (ch >= 0x31 /* 1 */ && ch <= 0x39 /* 9 */) {
        do {
          state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */);
          state.advance();
        } while ((ch = state.current()) >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */)
        return true
      }
      return false
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape
    pp$9.regexp_eatCharacterClassEscape = function(state) {
      var ch = state.current();

      if (isCharacterClassEscape(ch)) {
        state.lastIntValue = -1;
        state.advance();
        return true
      }

      if (
        state.switchU &&
        this.options.ecmaVersion >= 9 &&
        (ch === 0x50 /* P */ || ch === 0x70 /* p */)
      ) {
        state.lastIntValue = -1;
        state.advance();
        if (
          state.eat(0x7B /* { */) &&
          this.regexp_eatUnicodePropertyValueExpression(state) &&
          state.eat(0x7D /* } */)
        ) {
          return true
        }
        state.raise("Invalid property name");
      }

      return false
    };
    function isCharacterClassEscape(ch) {
      return (
        ch === 0x64 /* d */ ||
        ch === 0x44 /* D */ ||
        ch === 0x73 /* s */ ||
        ch === 0x53 /* S */ ||
        ch === 0x77 /* w */ ||
        ch === 0x57 /* W */
      )
    }

    // UnicodePropertyValueExpression ::
    //   UnicodePropertyName `=` UnicodePropertyValue
    //   LoneUnicodePropertyNameOrValue
    pp$9.regexp_eatUnicodePropertyValueExpression = function(state) {
      var start = state.pos;

      // UnicodePropertyName `=` UnicodePropertyValue
      if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D /* = */)) {
        var name = state.lastStringValue;
        if (this.regexp_eatUnicodePropertyValue(state)) {
          var value = state.lastStringValue;
          this.regexp_validateUnicodePropertyNameAndValue(state, name, value);
          return true
        }
      }
      state.pos = start;

      // LoneUnicodePropertyNameOrValue
      if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) {
        var nameOrValue = state.lastStringValue;
        this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue);
        return true
      }
      return false
    };
    pp$9.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) {
      if (!data.hasOwnProperty(name) || data[name].indexOf(value) === -1) {
        state.raise("Invalid property name");
      }
    };
    pp$9.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) {
      if (data.$LONE.indexOf(nameOrValue) === -1) {
        state.raise("Invalid property name");
      }
    };

    // UnicodePropertyName ::
    //   UnicodePropertyNameCharacters
    pp$9.regexp_eatUnicodePropertyName = function(state) {
      var ch = 0;
      state.lastStringValue = "";
      while (isUnicodePropertyNameCharacter(ch = state.current())) {
        state.lastStringValue += codePointToString$1(ch);
        state.advance();
      }
      return state.lastStringValue !== ""
    };
    function isUnicodePropertyNameCharacter(ch) {
      return isControlLetter(ch) || ch === 0x5F /* _ */
    }

    // UnicodePropertyValue ::
    //   UnicodePropertyValueCharacters
    pp$9.regexp_eatUnicodePropertyValue = function(state) {
      var ch = 0;
      state.lastStringValue = "";
      while (isUnicodePropertyValueCharacter(ch = state.current())) {
        state.lastStringValue += codePointToString$1(ch);
        state.advance();
      }
      return state.lastStringValue !== ""
    };
    function isUnicodePropertyValueCharacter(ch) {
      return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch)
    }

    // LoneUnicodePropertyNameOrValue ::
    //   UnicodePropertyValueCharacters
    pp$9.regexp_eatLoneUnicodePropertyNameOrValue = function(state) {
      return this.regexp_eatUnicodePropertyValue(state)
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass
    pp$9.regexp_eatCharacterClass = function(state) {
      if (state.eat(0x5B /* [ */)) {
        state.eat(0x5E /* ^ */);
        this.regexp_classRanges(state);
        if (state.eat(0x5D /* [ */)) {
          return true
        }
        // Unreachable since it threw "unterminated regular expression" error before.
        state.raise("Unterminated character class");
      }
      return false
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassRanges
    // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRanges
    // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRangesNoDash
    pp$9.regexp_classRanges = function(state) {
      var this$1 = this;

      while (this.regexp_eatClassAtom(state)) {
        var left = state.lastIntValue;
        if (state.eat(0x2D /* - */) && this$1.regexp_eatClassAtom(state)) {
          var right = state.lastIntValue;
          if (state.switchU && (left === -1 || right === -1)) {
            state.raise("Invalid character class");
          }
          if (left !== -1 && right !== -1 && left > right) {
            state.raise("Range out of order in character class");
          }
        }
      }
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom
    // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash
    pp$9.regexp_eatClassAtom = function(state) {
      var start = state.pos;

      if (state.eat(0x5C /* \ */)) {
        if (this.regexp_eatClassEscape(state)) {
          return true
        }
        if (state.switchU) {
          // Make the same message as V8.
          var ch$1 = state.current();
          if (ch$1 === 0x63 /* c */ || isOctalDigit(ch$1)) {
            state.raise("Invalid class escape");
          }
          state.raise("Invalid escape");
        }
        state.pos = start;
      }

      var ch = state.current();
      if (ch !== 0x5D /* [ */) {
        state.lastIntValue = ch;
        state.advance();
        return true
      }

      return false
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape
    pp$9.regexp_eatClassEscape = function(state) {
      var start = state.pos;

      if (state.eat(0x62 /* b */)) {
        state.lastIntValue = 0x08; /* <BS> */
        return true
      }

      if (state.switchU && state.eat(0x2D /* - */)) {
        state.lastIntValue = 0x2D; /* - */
        return true
      }

      if (!state.switchU && state.eat(0x63 /* c */)) {
        if (this.regexp_eatClassControlLetter(state)) {
          return true
        }
        state.pos = start;
      }

      return (
        this.regexp_eatCharacterClassEscape(state) ||
        this.regexp_eatCharacterEscape(state)
      )
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter
    pp$9.regexp_eatClassControlLetter = function(state) {
      var ch = state.current();
      if (isDecimalDigit(ch) || ch === 0x5F /* _ */) {
        state.lastIntValue = ch % 0x20;
        state.advance();
        return true
      }
      return false
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
    pp$9.regexp_eatHexEscapeSequence = function(state) {
      var start = state.pos;
      if (state.eat(0x78 /* x */)) {
        if (this.regexp_eatFixedHexDigits(state, 2)) {
          return true
        }
        if (state.switchU) {
          state.raise("Invalid escape");
        }
        state.pos = start;
      }
      return false
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits
    pp$9.regexp_eatDecimalDigits = function(state) {
      var start = state.pos;
      var ch = 0;
      state.lastIntValue = 0;
      while (isDecimalDigit(ch = state.current())) {
        state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */);
        state.advance();
      }
      return state.pos !== start
    };
    function isDecimalDigit(ch) {
      return ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */
    }

    // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits
    pp$9.regexp_eatHexDigits = function(state) {
      var start = state.pos;
      var ch = 0;
      state.lastIntValue = 0;
      while (isHexDigit(ch = state.current())) {
        state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
        state.advance();
      }
      return state.pos !== start
    };
    function isHexDigit(ch) {
      return (
        (ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) ||
        (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) ||
        (ch >= 0x61 /* a */ && ch <= 0x66 /* f */)
      )
    }
    function hexToInt(ch) {
      if (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) {
        return 10 + (ch - 0x41 /* A */)
      }
      if (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) {
        return 10 + (ch - 0x61 /* a */)
      }
      return ch - 0x30 /* 0 */
    }

    // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence
    // Allows only 0-377(octal) i.e. 0-255(decimal).
    pp$9.regexp_eatLegacyOctalEscapeSequence = function(state) {
      if (this.regexp_eatOctalDigit(state)) {
        var n1 = state.lastIntValue;
        if (this.regexp_eatOctalDigit(state)) {
          var n2 = state.lastIntValue;
          if (n1 <= 3 && this.regexp_eatOctalDigit(state)) {
            state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue;
          } else {
            state.lastIntValue = n1 * 8 + n2;
          }
        } else {
          state.lastIntValue = n1;
        }
        return true
      }
      return false
    };

    // https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit
    pp$9.regexp_eatOctalDigit = function(state) {
      var ch = state.current();
      if (isOctalDigit(ch)) {
        state.lastIntValue = ch - 0x30; /* 0 */
        state.advance();
        return true
      }
      state.lastIntValue = 0;
      return false
    };
    function isOctalDigit(ch) {
      return ch >= 0x30 /* 0 */ && ch <= 0x37 /* 7 */
    }

    // https://www.ecma-international.org/ecma-262/8.0/#prod-Hex4Digits
    // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigit
    // And HexDigit HexDigit in https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
    pp$9.regexp_eatFixedHexDigits = function(state, length) {
      var start = state.pos;
      state.lastIntValue = 0;
      for (var i = 0; i < length; ++i) {
        var ch = state.current();
        if (!isHexDigit(ch)) {
          state.pos = start;
          return false
        }
        state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
        state.advance();
      }
      return true
    };

    // Object type used to represent tokens. Note that normally, tokens
    // simply exist as properties on the parser object. This is only
    // used for the onToken callback and the external tokenizer.

    var Token = function Token(p) {
      this.type = p.type;
      this.value = p.value;
      this.start = p.start;
      this.end = p.end;
      if (p.options.locations)
        { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); }
      if (p.options.ranges)
        { this.range = [p.start, p.end]; }
    };

    // ## Tokenizer

    var pp$8 = Parser.prototype;

    // Move to the next token

    pp$8.next = function() {
      if (this.options.onToken)
        { this.options.onToken(new Token(this)); }

      this.lastTokEnd = this.end;
      this.lastTokStart = this.start;
      this.lastTokEndLoc = this.endLoc;
      this.lastTokStartLoc = this.startLoc;
      this.nextToken();
    };

    pp$8.getToken = function() {
      this.next();
      return new Token(this)
    };

    // If we're in an ES6 environment, make parsers iterable
    if (typeof Symbol !== "undefined")
      { pp$8[Symbol.iterator] = function() {
        var this$1 = this;

        return {
          next: function () {
            var token = this$1.getToken();
            return {
              done: token.type === types.eof,
              value: token
            }
          }
        }
      }; }

    // Toggle strict mode. Re-reads the next number or string to please
    // pedantic tests (`"use strict"; 010;` should fail).

    pp$8.curContext = function() {
      return this.context[this.context.length - 1]
    };

    // Read a single token, updating the parser object's token-related
    // properties.

    pp$8.nextToken = function() {
      var curContext = this.curContext();
      if (!curContext || !curContext.preserveSpace) { this.skipSpace(); }

      this.start = this.pos;
      if (this.options.locations) { this.startLoc = this.curPosition(); }
      if (this.pos >= this.input.length) { return this.finishToken(types.eof) }

      if (curContext.override) { return curContext.override(this) }
      else { this.readToken(this.fullCharCodeAtPos()); }
    };

    pp$8.readToken = function(code) {
      // Identifier or keyword. '\uXXXX' sequences are allowed in
      // identifiers, so '\' also dispatches to that.
      if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */)
        { return this.readWord() }

      return this.getTokenFromCode(code)
    };

    pp$8.fullCharCodeAtPos = function() {
      var code = this.input.charCodeAt(this.pos);
      if (code <= 0xd7ff || code >= 0xe000) { return code }
      var next = this.input.charCodeAt(this.pos + 1);
      return (code << 10) + next - 0x35fdc00
    };

    pp$8.skipBlockComment = function() {
      var this$1 = this;

      var startLoc = this.options.onComment && this.curPosition();
      var start = this.pos, end = this.input.indexOf("*/", this.pos += 2);
      if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); }
      this.pos = end + 2;
      if (this.options.locations) {
        lineBreakG.lastIndex = start;
        var match;
        while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) {
          ++this$1.curLine;
          this$1.lineStart = match.index + match[0].length;
        }
      }
      if (this.options.onComment)
        { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos,
                               startLoc, this.curPosition()); }
    };

    pp$8.skipLineComment = function(startSkip) {
      var this$1 = this;

      var start = this.pos;
      var startLoc = this.options.onComment && this.curPosition();
      var ch = this.input.charCodeAt(this.pos += startSkip);
      while (this.pos < this.input.length && !isNewLine(ch)) {
        ch = this$1.input.charCodeAt(++this$1.pos);
      }
      if (this.options.onComment)
        { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos,
                               startLoc, this.curPosition()); }
    };

    // Called at the start of the parse and after every token. Skips
    // whitespace and comments, and.

    pp$8.skipSpace = function() {
      var this$1 = this;

      loop: while (this.pos < this.input.length) {
        var ch = this$1.input.charCodeAt(this$1.pos);
        switch (ch) {
        case 32: case 160: // ' '
          ++this$1.pos;
          break
        case 13:
          if (this$1.input.charCodeAt(this$1.pos + 1) === 10) {
            ++this$1.pos;
          }
        case 10: case 8232: case 8233:
          ++this$1.pos;
          if (this$1.options.locations) {
            ++this$1.curLine;
            this$1.lineStart = this$1.pos;
          }
          break
        case 47: // '/'
          switch (this$1.input.charCodeAt(this$1.pos + 1)) {
          case 42: // '*'
            this$1.skipBlockComment();
            break
          case 47:
            this$1.skipLineComment(2);
            break
          default:
            break loop
          }
          break
        default:
          if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
            ++this$1.pos;
          } else {
            break loop
          }
        }
      }
    };

    // Called at the end of every token. Sets `end`, `val`, and
    // maintains `context` and `exprAllowed`, and skips the space after
    // the token, so that the next one's `start` will point at the
    // right position.

    pp$8.finishToken = function(type, val) {
      this.end = this.pos;
      if (this.options.locations) { this.endLoc = this.curPosition(); }
      var prevType = this.type;
      this.type = type;
      this.value = val;

      this.updateContext(prevType);
    };

    // ### Token reading

    // This is the function that is called to fetch the next token. It
    // is somewhat obscure, because it works in character codes rather
    // than characters, and because operator parsing has been inlined
    // into it.
    //
    // All in the name of speed.
    //
    pp$8.readToken_dot = function() {
      var next = this.input.charCodeAt(this.pos + 1);
      if (next >= 48 && next <= 57) { return this.readNumber(true) }
      var next2 = this.input.charCodeAt(this.pos + 2);
      if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.'
        this.pos += 3;
        return this.finishToken(types.ellipsis)
      } else {
        ++this.pos;
        return this.finishToken(types.dot)
      }
    };

    pp$8.readToken_slash = function() { // '/'
      var next = this.input.charCodeAt(this.pos + 1);
      if (this.exprAllowed) { ++this.pos; return this.readRegexp() }
      if (next === 61) { return this.finishOp(types.assign, 2) }
      return this.finishOp(types.slash, 1)
    };

    pp$8.readToken_mult_modulo_exp = function(code) { // '%*'
      var next = this.input.charCodeAt(this.pos + 1);
      var size = 1;
      var tokentype = code === 42 ? types.star : types.modulo;

      // exponentiation operator ** and **=
      if (this.options.ecmaVersion >= 7 && code == 42 && next === 42) {
        ++size;
        tokentype = types.starstar;
        next = this.input.charCodeAt(this.pos + 2);
      }

      if (next === 61) { return this.finishOp(types.assign, size + 1) }
      return this.finishOp(tokentype, size)
    };

    pp$8.readToken_pipe_amp = function(code) { // '|&'
      var next = this.input.charCodeAt(this.pos + 1);
      if (next === code) { return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2) }
      if (next === 61) { return this.finishOp(types.assign, 2) }
      return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1)
    };

    pp$8.readToken_caret = function() { // '^'
      var next = this.input.charCodeAt(this.pos + 1);
      if (next === 61) { return this.finishOp(types.assign, 2) }
      return this.finishOp(types.bitwiseXOR, 1)
    };

    pp$8.readToken_plus_min = function(code) { // '+-'
      var next = this.input.charCodeAt(this.pos + 1);
      if (next === code) {
        if (next == 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 62 &&
            (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) {
          // A `-->` line comment
          this.skipLineComment(3);
          this.skipSpace();
          return this.nextToken()
        }
        return this.finishOp(types.incDec, 2)
      }
      if (next === 61) { return this.finishOp(types.assign, 2) }
      return this.finishOp(types.plusMin, 1)
    };

    pp$8.readToken_lt_gt = function(code) { // '<>'
      var next = this.input.charCodeAt(this.pos + 1);
      var size = 1;
      if (next === code) {
        size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2;
        if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types.assign, size + 1) }
        return this.finishOp(types.bitShift, size)
      }
      if (next == 33 && code == 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 45 &&
          this.input.charCodeAt(this.pos + 3) == 45) {
        // `<!--`, an XML-style comment that should be interpreted as a line comment
        this.skipLineComment(4);
        this.skipSpace();
        return this.nextToken()
      }
      if (next === 61) { size = 2; }
      return this.finishOp(types.relational, size)
    };

    pp$8.readToken_eq_excl = function(code) { // '=!'
      var next = this.input.charCodeAt(this.pos + 1);
      if (next === 61) { return this.finishOp(types.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2) }
      if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { // '=>'
        this.pos += 2;
        return this.finishToken(types.arrow)
      }
      return this.finishOp(code === 61 ? types.eq : types.prefix, 1)
    };

    pp$8.getTokenFromCode = function(code) {
      switch (code) {
      // The interpretation of a dot depends on whether it is followed
      // by a digit or another two dots.
      case 46: // '.'
        return this.readToken_dot()

      // Punctuation tokens.
      case 40: ++this.pos; return this.finishToken(types.parenL)
      case 41: ++this.pos; return this.finishToken(types.parenR)
      case 59: ++this.pos; return this.finishToken(types.semi)
      case 44: ++this.pos; return this.finishToken(types.comma)
      case 91: ++this.pos; return this.finishToken(types.bracketL)
      case 93: ++this.pos; return this.finishToken(types.bracketR)
      case 123: ++this.pos; return this.finishToken(types.braceL)
      case 125: ++this.pos; return this.finishToken(types.braceR)
      case 58: ++this.pos; return this.finishToken(types.colon)
      case 63: ++this.pos; return this.finishToken(types.question)

      case 96: // '`'
        if (this.options.ecmaVersion < 6) { break }
        ++this.pos;
        return this.finishToken(types.backQuote)

      case 48: // '0'
        var next = this.input.charCodeAt(this.pos + 1);
        if (next === 120 || next === 88) { return this.readRadixNumber(16) } // '0x', '0X' - hex number
        if (this.options.ecmaVersion >= 6) {
          if (next === 111 || next === 79) { return this.readRadixNumber(8) } // '0o', '0O' - octal number
          if (next === 98 || next === 66) { return this.readRadixNumber(2) } // '0b', '0B' - binary number
        }

      // Anything else beginning with a digit is an integer, octal
      // number, or float.
      case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9
        return this.readNumber(false)

      // Quotes produce strings.
      case 34: case 39: // '"', "'"
        return this.readString(code)

      // Operators are parsed inline in tiny state machines. '=' (61) is
      // often referred to. `finishOp` simply skips the amount of
      // characters it is given as second argument, and returns a token
      // of the type given by its first argument.

      case 47: // '/'
        return this.readToken_slash()

      case 37: case 42: // '%*'
        return this.readToken_mult_modulo_exp(code)

      case 124: case 38: // '|&'
        return this.readToken_pipe_amp(code)

      case 94: // '^'
        return this.readToken_caret()

      case 43: case 45: // '+-'
        return this.readToken_plus_min(code)

      case 60: case 62: // '<>'
        return this.readToken_lt_gt(code)

      case 61: case 33: // '=!'
        return this.readToken_eq_excl(code)

      case 126: // '~'
        return this.finishOp(types.prefix, 1)
      }

      this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'");
    };

    pp$8.finishOp = function(type, size) {
      var str = this.input.slice(this.pos, this.pos + size);
      this.pos += size;
      return this.finishToken(type, str)
    };

    pp$8.readRegexp = function() {
      var this$1 = this;

      var escaped, inClass, start = this.pos;
      for (;;) {
        if (this$1.pos >= this$1.input.length) { this$1.raise(start, "Unterminated regular expression"); }
        var ch = this$1.input.charAt(this$1.pos);
        if (lineBreak.test(ch)) { this$1.raise(start, "Unterminated regular expression"); }
        if (!escaped) {
          if (ch === "[") { inClass = true; }
          else if (ch === "]" && inClass) { inClass = false; }
          else if (ch === "/" && !inClass) { break }
          escaped = ch === "\\";
        } else { escaped = false; }
        ++this$1.pos;
      }
      var pattern = this.input.slice(start, this.pos);
      ++this.pos;
      var flagsStart = this.pos;
      var flags = this.readWord1();
      if (this.containsEsc) { this.unexpected(flagsStart); }

      // Validate pattern
      var state = this.regexpState || (this.regexpState = new RegExpValidationState(this));
      state.reset(start, pattern, flags);
      this.validateRegExpFlags(state);
      this.validateRegExpPattern(state);

      // Create Literal#value property value.
      var value = null;
      try {
        value = new RegExp(pattern, flags);
      } catch (e) {
        // ESTree requires null if it failed to instantiate RegExp object.
        // https://github.com/estree/estree/blob/a27003adf4fd7bfad44de9cef372a2eacd527b1c/es5.md#regexpliteral
      }

      return this.finishToken(types.regexp, {pattern: pattern, flags: flags, value: value})
    };

    // Read an integer in the given radix. Return null if zero digits
    // were read, the integer value otherwise. When `len` is given, this
    // will return `null` unless the integer has exactly `len` digits.

    pp$8.readInt = function(radix, len) {
      var this$1 = this;

      var start = this.pos, total = 0;
      for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) {
        var code = this$1.input.charCodeAt(this$1.pos), val = (void 0);
        if (code >= 97) { val = code - 97 + 10; } // a
        else if (code >= 65) { val = code - 65 + 10; } // A
        else if (code >= 48 && code <= 57) { val = code - 48; } // 0-9
        else { val = Infinity; }
        if (val >= radix) { break }
        ++this$1.pos;
        total = total * radix + val;
      }
      if (this.pos === start || len != null && this.pos - start !== len) { return null }

      return total
    };

    pp$8.readRadixNumber = function(radix) {
      this.pos += 2; // 0x
      var val = this.readInt(radix);
      if (val == null) { this.raise(this.start + 2, "Expected number in radix " + radix); }
      if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
      return this.finishToken(types.num, val)
    };

    // Read an integer, octal integer, or floating-point number.

    pp$8.readNumber = function(startsWithDot) {
      var start = this.pos;
      if (!startsWithDot && this.readInt(10) === null) { this.raise(start, "Invalid number"); }
      var octal = this.pos - start >= 2 && this.input.charCodeAt(start) === 48;
      if (octal && this.strict) { this.raise(start, "Invalid number"); }
      if (octal && /[89]/.test(this.input.slice(start, this.pos))) { octal = false; }
      var next = this.input.charCodeAt(this.pos);
      if (next === 46 && !octal) { // '.'
        ++this.pos;
        this.readInt(10);
        next = this.input.charCodeAt(this.pos);
      }
      if ((next === 69 || next === 101) && !octal) { // 'eE'
        next = this.input.charCodeAt(++this.pos);
        if (next === 43 || next === 45) { ++this.pos; } // '+-'
        if (this.readInt(10) === null) { this.raise(start, "Invalid number"); }
      }
      if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }

      var str = this.input.slice(start, this.pos);
      var val = octal ? parseInt(str, 8) : parseFloat(str);
      return this.finishToken(types.num, val)
    };

    // Read a string value, interpreting backslash-escapes.

    pp$8.readCodePoint = function() {
      var ch = this.input.charCodeAt(this.pos), code;

      if (ch === 123) { // '{'
        if (this.options.ecmaVersion < 6) { this.unexpected(); }
        var codePos = ++this.pos;
        code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos);
        ++this.pos;
        if (code > 0x10FFFF) { this.invalidStringToken(codePos, "Code point out of bounds"); }
      } else {
        code = this.readHexChar(4);
      }
      return code
    };

    function codePointToString(code) {
      // UTF-16 Decoding
      if (code <= 0xFFFF) { return String.fromCharCode(code) }
      code -= 0x10000;
      return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00)
    }

    pp$8.readString = function(quote) {
      var this$1 = this;

      var out = "", chunkStart = ++this.pos;
      for (;;) {
        if (this$1.pos >= this$1.input.length) { this$1.raise(this$1.start, "Unterminated string constant"); }
        var ch = this$1.input.charCodeAt(this$1.pos);
        if (ch === quote) { break }
        if (ch === 92) { // '\'
          out += this$1.input.slice(chunkStart, this$1.pos);
          out += this$1.readEscapedChar(false);
          chunkStart = this$1.pos;
        } else {
          if (isNewLine(ch)) { this$1.raise(this$1.start, "Unterminated string constant"); }
          ++this$1.pos;
        }
      }
      out += this.input.slice(chunkStart, this.pos++);
      return this.finishToken(types.string, out)
    };

    // Reads template string tokens.

    var INVALID_TEMPLATE_ESCAPE_ERROR = {};

    pp$8.tryReadTemplateToken = function() {
      this.inTemplateElement = true;
      try {
        this.readTmplToken();
      } catch (err) {
        if (err === INVALID_TEMPLATE_ESCAPE_ERROR) {
          this.readInvalidTemplateToken();
        } else {
          throw err
        }
      }

      this.inTemplateElement = false;
    };

    pp$8.invalidStringToken = function(position, message) {
      if (this.inTemplateElement && this.options.ecmaVersion >= 9) {
        throw INVALID_TEMPLATE_ESCAPE_ERROR
      } else {
        this.raise(position, message);
      }
    };

    pp$8.readTmplToken = function() {
      var this$1 = this;

      var out = "", chunkStart = this.pos;
      for (;;) {
        if (this$1.pos >= this$1.input.length) { this$1.raise(this$1.start, "Unterminated template"); }
        var ch = this$1.input.charCodeAt(this$1.pos);
        if (ch === 96 || ch === 36 && this$1.input.charCodeAt(this$1.pos + 1) === 123) { // '`', '${'
          if (this$1.pos === this$1.start && (this$1.type === types.template || this$1.type === types.invalidTemplate)) {
            if (ch === 36) {
              this$1.pos += 2;
              return this$1.finishToken(types.dollarBraceL)
            } else {
              ++this$1.pos;
              return this$1.finishToken(types.backQuote)
            }
          }
          out += this$1.input.slice(chunkStart, this$1.pos);
          return this$1.finishToken(types.template, out)
        }
        if (ch === 92) { // '\'
          out += this$1.input.slice(chunkStart, this$1.pos);
          out += this$1.readEscapedChar(true);
          chunkStart = this$1.pos;
        } else if (isNewLine(ch)) {
          out += this$1.input.slice(chunkStart, this$1.pos);
          ++this$1.pos;
          switch (ch) {
          case 13:
            if (this$1.input.charCodeAt(this$1.pos) === 10) { ++this$1.pos; }
          case 10:
            out += "\n";
            break
          default:
            out += String.fromCharCode(ch);
            break
          }
          if (this$1.options.locations) {
            ++this$1.curLine;
            this$1.lineStart = this$1.pos;
          }
          chunkStart = this$1.pos;
        } else {
          ++this$1.pos;
        }
      }
    };

    // Reads a template token to search for the end, without validating any escape sequences
    pp$8.readInvalidTemplateToken = function() {
      var this$1 = this;

      for (; this.pos < this.input.length; this.pos++) {
        switch (this$1.input[this$1.pos]) {
        case "\\":
          ++this$1.pos;
          break

        case "$":
          if (this$1.input[this$1.pos + 1] !== "{") {
            break
          }
        // falls through

        case "`":
          return this$1.finishToken(types.invalidTemplate, this$1.input.slice(this$1.start, this$1.pos))

        // no default
        }
      }
      this.raise(this.start, "Unterminated template");
    };

    // Used to read escaped characters

    pp$8.readEscapedChar = function(inTemplate) {
      var ch = this.input.charCodeAt(++this.pos);
      ++this.pos;
      switch (ch) {
      case 110: return "\n" // 'n' -> '\n'
      case 114: return "\r" // 'r' -> '\r'
      case 120: return String.fromCharCode(this.readHexChar(2)) // 'x'
      case 117: return codePointToString(this.readCodePoint()) // 'u'
      case 116: return "\t" // 't' -> '\t'
      case 98: return "\b" // 'b' -> '\b'
      case 118: return "\u000b" // 'v' -> '\u000b'
      case 102: return "\f" // 'f' -> '\f'
      case 13: if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } // '\r\n'
      case 10: // ' \n'
        if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; }
        return ""
      default:
        if (ch >= 48 && ch <= 55) {
          var octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0];
          var octal = parseInt(octalStr, 8);
          if (octal > 255) {
            octalStr = octalStr.slice(0, -1);
            octal = parseInt(octalStr, 8);
          }
          this.pos += octalStr.length - 1;
          ch = this.input.charCodeAt(this.pos);
          if ((octalStr !== "0" || ch == 56 || ch == 57) && (this.strict || inTemplate)) {
            this.invalidStringToken(
              this.pos - 1 - octalStr.length,
              inTemplate
                ? "Octal literal in template string"
                : "Octal literal in strict mode"
            );
          }
          return String.fromCharCode(octal)
        }
        return String.fromCharCode(ch)
      }
    };

    // Used to read character escape sequences ('\x', '\u', '\U').

    pp$8.readHexChar = function(len) {
      var codePos = this.pos;
      var n = this.readInt(16, len);
      if (n === null) { this.invalidStringToken(codePos, "Bad character escape sequence"); }
      return n
    };

    // Read an identifier, and return it as a string. Sets `this.containsEsc`
    // to whether the word contained a '\u' escape.
    //
    // Incrementally adds only escaped chars, adding other chunks as-is
    // as a micro-optimization.

    pp$8.readWord1 = function() {
      var this$1 = this;

      this.containsEsc = false;
      var word = "", first = true, chunkStart = this.pos;
      var astral = this.options.ecmaVersion >= 6;
      while (this.pos < this.input.length) {
        var ch = this$1.fullCharCodeAtPos();
        if (isIdentifierChar(ch, astral)) {
          this$1.pos += ch <= 0xffff ? 1 : 2;
        } else if (ch === 92) { // "\"
          this$1.containsEsc = true;
          word += this$1.input.slice(chunkStart, this$1.pos);
          var escStart = this$1.pos;
          if (this$1.input.charCodeAt(++this$1.pos) != 117) // "u"
            { this$1.invalidStringToken(this$1.pos, "Expecting Unicode escape sequence \\uXXXX"); }
          ++this$1.pos;
          var esc = this$1.readCodePoint();
          if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral))
            { this$1.invalidStringToken(escStart, "Invalid Unicode escape"); }
          word += codePointToString(esc);
          chunkStart = this$1.pos;
        } else {
          break
        }
        first = false;
      }
      return word + this.input.slice(chunkStart, this.pos)
    };

    // Read an identifier or keyword token. Will check for reserved
    // words when necessary.

    pp$8.readWord = function() {
      var word = this.readWord1();
      var type = types.name;
      if (this.keywords.test(word)) {
        if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword " + word); }
        type = keywords$1[word];
      }
      return this.finishToken(type, word)
    };

    // Acorn is a tiny, fast JavaScript parser written in JavaScript.
    //
    // Acorn was written by Marijn Haverbeke, Ingvar Stepanyan, and
    // various contributors and released under an MIT license.
    //
    // Git repositories for Acorn are available at
    //
    //     http://marijnhaverbeke.nl/git/acorn
    //     https://github.com/acornjs/acorn.git
    //
    // Please use the [github bug tracker][ghbt] to report issues.
    //
    // [ghbt]: https://github.com/acornjs/acorn/issues
    //
    // This file defines the main parser interface. The library also comes
    // with a [error-tolerant parser][dammit] and an
    // [abstract syntax tree walker][walk], defined in other files.
    //
    // [dammit]: acorn_loose.js
    // [walk]: util/walk.js

    var version = "5.5.3";

    // The main exported interface (under `self.acorn` when in the
    // browser) is a `parse` function that takes a code string and
    // returns an abstract syntax tree as specified by [Mozilla parser
    // API][api].
    //
    // [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API

    function parse(input, options) {
      return new Parser(options, input).parse()
    }

    // This function tries to parse a single expression at a given
    // offset in a string. Useful for parsing mixed-language formats
    // that embed JavaScript expressions.

    function parseExpressionAt(input, pos, options) {
      var p = new Parser(options, input, pos);
      p.nextToken();
      return p.parseExpression()
    }

    // Acorn is organized as a tokenizer and a recursive-descent parser.
    // The `tokenizer` export provides an interface to the tokenizer.

    function tokenizer(input, options) {
      return new Parser(options, input)
    }

    // This is a terrible kludge to support the existing, pre-ES6
    // interface where the loose parser module retroactively adds exports
    // to this module.
    var parse_dammit;
    var LooseParser;
    var pluginsLoose; // eslint-disable-line camelcase
    function addLooseExports(parse, Parser$$1, plugins$$1) {
      parse_dammit = parse; // eslint-disable-line camelcase
      LooseParser = Parser$$1;
      pluginsLoose = plugins$$1;
    }

    var acorn = /*#__PURE__*/Object.freeze({
        version: version,
        parse: parse,
        parseExpressionAt: parseExpressionAt,
        tokenizer: tokenizer,
        get parse_dammit () { return parse_dammit; },
        get LooseParser () { return LooseParser; },
        get pluginsLoose () { return pluginsLoose; },
        addLooseExports: addLooseExports,
        Parser: Parser,
        plugins: plugins,
        defaultOptions: defaultOptions,
        Position: Position,
        SourceLocation: SourceLocation,
        getLineInfo: getLineInfo,
        Node: Node,
        TokenType: TokenType,
        tokTypes: types,
        keywordTypes: keywords$1,
        TokContext: TokContext,
        tokContexts: types$1,
        isIdentifierChar: isIdentifierChar,
        isIdentifierStart: isIdentifierStart,
        Token: Token,
        isNewLine: isNewLine,
        lineBreak: lineBreak,
        lineBreakG: lineBreakG,
        nonASCIIwhitespace: nonASCIIwhitespace
    });

    const literals = new Map([['true', true], ['false', false], ['null', null]]);
    function readExpression(parser) {
        const start = parser.index;
        const name = parser.readUntil(/\s*}/);
        if (name && /^[a-z]+$/.test(name)) {
            const end = start + name.length;
            if (literals.has(name)) {
                return {
                    type: 'Literal',
                    start,
                    end,
                    value: literals.get(name),
                    raw: name,
                };
            }
            return {
                type: 'Identifier',
                start,
                end: start + name.length,
                name,
            };
        }
        parser.index = start;
        try {
            const node = parseExpressionAt(parser.template, parser.index, {
                ecmaVersion: 9,
                preserveParens: true,
            });
            parser.index = node.end;
            return node;
        }
        catch (err) {
            parser.acornError(err);
        }
    }

    /* eslint-disable no-underscore-dangle */

    const DynamicImportKey = 'Import';

    function injectDynamicImport(acorn) {
      const tt = acorn.tokTypes;

      // NOTE: This allows `yield import()` to parse correctly.
      tt._import.startsExpr = true;

      function parseDynamicImport() {
        const node = this.startNode();
        this.next();
        if (this.type !== tt.parenL) {
          this.unexpected();
        }
        return this.finishNode(node, DynamicImportKey);
      }

      function peekNext() {
        return this.input[this.pos];
      }

      // eslint-disable-next-line no-param-reassign
      acorn.plugins.dynamicImport = function dynamicImportPlugin(instance) {
        instance.extend('parseStatement', nextMethod => (
          function parseStatement(...args) {
            const node = this.startNode();
            if (this.type === tt._import) {
              const nextToken = peekNext.call(this);
              if (nextToken === tt.parenL.label) {
                const expr = this.parseExpression();
                return this.parseExpressionStatement(node, expr);
              }
            }

            return nextMethod.apply(this, args);
          }
        ));

        instance.extend('parseExprAtom', nextMethod => (
          function parseExprAtom(refDestructuringErrors) {
            if (this.type === tt._import) {
              return parseDynamicImport.call(this);
            }
            return nextMethod.call(this, refDestructuringErrors);
          }
        ));
      };

      return acorn;
    }

    function repeat(str, i) {
        let result = '';
        while (i--)
            result += str;
        return result;
    }

    const scriptClosingTag = '</script>';
    injectDynamicImport(acorn);
    function readScript(parser, start, attributes) {
        const scriptStart = parser.index;
        const scriptEnd = parser.template.indexOf(scriptClosingTag, scriptStart);
        if (scriptEnd === -1)
            parser.error({
                code: `unclosed-script`,
                message: `<script> must have a closing tag`
            });
        const source = repeat(' ', scriptStart) + parser.template.slice(scriptStart, scriptEnd);
        parser.index = scriptEnd + scriptClosingTag.length;
        let ast;
        try {
            ast = parse(source, {
                ecmaVersion: 9,
                sourceType: 'module',
                plugins: {
                    dynamicImport: true
                }
            });
        }
        catch (err) {
            parser.acornError(err);
        }
        if (!ast.body.length)
            return null;
        ast.start = scriptStart;
        return {
            start,
            end: parser.index,
            attributes,
            content: ast,
        };
    }

    var MAX_LINE_LENGTH = 100;
    var OFFSET_CORRECTION = 60;
    var TAB_REPLACEMENT = '    ';

    function sourceFragment(error, extraLines) {
        function processLines(start, end) {
            return lines.slice(start, end).map(function(line, idx) {
                var num = String(start + idx + 1);

                while (num.length < maxNumLength) {
                    num = ' ' + num;
                }

                return num + ' |' + line;
            }).join('\n');
        }

        var lines = error.source.split(/\n|\r\n?|\f/);
        var line = error.line;
        var column = error.column;
        var startLine = Math.max(1, line - extraLines) - 1;
        var endLine = Math.min(line + extraLines, lines.length + 1);
        var maxNumLength = Math.max(4, String(endLine).length) + 1;
        var cutLeft = 0;

        // correct column according to replaced tab before column
        column += (TAB_REPLACEMENT.length - 1) * (lines[line - 1].substr(0, column - 1).match(/\t/g) || []).length;

        if (column > MAX_LINE_LENGTH) {
            cutLeft = column - OFFSET_CORRECTION + 3;
            column = OFFSET_CORRECTION - 2;
        }

        for (var i = startLine; i <= endLine; i++) {
            if (i >= 0 && i < lines.length) {
                lines[i] = lines[i].replace(/\t/g, TAB_REPLACEMENT);
                lines[i] =
                    (cutLeft > 0 && lines[i].length > cutLeft ? '\u2026' : '') +
                    lines[i].substr(cutLeft, MAX_LINE_LENGTH - 2) +
                    (lines[i].length > cutLeft + MAX_LINE_LENGTH - 1 ? '\u2026' : '');
            }
        }

        return [
            processLines(startLine, line),
            new Array(column + maxNumLength + 2).join('-') + '^',
            processLines(line, endLine)
        ].join('\n');
    }

    var CssSyntaxError = function(message, source, offset, line, column) {
        // some VMs prevent setting line/column otherwise (iOS Safari 10 even throw an exception)
        var error = Object.create(SyntaxError.prototype);

        error.name = 'CssSyntaxError';
        error.message = message;
        error.stack = (new Error().stack || '').replace(/^.+\n/, error.name + ': ' + error.message + '\n');
        error.source = source;
        error.offset = offset;
        error.line = line;
        error.column = column;

        error.sourceFragment = function(extraLines) {
            return sourceFragment(error, isNaN(extraLines) ? 0 : extraLines);
        };
        Object.defineProperty(error, 'formattedMessage', {
            get: function() {
                return (
                    'Parse error: ' + error.message + '\n' +
                    sourceFragment(error, 2)
                );
            }
        });

        // for backward capability
        error.parseError = {
            offset: offset,
            line: line,
            column: column
        };

        return error;
    };

    var error = CssSyntaxError;

    var error$1 = /*#__PURE__*/Object.freeze({
        default: error,
        __moduleExports: error
    });

    // token types (note: value shouldn't intersect with used char codes)
    var WHITESPACE = 1;
    var IDENTIFIER = 2;
    var NUMBER = 3;
    var STRING = 4;
    var COMMENT = 5;
    var PUNCTUATOR = 6;
    var CDO = 7;
    var CDC = 8;
    var ATRULE = 14;
    var FUNCTION = 15;
    var URL = 16;
    var RAW = 17;

    var TAB = 9;
    var N = 10;
    var F = 12;
    var R = 13;
    var SPACE = 32;

    var TYPE = {
        WhiteSpace:   WHITESPACE,
        Identifier:   IDENTIFIER,
        Number:           NUMBER,
        String:           STRING,
        Comment:         COMMENT,
        Punctuator:   PUNCTUATOR,
        CDO:                 CDO,
        CDC:                 CDC,
        Atrule:           ATRULE,
        Function:       FUNCTION,
        Url:                 URL,
        Raw:                 RAW,

        ExclamationMark:      33,  // !
        QuotationMark:        34,  // "
        NumberSign:           35,  // #
        DollarSign:           36,  // $
        PercentSign:          37,  // %
        Ampersand:            38,  // &
        Apostrophe:           39,  // '
        LeftParenthesis:      40,  // (
        RightParenthesis:     41,  // )
        Asterisk:             42,  // *
        PlusSign:             43,  // +
        Comma:                44,  // ,
        HyphenMinus:          45,  // -
        FullStop:             46,  // .
        Solidus:              47,  // /
        Colon:                58,  // :
        Semicolon:            59,  // ;
        LessThanSign:         60,  // <
        EqualsSign:           61,  // =
        GreaterThanSign:      62,  // >
        QuestionMark:         63,  // ?
        CommercialAt:         64,  // @
        LeftSquareBracket:    91,  // [
        Backslash:            92,  // \
        RightSquareBracket:   93,  // ]
        CircumflexAccent:     94,  // ^
        LowLine:              95,  // _
        GraveAccent:          96,  // `
        LeftCurlyBracket:    123,  // {
        VerticalLine:        124,  // |
        RightCurlyBracket:   125,  // }
        Tilde:               126   // ~
    };

    var NAME = Object.keys(TYPE).reduce(function(result, key) {
        result[TYPE[key]] = key;
        return result;
    }, {});

    // https://drafts.csswg.org/css-syntax/#tokenizer-definitions
    // > non-ASCII code point
    // >   A code point with a value equal to or greater than U+0080 <control>
    // > name-start code point
    // >   A letter, a non-ASCII code point, or U+005F LOW LINE (_).
    // > name code point
    // >   A name-start code point, a digit, or U+002D HYPHEN-MINUS (-)
    // That means only ASCII code points has a special meaning and we a maps for 0..127 codes only
    var SafeUint32Array = typeof Uint32Array !== 'undefined' ? Uint32Array : Array; // fallback on Array when TypedArray is not supported
    var SYMBOL_TYPE = new SafeUint32Array(0x80);
    var PUNCTUATION = new SafeUint32Array(0x80);
    var STOP_URL_RAW = new SafeUint32Array(0x80);

    for (var i = 0; i < SYMBOL_TYPE.length; i++) {
        SYMBOL_TYPE[i] = IDENTIFIER;
    }

    // fill categories
    [
        TYPE.ExclamationMark,    // !
        TYPE.QuotationMark,      // "
        TYPE.NumberSign,         // #
        TYPE.DollarSign,         // $
        TYPE.PercentSign,        // %
        TYPE.Ampersand,          // &
        TYPE.Apostrophe,         // '
        TYPE.LeftParenthesis,    // (
        TYPE.RightParenthesis,   // )
        TYPE.Asterisk,           // *
        TYPE.PlusSign,           // +
        TYPE.Comma,              // ,
        TYPE.HyphenMinus,        // -
        TYPE.FullStop,           // .
        TYPE.Solidus,            // /
        TYPE.Colon,              // :
        TYPE.Semicolon,          // ;
        TYPE.LessThanSign,       // <
        TYPE.EqualsSign,         // =
        TYPE.GreaterThanSign,    // >
        TYPE.QuestionMark,       // ?
        TYPE.CommercialAt,       // @
        TYPE.LeftSquareBracket,  // [
        // TYPE.Backslash,          // \
        TYPE.RightSquareBracket, // ]
        TYPE.CircumflexAccent,   // ^
        // TYPE.LowLine,            // _
        TYPE.GraveAccent,        // `
        TYPE.LeftCurlyBracket,   // {
        TYPE.VerticalLine,       // |
        TYPE.RightCurlyBracket,  // }
        TYPE.Tilde               // ~
    ].forEach(function(key) {
        SYMBOL_TYPE[Number(key)] = PUNCTUATOR;
        PUNCTUATION[Number(key)] = PUNCTUATOR;
    });

    for (var i = 48; i <= 57; i++) {
        SYMBOL_TYPE[i] = NUMBER;
    }

    SYMBOL_TYPE[SPACE] = WHITESPACE;
    SYMBOL_TYPE[TAB] = WHITESPACE;
    SYMBOL_TYPE[N] = WHITESPACE;
    SYMBOL_TYPE[R] = WHITESPACE;
    SYMBOL_TYPE[F] = WHITESPACE;

    SYMBOL_TYPE[TYPE.Apostrophe] = STRING;
    SYMBOL_TYPE[TYPE.QuotationMark] = STRING;

    STOP_URL_RAW[SPACE] = 1;
    STOP_URL_RAW[TAB] = 1;
    STOP_URL_RAW[N] = 1;
    STOP_URL_RAW[R] = 1;
    STOP_URL_RAW[F] = 1;
    STOP_URL_RAW[TYPE.Apostrophe] = 1;
    STOP_URL_RAW[TYPE.QuotationMark] = 1;
    STOP_URL_RAW[TYPE.LeftParenthesis] = 1;
    STOP_URL_RAW[TYPE.RightParenthesis] = 1;

    // whitespace is punctuation ...
    PUNCTUATION[SPACE] = PUNCTUATOR;
    PUNCTUATION[TAB] = PUNCTUATOR;
    PUNCTUATION[N] = PUNCTUATOR;
    PUNCTUATION[R] = PUNCTUATOR;
    PUNCTUATION[F] = PUNCTUATOR;
    // ... hyper minus is not
    PUNCTUATION[TYPE.HyphenMinus] = 0;

    var _const = {
        TYPE: TYPE,
        NAME: NAME,

        SYMBOL_TYPE: SYMBOL_TYPE,
        PUNCTUATION: PUNCTUATION,
        STOP_URL_RAW: STOP_URL_RAW
    };
    var _const_1 = _const.TYPE;
    var _const_2 = _const.NAME;
    var _const_3 = _const.SYMBOL_TYPE;
    var _const_4 = _const.PUNCTUATION;
    var _const_5 = _const.STOP_URL_RAW;

    var _const$1 = /*#__PURE__*/Object.freeze({
        default: _const,
        __moduleExports: _const,
        TYPE: _const_1,
        NAME: _const_2,
        SYMBOL_TYPE: _const_3,
        PUNCTUATION: _const_4,
        STOP_URL_RAW: _const_5
    });

    var constants = ( _const$1 && _const ) || _const$1;

    var PUNCTUATION$1 = constants.PUNCTUATION;
    var STOP_URL_RAW$1 = constants.STOP_URL_RAW;
    var TYPE$1 = constants.TYPE;
    var FULLSTOP = TYPE$1.FullStop;
    var PLUSSIGN = TYPE$1.PlusSign;
    var HYPHENMINUS = TYPE$1.HyphenMinus;
    var PUNCTUATOR$1 = TYPE$1.Punctuator;
    var TAB$1 = 9;
    var N$1 = 10;
    var F$1 = 12;
    var R$1 = 13;
    var SPACE$1 = 32;
    var BACK_SLASH = 92;
    var E = 101; // 'e'.charCodeAt(0)

    function firstCharOffset(source) {
        // detect BOM (https://en.wikipedia.org/wiki/Byte_order_mark)
        if (source.charCodeAt(0) === 0xFEFF ||  // UTF-16BE
            source.charCodeAt(0) === 0xFFFE) {  // UTF-16LE
            return 1;
        }

        return 0;
    }

    function isHex(code) {
        return (code >= 48 && code <= 57) || // 0 .. 9
               (code >= 65 && code <= 70) || // A .. F
               (code >= 97 && code <= 102);  // a .. f
    }

    function isNumber(code) {
        return code >= 48 && code <= 57;
    }

    function isNewline(source, offset, code) {
        if (code === N$1 || code === F$1 || code === R$1) {
            if (code === R$1 && offset + 1 < source.length && source.charCodeAt(offset + 1) === N$1) {
                return 2;
            }

            return 1;
        }

        return 0;
    }

    function cmpChar(testStr, offset, referenceCode) {
        var code = testStr.charCodeAt(offset);

        // code.toLowerCase()
        if (code >= 65 && code <= 90) {
            code = code | 32;
        }

        return code === referenceCode;
    }

    function cmpStr(testStr, start, end, referenceStr) {
        if (end - start !== referenceStr.length) {
            return false;
        }

        if (start < 0 || end > testStr.length) {
            return false;
        }

        for (var i = start; i < end; i++) {
            var testCode = testStr.charCodeAt(i);
            var refCode = referenceStr.charCodeAt(i - start);

            // testStr[i].toLowerCase()
            if (testCode >= 65 && testCode <= 90) {
                testCode = testCode | 32;
            }

            if (testCode !== refCode) {
                return false;
            }
        }

        return true;
    }

    function endsWith(testStr, referenceStr) {
        return cmpStr(testStr, testStr.length - referenceStr.length, testStr.length, referenceStr);
    }

    function findLastNonSpaceLocation(scanner) {
        for (var i = scanner.source.length - 1; i >= 0; i--) {
            var code = scanner.source.charCodeAt(i);

            if (code !== SPACE$1 && code !== TAB$1 && code !== R$1 && code !== N$1 && code !== F$1) {
                break;
            }
        }

        return scanner.getLocation(i + 1);
    }

    function findWhiteSpaceEnd(source, offset) {
        for (; offset < source.length; offset++) {
            var code = source.charCodeAt(offset);

            if (code !== SPACE$1 && code !== TAB$1 && code !== R$1 && code !== N$1 && code !== F$1) {
                break;
            }
        }

        return offset;
    }

    function findCommentEnd(source, offset) {
        var commentEnd = source.indexOf('*/', offset);

        if (commentEnd === -1) {
            return source.length;
        }

        return commentEnd + 2;
    }

    function findStringEnd(source, offset, quote) {
        for (; offset < source.length; offset++) {
            var code = source.charCodeAt(offset);

            // TODO: bad string
            if (code === BACK_SLASH) {
                offset++;
            } else if (code === quote) {
                offset++;
                break;
            }
        }

        return offset;
    }

    function findDecimalNumberEnd(source, offset) {
        for (; offset < source.length; offset++) {
            var code = source.charCodeAt(offset);

            if (code < 48 || code > 57) {  // not a 0 .. 9
                break;
            }
        }

        return offset;
    }

    function findNumberEnd(source, offset, allowFraction) {
        var code;

        offset = findDecimalNumberEnd(source, offset);

        // fraction: .\d+
        if (allowFraction && offset + 1 < source.length && source.charCodeAt(offset) === FULLSTOP) {
            code = source.charCodeAt(offset + 1);

            if (isNumber(code)) {
                offset = findDecimalNumberEnd(source, offset + 1);
            }
        }

        // exponent: e[+-]\d+
        if (offset + 1 < source.length) {
            if ((source.charCodeAt(offset) | 32) === E) { // case insensitive check for `e`
                code = source.charCodeAt(offset + 1);

                if (code === PLUSSIGN || code === HYPHENMINUS) {
                    if (offset + 2 < source.length) {
                        code = source.charCodeAt(offset + 2);
                    }
                }

                if (isNumber(code)) {
                    offset = findDecimalNumberEnd(source, offset + 2);
                }
            }
        }

        return offset;
    }

    // skip escaped unicode sequence that can ends with space
    // [0-9a-f]{1,6}(\r\n|[ \n\r\t\f])?
    function findEscaseEnd(source, offset) {
        for (var i = 0; i < 7 && offset + i < source.length; i++) {
            var code = source.charCodeAt(offset + i);

            if (i !== 6 && isHex(code)) {
                continue;
            }

            if (i > 0) {
                offset += i - 1 + isNewline(source, offset + i, code);
                if (code === SPACE$1 || code === TAB$1) {
                    offset++;
                }
            }

            break;
        }

        return offset;
    }

    function findIdentifierEnd(source, offset) {
        for (; offset < source.length; offset++) {
            var code = source.charCodeAt(offset);

            if (code === BACK_SLASH) {
                offset = findEscaseEnd(source, offset + 1);
            } else if (code < 0x80 && PUNCTUATION$1[code] === PUNCTUATOR$1) {
                break;
            }
        }

        return offset;
    }

    function findUrlRawEnd(source, offset) {
        for (; offset < source.length; offset++) {
            var code = source.charCodeAt(offset);

            if (code === BACK_SLASH) {
                offset = findEscaseEnd(source, offset + 1);
            } else if (code < 0x80 && STOP_URL_RAW$1[code] === 1) {
                break;
            }
        }

        return offset;
    }

    var utils = {
        firstCharOffset: firstCharOffset,

        isHex: isHex,
        isNumber: isNumber,
        isNewline: isNewline,

        cmpChar: cmpChar,
        cmpStr: cmpStr,
        endsWith: endsWith,

        findLastNonSpaceLocation: findLastNonSpaceLocation,
        findWhiteSpaceEnd: findWhiteSpaceEnd,
        findCommentEnd: findCommentEnd,
        findStringEnd: findStringEnd,
        findDecimalNumberEnd: findDecimalNumberEnd,
        findNumberEnd: findNumberEnd,
        findEscaseEnd: findEscaseEnd,
        findIdentifierEnd: findIdentifierEnd,
        findUrlRawEnd: findUrlRawEnd
    };
    var utils_1 = utils.firstCharOffset;
    var utils_2 = utils.isHex;
    var utils_3 = utils.isNumber;
    var utils_4 = utils.isNewline;
    var utils_5 = utils.cmpChar;
    var utils_6 = utils.cmpStr;
    var utils_7 = utils.endsWith;
    var utils_8 = utils.findLastNonSpaceLocation;
    var utils_9 = utils.findWhiteSpaceEnd;
    var utils_10 = utils.findCommentEnd;
    var utils_11 = utils.findStringEnd;
    var utils_12 = utils.findDecimalNumberEnd;
    var utils_13 = utils.findNumberEnd;
    var utils_14 = utils.findEscaseEnd;
    var utils_15 = utils.findIdentifierEnd;
    var utils_16 = utils.findUrlRawEnd;

    var utils$1 = /*#__PURE__*/Object.freeze({
        default: utils,
        __moduleExports: utils,
        firstCharOffset: utils_1,
        isHex: utils_2,
        isNumber: utils_3,
        isNewline: utils_4,
        cmpChar: utils_5,
        cmpStr: utils_6,
        endsWith: utils_7,
        findLastNonSpaceLocation: utils_8,
        findWhiteSpaceEnd: utils_9,
        findCommentEnd: utils_10,
        findStringEnd: utils_11,
        findDecimalNumberEnd: utils_12,
        findNumberEnd: utils_13,
        findEscaseEnd: utils_14,
        findIdentifierEnd: utils_15,
        findUrlRawEnd: utils_16
    });

    var CssSyntaxError$1 = ( error$1 && error ) || error$1;

    var utils$2 = ( utils$1 && utils ) || utils$1;

    var TYPE$2 = constants.TYPE;
    var NAME$1 = constants.NAME;
    var SYMBOL_TYPE$1 = constants.SYMBOL_TYPE;


    var firstCharOffset$1 = utils$2.firstCharOffset;
    var cmpStr$1 = utils$2.cmpStr;
    var isNumber$1 = utils$2.isNumber;
    var findLastNonSpaceLocation$1 = utils$2.findLastNonSpaceLocation;
    var findWhiteSpaceEnd$1 = utils$2.findWhiteSpaceEnd;
    var findCommentEnd$1 = utils$2.findCommentEnd;
    var findStringEnd$1 = utils$2.findStringEnd;
    var findNumberEnd$1 = utils$2.findNumberEnd;
    var findIdentifierEnd$1 = utils$2.findIdentifierEnd;
    var findUrlRawEnd$1 = utils$2.findUrlRawEnd;

    var NULL = 0;
    var WHITESPACE$1 = TYPE$2.WhiteSpace;
    var IDENTIFIER$1 = TYPE$2.Identifier;
    var NUMBER$1 = TYPE$2.Number;
    var STRING$1 = TYPE$2.String;
    var COMMENT$1 = TYPE$2.Comment;
    var PUNCTUATOR$2 = TYPE$2.Punctuator;
    var CDO$1 = TYPE$2.CDO;
    var CDC$1 = TYPE$2.CDC;
    var ATRULE$1 = TYPE$2.Atrule;
    var FUNCTION$1 = TYPE$2.Function;
    var URL$1 = TYPE$2.Url;
    var RAW$1 = TYPE$2.Raw;

    var N$2 = 10;
    var F$2 = 12;
    var R$2 = 13;
    var STAR = TYPE$2.Asterisk;
    var SLASH = TYPE$2.Solidus;
    var FULLSTOP$1 = TYPE$2.FullStop;
    var PLUSSIGN$1 = TYPE$2.PlusSign;
    var HYPHENMINUS$1 = TYPE$2.HyphenMinus;
    var GREATERTHANSIGN = TYPE$2.GreaterThanSign;
    var LESSTHANSIGN = TYPE$2.LessThanSign;
    var EXCLAMATIONMARK = TYPE$2.ExclamationMark;
    var COMMERCIALAT = TYPE$2.CommercialAt;
    var QUOTATIONMARK = TYPE$2.QuotationMark;
    var APOSTROPHE = TYPE$2.Apostrophe;
    var LEFTPARENTHESIS = TYPE$2.LeftParenthesis;
    var RIGHTPARENTHESIS = TYPE$2.RightParenthesis;
    var LEFTCURLYBRACKET = TYPE$2.LeftCurlyBracket;
    var RIGHTCURLYBRACKET = TYPE$2.RightCurlyBracket;
    var LEFTSQUAREBRACKET = TYPE$2.LeftSquareBracket;
    var RIGHTSQUAREBRACKET = TYPE$2.RightSquareBracket;

    var MIN_BUFFER_SIZE = 16 * 1024;
    var OFFSET_MASK = 0x00FFFFFF;
    var TYPE_SHIFT = 24;
    var SafeUint32Array$1 = typeof Uint32Array !== 'undefined' ? Uint32Array : Array; // fallback on Array when TypedArray is not supported

    function computeLinesAndColumns(tokenizer, source) {
        var sourceLength = source.length;
        var start = firstCharOffset$1(source);
        var lines = tokenizer.lines;
        var line = tokenizer.startLine;
        var columns = tokenizer.columns;
        var column = tokenizer.startColumn;

        if (lines === null || lines.length < sourceLength + 1) {
            lines = new SafeUint32Array$1(Math.max(sourceLength + 1024, MIN_BUFFER_SIZE));
            columns = new SafeUint32Array$1(lines.length);
        }

        for (var i = start; i < sourceLength; i++) {
            var code = source.charCodeAt(i);

            lines[i] = line;
            columns[i] = column++;

            if (code === N$2 || code === R$2 || code === F$2) {
                if (code === R$2 && i + 1 < sourceLength && source.charCodeAt(i + 1) === N$2) {
                    i++;
                    lines[i] = line;
                    columns[i] = column;
                }

                line++;
                column = 1;
            }
        }

        lines[i] = line;
        columns[i] = column;

        tokenizer.linesAnsColumnsComputed = true;
        tokenizer.lines = lines;
        tokenizer.columns = columns;
    }

    function tokenLayout(tokenizer, source, startPos) {
        var sourceLength = source.length;
        var offsetAndType = tokenizer.offsetAndType;
        var balance = tokenizer.balance;
        var tokenCount = 0;
        var prevType = 0;
        var offset = startPos;
        var anchor = 0;
        var balanceCloseCode = 0;
        var balanceStart = 0;
        var balancePrev = 0;

        if (offsetAndType === null || offsetAndType.length < sourceLength + 1) {
            offsetAndType = new SafeUint32Array$1(sourceLength + 1024);
            balance = new SafeUint32Array$1(sourceLength + 1024);
        }

        while (offset < sourceLength) {
            var code = source.charCodeAt(offset);
            var type = code < 0x80 ? SYMBOL_TYPE$1[code] : IDENTIFIER$1;

            balance[tokenCount] = sourceLength;

            switch (type) {
                case WHITESPACE$1:
                    offset = findWhiteSpaceEnd$1(source, offset + 1);
                    break;

                case PUNCTUATOR$2:
                    switch (code) {
                        case balanceCloseCode:
                            balancePrev = balanceStart & OFFSET_MASK;
                            balanceStart = balance[balancePrev];
                            balanceCloseCode = balanceStart >> TYPE_SHIFT;
                            balance[tokenCount] = balancePrev;
                            balance[balancePrev++] = tokenCount;
                            for (; balancePrev < tokenCount; balancePrev++) {
                                if (balance[balancePrev] === sourceLength) {
                                    balance[balancePrev] = tokenCount;
                                }
                            }
                            break;

                        case LEFTSQUAREBRACKET:
                            balance[tokenCount] = balanceStart;
                            balanceCloseCode = RIGHTSQUAREBRACKET;
                            balanceStart = (balanceCloseCode << TYPE_SHIFT) | tokenCount;
                            break;

                        case LEFTCURLYBRACKET:
                            balance[tokenCount] = balanceStart;
                            balanceCloseCode = RIGHTCURLYBRACKET;
                            balanceStart = (balanceCloseCode << TYPE_SHIFT) | tokenCount;
                            break;

                        case LEFTPARENTHESIS:
                            balance[tokenCount] = balanceStart;
                            balanceCloseCode = RIGHTPARENTHESIS;
                            balanceStart = (balanceCloseCode << TYPE_SHIFT) | tokenCount;
                            break;
                    }

                    // /*
                    if (code === STAR && prevType === SLASH) {
                        type = COMMENT$1;
                        offset = findCommentEnd$1(source, offset + 1);
                        tokenCount--; // rewrite prev token
                        break;
                    }

                    // edge case for -.123 and +.123
                    if (code === FULLSTOP$1 && (prevType === PLUSSIGN$1 || prevType === HYPHENMINUS$1)) {
                        if (offset + 1 < sourceLength && isNumber$1(source.charCodeAt(offset + 1))) {
                            type = NUMBER$1;
                            offset = findNumberEnd$1(source, offset + 2, false);
                            tokenCount--; // rewrite prev token
                            break;
                        }
                    }

                    // <!--
                    if (code === EXCLAMATIONMARK && prevType === LESSTHANSIGN) {
                        if (offset + 2 < sourceLength &&
                            source.charCodeAt(offset + 1) === HYPHENMINUS$1 &&
                            source.charCodeAt(offset + 2) === HYPHENMINUS$1) {
                            type = CDO$1;
                            offset = offset + 3;
                            tokenCount--; // rewrite prev token
                            break;
                        }
                    }

                    // -->
                    if (code === HYPHENMINUS$1 && prevType === HYPHENMINUS$1) {
                        if (offset + 1 < sourceLength && source.charCodeAt(offset + 1) === GREATERTHANSIGN) {
                            type = CDC$1;
                            offset = offset + 2;
                            tokenCount--; // rewrite prev token
                            break;
                        }
                    }

                    // ident(
                    if (code === LEFTPARENTHESIS && prevType === IDENTIFIER$1) {
                        offset = offset + 1;
                        tokenCount--; // rewrite prev token
                        balance[tokenCount] = balance[tokenCount + 1];
                        balanceStart--;

                        // 4 char length identifier and equal to `url(` (case insensitive)
                        if (offset - anchor === 4 && cmpStr$1(source, anchor, offset, 'url(')) {
                            // special case for url() because it can contain any symbols sequence with few exceptions
                            anchor = findWhiteSpaceEnd$1(source, offset);
                            code = source.charCodeAt(anchor);
                            if (code !== LEFTPARENTHESIS &&
                                code !== RIGHTPARENTHESIS &&
                                code !== QUOTATIONMARK &&
                                code !== APOSTROPHE) {
                                // url(
                                offsetAndType[tokenCount++] = (URL$1 << TYPE_SHIFT) | offset;
                                balance[tokenCount] = sourceLength;

                                // ws*
                                if (anchor !== offset) {
                                    offsetAndType[tokenCount++] = (WHITESPACE$1 << TYPE_SHIFT) | anchor;
                                    balance[tokenCount] = sourceLength;
                                }

                                // raw
                                type = RAW$1;
                                offset = findUrlRawEnd$1(source, anchor);
                            } else {
                                type = URL$1;
                            }
                        } else {
                            type = FUNCTION$1;
                        }
                        break;
                    }

                    type = code;
                    offset = offset + 1;
                    break;

                case NUMBER$1:
                    offset = findNumberEnd$1(source, offset + 1, prevType !== FULLSTOP$1);

                    // merge number with a preceding dot, dash or plus
                    if (prevType === FULLSTOP$1 ||
                        prevType === HYPHENMINUS$1 ||
                        prevType === PLUSSIGN$1) {
                        tokenCount--; // rewrite prev token
                    }

                    break;

                case STRING$1:
                    offset = findStringEnd$1(source, offset + 1, code);
                    break;

                default:
                    anchor = offset;
                    offset = findIdentifierEnd$1(source, offset);

                    // merge identifier with a preceding dash
                    if (prevType === HYPHENMINUS$1) {
                        // rewrite prev token
                        tokenCount--;
                        // restore prev prev token type
                        // for case @-prefix-ident
                        prevType = tokenCount === 0 ? 0 : offsetAndType[tokenCount - 1] >> TYPE_SHIFT;
                    }

                    if (prevType === COMMERCIALAT) {
                        // rewrite prev token and change type to <at-keyword-token>
                        tokenCount--;
                        type = ATRULE$1;
                    }
            }

            offsetAndType[tokenCount++] = (type << TYPE_SHIFT) | offset;
            prevType = type;
        }

        // finalize arrays
        offsetAndType[tokenCount] = offset;
        balance[tokenCount] = sourceLength;
        while (balanceStart !== 0) {
            balancePrev = balanceStart & OFFSET_MASK;
            balanceStart = balance[balancePrev];
            balance[balancePrev] = sourceLength;
        }

        tokenizer.offsetAndType = offsetAndType;
        tokenizer.tokenCount = tokenCount;
        tokenizer.balance = balance;
    }

    //
    // tokenizer
    //

    var Tokenizer = function(source, startOffset, startLine, startColumn) {
        this.offsetAndType = null;
        this.balance = null;
        this.lines = null;
        this.columns = null;

        this.setSource(source, startOffset, startLine, startColumn);
    };

    Tokenizer.prototype = {
        setSource: function(source, startOffset, startLine, startColumn) {
            var safeSource = String(source || '');
            var start = firstCharOffset$1(safeSource);

            this.source = safeSource;
            this.firstCharOffset = start;
            this.startOffset = typeof startOffset === 'undefined' ? 0 : startOffset;
            this.startLine = typeof startLine === 'undefined' ? 1 : startLine;
            this.startColumn = typeof startColumn === 'undefined' ? 1 : startColumn;
            this.linesAnsColumnsComputed = false;

            this.eof = false;
            this.currentToken = -1;
            this.tokenType = 0;
            this.tokenStart = start;
            this.tokenEnd = start;

            tokenLayout(this, safeSource, start);
            this.next();
        },

        lookupType: function(offset) {
            offset += this.currentToken;

            if (offset < this.tokenCount) {
                return this.offsetAndType[offset] >> TYPE_SHIFT;
            }

            return NULL;
        },
        lookupNonWSType: function(offset) {
            offset += this.currentToken;

            for (var type; offset < this.tokenCount; offset++) {
                type = this.offsetAndType[offset] >> TYPE_SHIFT;

                if (type !== WHITESPACE$1) {
                    return type;
                }
            }

            return NULL;
        },
        lookupValue: function(offset, referenceStr) {
            offset += this.currentToken;

            if (offset < this.tokenCount) {
                return cmpStr$1(
                    this.source,
                    this.offsetAndType[offset - 1] & OFFSET_MASK,
                    this.offsetAndType[offset] & OFFSET_MASK,
                    referenceStr
                );
            }

            return false;
        },
        getTokenStart: function(tokenNum) {
            if (tokenNum === this.currentToken) {
                return this.tokenStart;
            }

            if (tokenNum > 0) {
                return tokenNum < this.tokenCount
                    ? this.offsetAndType[tokenNum - 1] & OFFSET_MASK
                    : this.offsetAndType[this.tokenCount] & OFFSET_MASK;
            }

            return this.firstCharOffset;
        },
        getOffsetExcludeWS: function() {
            if (this.currentToken > 0) {
                if ((this.offsetAndType[this.currentToken - 1] >> TYPE_SHIFT) === WHITESPACE$1) {
                    return this.currentToken > 1
                        ? this.offsetAndType[this.currentToken - 2] & OFFSET_MASK
                        : this.firstCharOffset;
                }
            }
            return this.tokenStart;
        },
        getRawLength: function(startToken, endTokenType1, endTokenType2, includeTokenType2) {
            var cursor = startToken;
            var balanceEnd;

            loop:
            for (; cursor < this.tokenCount; cursor++) {
                balanceEnd = this.balance[cursor];

                // belance end points to offset before start
                if (balanceEnd < startToken) {
                    break loop;
                }

                // check token is stop type
                switch (this.offsetAndType[cursor] >> TYPE_SHIFT) {
                    case endTokenType1:
                        break loop;

                    case endTokenType2:
                        if (includeTokenType2) {
                            cursor++;
                        }
                        break loop;

                    default:
                        // fast forward to the end of balanced block
                        if (this.balance[balanceEnd] === cursor) {
                            cursor = balanceEnd;
                        }
                }

            }

            return cursor - this.currentToken;
        },

        getTokenValue: function() {
            return this.source.substring(this.tokenStart, this.tokenEnd);
        },
        substrToCursor: function(start) {
            return this.source.substring(start, this.tokenStart);
        },

        skipWS: function() {
            for (var i = this.currentToken, skipTokenCount = 0; i < this.tokenCount; i++, skipTokenCount++) {
                if ((this.offsetAndType[i] >> TYPE_SHIFT) !== WHITESPACE$1) {
                    break;
                }
            }

            if (skipTokenCount > 0) {
                this.skip(skipTokenCount);
            }
        },
        skipSC: function() {
            while (this.tokenType === WHITESPACE$1 || this.tokenType === COMMENT$1) {
                this.next();
            }
        },
        skip: function(tokenCount) {
            var next = this.currentToken + tokenCount;

            if (next < this.tokenCount) {
                this.currentToken = next;
                this.tokenStart = this.offsetAndType[next - 1] & OFFSET_MASK;
                next = this.offsetAndType[next];
                this.tokenType = next >> TYPE_SHIFT;
                this.tokenEnd = next & OFFSET_MASK;
            } else {
                this.currentToken = this.tokenCount;
                this.next();
            }
        },
        next: function() {
            var next = this.currentToken + 1;

            if (next < this.tokenCount) {
                this.currentToken = next;
                this.tokenStart = this.tokenEnd;
                next = this.offsetAndType[next];
                this.tokenType = next >> TYPE_SHIFT;
                this.tokenEnd = next & OFFSET_MASK;
            } else {
                this.currentToken = this.tokenCount;
                this.eof = true;
                this.tokenType = NULL;
                this.tokenStart = this.tokenEnd = this.source.length;
            }
        },

        eat: function(tokenType) {
            if (this.tokenType !== tokenType) {
                var offset = this.tokenStart;
                var message = NAME$1[tokenType] + ' is expected';

                // tweak message and offset
                if (tokenType === IDENTIFIER$1) {
                    // when identifier is expected but there is a function or url
                    if (this.tokenType === FUNCTION$1 || this.tokenType === URL$1) {
                        offset = this.tokenEnd - 1;
                        message += ' but function found';
                    }
                } else {
                    // when test type is part of another token show error for current position + 1
                    // e.g. eat(HYPHENMINUS) will fail on "-foo", but pointing on "-" is odd
                    if (this.source.charCodeAt(this.tokenStart) === tokenType) {
                        offset = offset + 1;
                    }
                }

                this.error(message, offset);
            }

            this.next();
        },
        eatNonWS: function(tokenType) {
            this.skipWS();
            this.eat(tokenType);
        },

        consume: function(tokenType) {
            var value = this.getTokenValue();

            this.eat(tokenType);

            return value;
        },
        consumeFunctionName: function() {
            var name = this.source.substring(this.tokenStart, this.tokenEnd - 1);

            this.eat(FUNCTION$1);

            return name;
        },
        consumeNonWS: function(tokenType) {
            this.skipWS();

            return this.consume(tokenType);
        },

        expectIdentifier: function(name) {
            if (this.tokenType !== IDENTIFIER$1 || cmpStr$1(this.source, this.tokenStart, this.tokenEnd, name) === false) {
                this.error('Identifier `' + name + '` is expected');
            }

            this.next();
        },

        getLocation: function(offset, filename) {
            if (!this.linesAnsColumnsComputed) {
                computeLinesAndColumns(this, this.source);
            }

            return {
                source: filename,
                offset: this.startOffset + offset,
                line: this.lines[offset],
                column: this.columns[offset]
            };
        },

        getLocationRange: function(start, end, filename) {
            if (!this.linesAnsColumnsComputed) {
                computeLinesAndColumns(this, this.source);
            }

            return {
                source: filename,
                start: {
                    offset: this.startOffset + start,
                    line: this.lines[start],
                    column: this.columns[start]
                },
                end: {
                    offset: this.startOffset + end,
                    line: this.lines[end],
                    column: this.columns[end]
                }
            };
        },

        error: function(message, offset) {
            var location = typeof offset !== 'undefined' && offset < this.source.length
                ? this.getLocation(offset)
                : this.eof
                    ? findLastNonSpaceLocation$1(this)
                    : this.getLocation(this.tokenStart);

            throw new CssSyntaxError$1(
                message || 'Unexpected input',
                this.source,
                location.offset,
                location.line,
                location.column
            );
        },

        dump: function() {
            var offset = 0;

            return Array.prototype.slice.call(this.offsetAndType, 0, this.tokenCount).map(function(item, idx) {
                var start = offset;
                var end = item & OFFSET_MASK;

                offset = end;

                return {
                    idx: idx,
                    type: NAME$1[item >> TYPE_SHIFT],
                    chunk: this.source.substring(start, end),
                    balance: this.balance[idx]
                };
            }, this);
        }
    };

    // extend with error class
    Tokenizer.CssSyntaxError = CssSyntaxError$1;

    // extend tokenizer with constants
    Object.keys(constants).forEach(function(key) {
        Tokenizer[key] = constants[key];
    });

    // extend tokenizer with static methods from utils
    Object.keys(utils$2).forEach(function(key) {
        Tokenizer[key] = utils$2[key];
    });

    // warm up tokenizer to elimitate code branches that never execute
    // fix soft deoptimizations (insufficient type feedback)
    new Tokenizer('\n\r\r\n\f<!---->//""\'\'/*\r\n\f*/1a;.\\31\t\+2{url(a);func();+1.2e3 -.4e-5 .6e+7}').getLocation();

    var Tokenizer_1 = Tokenizer;

    var Tokenizer$1 = /*#__PURE__*/Object.freeze({
        default: Tokenizer_1,
        __moduleExports: Tokenizer_1
    });

    var require$$0 = ( Tokenizer$1 && Tokenizer_1 ) || Tokenizer$1;

    var tokenizer$1 = require$$0;

    var tokenizer$2 = /*#__PURE__*/Object.freeze({
        default: tokenizer$1,
        __moduleExports: tokenizer$1
    });

    //
    //            item        item        item        item
    //          /------\    /------\    /------\    /------\
    //          | data |    | data |    | data |    | data |
    //  null <--+-prev |<---+-prev |<---+-prev |<---+-prev |
    //          | next-+--->| next-+--->| next-+--->| next-+--> null
    //          \------/    \------/    \------/    \------/
    //             ^                                    ^
    //             |                list                |
    //             |              /------\              |
    //             \--------------+-head |              |
    //                            | tail-+--------------/
    //                            \------/
    //

    function createItem(data) {
        return {
            prev: null,
            next: null,
            data: data
        };
    }

    var cursors = null;
    var List = function() {
        this.cursor = null;
        this.head = null;
        this.tail = null;
    };

    List.createItem = createItem;
    List.prototype.createItem = createItem;

    List.prototype.getSize = function() {
        var size = 0;
        var cursor = this.head;

        while (cursor) {
            size++;
            cursor = cursor.next;
        }

        return size;
    };

    List.prototype.fromArray = function(array) {
        var cursor = null;

        this.head = null;

        for (var i = 0; i < array.length; i++) {
            var item = createItem(array[i]);

            if (cursor !== null) {
                cursor.next = item;
            } else {
                this.head = item;
            }

            item.prev = cursor;
            cursor = item;
        }

        this.tail = cursor;

        return this;
    };

    List.prototype.toArray = function() {
        var cursor = this.head;
        var result = [];

        while (cursor) {
            result.push(cursor.data);
            cursor = cursor.next;
        }

        return result;
    };

    List.prototype.toJSON = List.prototype.toArray;

    List.prototype.isEmpty = function() {
        return this.head === null;
    };

    List.prototype.first = function() {
        return this.head && this.head.data;
    };

    List.prototype.last = function() {
        return this.tail && this.tail.data;
    };

    function allocateCursor(node, prev, next) {
        var cursor;

        if (cursors !== null) {
            cursor = cursors;
            cursors = cursors.cursor;
            cursor.prev = prev;
            cursor.next = next;
            cursor.cursor = node.cursor;
        } else {
            cursor = {
                prev: prev,
                next: next,
                cursor: node.cursor
            };
        }

        node.cursor = cursor;

        return cursor;
    }

    function releaseCursor(node) {
        var cursor = node.cursor;

        node.cursor = cursor.cursor;
        cursor.prev = null;
        cursor.next = null;
        cursor.cursor = cursors;
        cursors = cursor;
    }

    List.prototype.each = function(fn, context) {
        var item;

        if (context === undefined) {
            context = this;
        }

        // push cursor
        var cursor = allocateCursor(this, null, this.head);

        while (cursor.next !== null) {
            item = cursor.next;
            cursor.next = item.next;

            fn.call(context, item.data, item, this);
        }

        // pop cursor
        releaseCursor(this);
    };

    List.prototype.eachRight = function(fn, context) {
        var item;

        if (context === undefined) {
            context = this;
        }

        // push cursor
        var cursor = allocateCursor(this, this.tail, null);

        while (cursor.prev !== null) {
            item = cursor.prev;
            cursor.prev = item.prev;

            fn.call(context, item.data, item, this);
        }

        // pop cursor
        releaseCursor(this);
    };

    List.prototype.nextUntil = function(start, fn, context) {
        if (start === null) {
            return;
        }

        var item;

        if (context === undefined) {
            context = this;
        }

        // push cursor
        var cursor = allocateCursor(this, null, start);

        while (cursor.next !== null) {
            item = cursor.next;
            cursor.next = item.next;

            if (fn.call(context, item.data, item, this)) {
                break;
            }
        }

        // pop cursor
        releaseCursor(this);
    };

    List.prototype.prevUntil = function(start, fn, context) {
        if (start === null) {
            return;
        }

        var item;

        if (context === undefined) {
            context = this;
        }

        // push cursor
        var cursor = allocateCursor(this, start, null);

        while (cursor.prev !== null) {
            item = cursor.prev;
            cursor.prev = item.prev;

            if (fn.call(context, item.data, item, this)) {
                break;
            }
        }

        // pop cursor
        releaseCursor(this);
    };

    List.prototype.some = function(fn, context) {
        var cursor = this.head;

        if (context === undefined) {
            context = this;
        }

        while (cursor !== null) {
            if (fn.call(context, cursor.data, cursor, this)) {
                return true;
            }

            cursor = cursor.next;
        }

        return false;
    };

    List.prototype.map = function(fn, context) {
        var result = [];
        var cursor = this.head;

        if (context === undefined) {
            context = this;
        }

        while (cursor !== null) {
            result.push(fn.call(context, cursor.data, cursor, this));
            cursor = cursor.next;
        }

        return result;
    };

    List.prototype.clear = function() {
        this.head = null;
        this.tail = null;
    };

    List.prototype.copy = function() {
        var result = new List();
        var cursor = this.head;

        while (cursor !== null) {
            result.insert(createItem(cursor.data));
            cursor = cursor.next;
        }

        return result;
    };

    List.prototype.updateCursors = function(prevOld, prevNew, nextOld, nextNew) {
        var cursor = this.cursor;

        while (cursor !== null) {
            if (cursor.prev === prevOld) {
                cursor.prev = prevNew;
            }

            if (cursor.next === nextOld) {
                cursor.next = nextNew;
            }

            cursor = cursor.cursor;
        }
    };

    List.prototype.prepend = function(item) {
        //      head
        //    ^
        // item
        this.updateCursors(null, item, this.head, item);

        // insert to the beginning of the list
        if (this.head !== null) {
            // new item <- first item
            this.head.prev = item;

            // new item -> first item
            item.next = this.head;
        } else {
            // if list has no head, then it also has no tail
            // in this case tail points to the new item
            this.tail = item;
        }

        // head always points to new item
        this.head = item;

        return this;
    };

    List.prototype.prependData = function(data) {
        return this.prepend(createItem(data));
    };

    List.prototype.append = function(item) {
        // tail
        //      ^
        //      item
        this.updateCursors(this.tail, item, null, item);

        // insert to the ending of the list
        if (this.tail !== null) {
            // last item -> new item
            this.tail.next = item;

            // last item <- new item
            item.prev = this.tail;
        } else {
            // if list has no tail, then it also has no head
            // in this case head points to new item
            this.head = item;
        }

        // tail always points to new item
        this.tail = item;

        return this;
    };

    List.prototype.appendData = function(data) {
        return this.append(createItem(data));
    };

    List.prototype.insert = function(item, before) {
        if (before !== undefined && before !== null) {
            // prev   before
            //      ^
            //     item
            this.updateCursors(before.prev, item, before, item);

            if (before.prev === null) {
                // insert to the beginning of list
                if (this.head !== before) {
                    throw new Error('before doesn\'t belong to list');
                }

                // since head points to before therefore list doesn't empty
                // no need to check tail
                this.head = item;
                before.prev = item;
                item.next = before;

                this.updateCursors(null, item);
            } else {

                // insert between two items
                before.prev.next = item;
                item.prev = before.prev;

                before.prev = item;
                item.next = before;
            }
        } else {
            this.append(item);
        }
    };

    List.prototype.insertData = function(data, before) {
        this.insert(createItem(data), before);
    };

    List.prototype.remove = function(item) {
        //      item
        //       ^
        // prev     next
        this.updateCursors(item, item.prev, item, item.next);

        if (item.prev !== null) {
            item.prev.next = item.next;
        } else {
            if (this.head !== item) {
                throw new Error('item doesn\'t belong to list');
            }

            this.head = item.next;
        }

        if (item.next !== null) {
            item.next.prev = item.prev;
        } else {
            if (this.tail !== item) {
                throw new Error('item doesn\'t belong to list');
            }

            this.tail = item.prev;
        }

        item.prev = null;
        item.next = null;

        return item;
    };

    List.prototype.appendList = function(list) {
        // ignore empty lists
        if (list.head === null) {
            return;
        }

        this.updateCursors(this.tail, list.tail, null, list.head);

        // insert to end of the list
        if (this.tail !== null) {
            // if destination list has a tail, then it also has a head,
            // but head doesn't change

            // dest tail -> source head
            this.tail.next = list.head;

            // dest tail <- source head
            list.head.prev = this.tail;
        } else {
            // if list has no a tail, then it also has no a head
            // in this case points head to new item
            this.head = list.head;
        }

        // tail always start point to new item
        this.tail = list.tail;

        list.head = null;
        list.tail = null;
    };

    List.prototype.insertList = function(list, before) {
        if (before !== undefined && before !== null) {
            // ignore empty lists
            if (list.head === null) {
                return;
            }

            this.updateCursors(before.prev, list.tail, before, list.head);

            // insert in the middle of dist list
            if (before.prev !== null) {
                // before.prev <-> list.head
                before.prev.next = list.head;
                list.head.prev = before.prev;
            } else {
                this.head = list.head;
            }

            before.prev = list.tail;
            list.tail.next = before;

            list.head = null;
            list.tail = null;
        } else {
            this.appendList(list);
        }
    };

    List.prototype.replace = function(oldItem, newItemOrList) {
        if ('head' in newItemOrList) {
            this.insertList(newItemOrList, oldItem);
        } else {
            this.insert(newItemOrList, oldItem);
        }
        this.remove(oldItem);
    };

    var list = List;

    var list$1 = /*#__PURE__*/Object.freeze({
        default: list,
        __moduleExports: list
    });

    var List$1 = ( list$1 && list ) || list$1;

    var require$$0$1 = ( tokenizer$2 && tokenizer$1 ) || tokenizer$2;

    var TYPE$3 = require$$0$1.TYPE;
    var WHITESPACE$2 = TYPE$3.WhiteSpace;
    var COMMENT$2 = TYPE$3.Comment;

    var sequence = function readSequence(recognizer) {
        var children = new List$1();
        var child = null;
        var context = {
            recognizer: recognizer,
            space: null,
            ignoreWS: false,
            ignoreWSAfter: false
        };

        this.scanner.skipSC();

        while (!this.scanner.eof) {
            switch (this.scanner.tokenType) {
                case COMMENT$2:
                    this.scanner.next();
                    continue;

                case WHITESPACE$2:
                    if (context.ignoreWS) {
                        this.scanner.next();
                    } else {
                        context.space = this.WhiteSpace();
                    }
                    continue;
            }

            child = recognizer.getNode.call(this, context);

            if (child === undefined) {
                break;
            }

            if (context.space !== null) {
                children.appendData(context.space);
                context.space = null;
            }

            children.appendData(child);

            if (context.ignoreWSAfter) {
                context.ignoreWSAfter = false;
                context.ignoreWS = true;
            } else {
                context.ignoreWS = false;
            }
        }

        return children;
    };

    var sequence$1 = /*#__PURE__*/Object.freeze({
        default: sequence,
        __moduleExports: sequence
    });

    var sequence$2 = ( sequence$1 && sequence ) || sequence$1;

    var noop = function() {};

    function createParseContext(name) {
        return function() {
            return this[name]();
        };
    }

    function processConfig(config) {
        var parserConfig = {
            context: {},
            scope: {},
            atrule: {},
            pseudo: {}
        };

        if (config.parseContext) {
            for (var name in config.parseContext) {
                switch (typeof config.parseContext[name]) {
                    case 'function':
                        parserConfig.context[name] = config.parseContext[name];
                        break;

                    case 'string':
                        parserConfig.context[name] = createParseContext(config.parseContext[name]);
                        break;
                }
            }
        }

        if (config.scope) {
            for (var name in config.scope) {
                parserConfig.scope[name] = config.scope[name];
            }
        }

        if (config.atrule) {
            for (var name in config.atrule) {
                var atrule = config.atrule[name];

                if (atrule.parse) {
                    parserConfig.atrule[name] = atrule.parse;
                }
            }
        }

        if (config.pseudo) {
            for (var name in config.pseudo) {
                var pseudo = config.pseudo[name];

                if (pseudo.parse) {
                    parserConfig.pseudo[name] = pseudo.parse;
                }
            }
        }

        if (config.node) {
            for (var name in config.node) {
                parserConfig[name] = config.node[name].parse;
            }
        }

        return parserConfig;
    }

    var create = function createParser(config) {
        var parser = {
            scanner: new require$$0$1(),
            filename: '<unknown>',
            needPositions: false,
            tolerant: false,
            onParseError: noop,
            parseAtruleExpression: true,
            parseSelector: true,
            parseValue: true,
            parseCustomProperty: false,

            readSequence: sequence$2,

            tolerantParse: function(consumer, fallback) {
                if (this.tolerant) {
                    var start = this.scanner.currentToken;

                    try {
                        return consumer.call(this);
                    } catch (e) {
                        this.onParseError(e);
                        return fallback.call(this, start);
                    }
                } else {
                    return consumer.call(this);
                }
            },

            getLocation: function(start, end) {
                if (this.needPositions) {
                    return this.scanner.getLocationRange(
                        start,
                        end,
                        this.filename
                    );
                }

                return null;
            },
            getLocationFromList: function(list) {
                if (this.needPositions) {
                    return this.scanner.getLocationRange(
                        list.head !== null ? list.first().loc.start.offset - this.scanner.startOffset : this.scanner.tokenStart,
                        list.head !== null ? list.last().loc.end.offset - this.scanner.startOffset : this.scanner.tokenStart,
                        this.filename
                    );
                }

                return null;
            }
        };

        config = processConfig(config || {});
        for (var key in config) {
            parser[key] = config[key];
        }

        return function(source, options) {
            options = options || {};

            var context = options.context || 'default';
            var ast;

            parser.scanner.setSource(source, options.offset, options.line, options.column);
            parser.filename = options.filename || '<unknown>';
            parser.needPositions = Boolean(options.positions);
            parser.tolerant = Boolean(options.tolerant);
            parser.onParseError = typeof options.onParseError === 'function' ? options.onParseError : noop;
            parser.parseAtruleExpression = 'parseAtruleExpression' in options ? Boolean(options.parseAtruleExpression) : true;
            parser.parseSelector = 'parseSelector' in options ? Boolean(options.parseSelector) : true;
            parser.parseValue = 'parseValue' in options ? Boolean(options.parseValue) : true;
            parser.parseCustomProperty = 'parseCustomProperty' in options ? Boolean(options.parseCustomProperty) : false;

            if (!parser.context.hasOwnProperty(context)) {
                throw new Error('Unknown context `' + context + '`');
            }

            ast = parser.context[context].call(parser, options);

            if (!parser.scanner.eof) {
                parser.scanner.error();
            }

            // console.log(JSON.stringify(ast, null, 4));
            return ast;
        };
    };

    var create$1 = /*#__PURE__*/Object.freeze({
        default: create,
        __moduleExports: create
    });

    var cmpChar$1 = require$$0$1.cmpChar;
    var TYPE$4 = require$$0$1.TYPE;

    var IDENTIFIER$2 = TYPE$4.Identifier;
    var STRING$2 = TYPE$4.String;
    var NUMBER$2 = TYPE$4.Number;
    var FUNCTION$2 = TYPE$4.Function;
    var URL$2 = TYPE$4.Url;
    var NUMBERSIGN = TYPE$4.NumberSign;
    var LEFTPARENTHESIS$1 = TYPE$4.LeftParenthesis;
    var LEFTSQUAREBRACKET$1 = TYPE$4.LeftSquareBracket;
    var PLUSSIGN$2 = TYPE$4.PlusSign;
    var HYPHENMINUS$2 = TYPE$4.HyphenMinus;
    var COMMA = TYPE$4.Comma;
    var SOLIDUS = TYPE$4.Solidus;
    var ASTERISK = TYPE$4.Asterisk;
    var PERCENTSIGN = TYPE$4.PercentSign;
    var BACKSLASH = TYPE$4.Backslash;
    var U = 117; // 'u'.charCodeAt(0)

    var _default = function defaultRecognizer(context) {
        switch (this.scanner.tokenType) {
            case NUMBERSIGN:
                return this.HexColor();

            case COMMA:
                context.space = null;
                context.ignoreWSAfter = true;
                return this.Operator();

            case SOLIDUS:
            case ASTERISK:
            case PLUSSIGN$2:
            case HYPHENMINUS$2:
                return this.Operator();

            case LEFTPARENTHESIS$1:
                return this.Parentheses(this.readSequence, context.recognizer);

            case LEFTSQUAREBRACKET$1:
                return this.Brackets(this.readSequence, context.recognizer);

            case STRING$2:
                return this.String();

            case NUMBER$2:
                switch (this.scanner.lookupType(1)) {
                    case PERCENTSIGN:
                        return this.Percentage();

                    case IDENTIFIER$2:
                        // edge case: number with folowing \0 and \9 hack shouldn't to be a Dimension
                        if (cmpChar$1(this.scanner.source, this.scanner.tokenEnd, BACKSLASH)) {
                            return this.Number();
                        } else {
                            return this.Dimension();
                        }

                    default:
                        return this.Number();
                }

            case FUNCTION$2:
                return this.Function(this.readSequence, context.recognizer);

            case URL$2:
                return this.Url();

            case IDENTIFIER$2:
                // check for unicode range, it should start with u+ or U+
                if (cmpChar$1(this.scanner.source, this.scanner.tokenStart, U) &&
                    cmpChar$1(this.scanner.source, this.scanner.tokenStart + 1, PLUSSIGN$2)) {
                    return this.UnicodeRange();
                } else {
                    return this.Identifier();
                }
        }
    };

    var _default$1 = /*#__PURE__*/Object.freeze({
        default: _default,
        __moduleExports: _default
    });

    var require$$0$2 = ( _default$1 && _default ) || _default$1;

    var atruleExpression = {
        getNode: require$$0$2
    };
    var atruleExpression_1 = atruleExpression.getNode;

    var atruleExpression$1 = /*#__PURE__*/Object.freeze({
        default: atruleExpression,
        __moduleExports: atruleExpression,
        getNode: atruleExpression_1
    });

    var TYPE$5 = require$$0$1.TYPE;

    var IDENTIFIER$3 = TYPE$5.Identifier;
    var NUMBER$3 = TYPE$5.Number;
    var NUMBERSIGN$1 = TYPE$5.NumberSign;
    var LEFTSQUAREBRACKET$2 = TYPE$5.LeftSquareBracket;
    var PLUSSIGN$3 = TYPE$5.PlusSign;
    var SOLIDUS$1 = TYPE$5.Solidus;
    var ASTERISK$1 = TYPE$5.Asterisk;
    var FULLSTOP$2 = TYPE$5.FullStop;
    var COLON = TYPE$5.Colon;
    var GREATERTHANSIGN$1 = TYPE$5.GreaterThanSign;
    var VERTICALLINE = TYPE$5.VerticalLine;
    var TILDE = TYPE$5.Tilde;

    function getNode(context) {
        switch (this.scanner.tokenType) {
            case PLUSSIGN$3:
            case GREATERTHANSIGN$1:
            case TILDE:
                context.space = null;
                context.ignoreWSAfter = true;
                return this.Combinator();

            case SOLIDUS$1:  // /deep/
                return this.Combinator();

            case FULLSTOP$2:
                return this.ClassSelector();

            case LEFTSQUAREBRACKET$2:
                return this.AttributeSelector();

            case NUMBERSIGN$1:
                return this.IdSelector();

            case COLON:
                if (this.scanner.lookupType(1) === COLON) {
                    return this.PseudoElementSelector();
                } else {
                    return this.PseudoClassSelector();
                }

            case IDENTIFIER$3:
            case ASTERISK$1:
            case VERTICALLINE:
                return this.TypeSelector();

            case NUMBER$3:
                return this.Percentage();
        }
    }
    var selector = {
        getNode: getNode
    };
    var selector_1 = selector.getNode;

    var selector$1 = /*#__PURE__*/Object.freeze({
        default: selector,
        __moduleExports: selector,
        getNode: selector_1
    });

    // https://drafts.csswg.org/css-images-4/#element-notation
    // https://developer.mozilla.org/en-US/docs/Web/CSS/element
    var element = function() {
        this.scanner.skipSC();

        var id = this.IdSelector();

        this.scanner.skipSC();

        return new List$1().appendData(
            id
        );
    };

    var element$1 = /*#__PURE__*/Object.freeze({
        default: element,
        __moduleExports: element
    });

    // legacy IE function
    // expression '(' raw ')'
    var expression = function() {
        return new List$1().appendData(
            this.Raw(this.scanner.currentToken, 0, 0, false, false)
        );
    };

    var expression$1 = /*#__PURE__*/Object.freeze({
        default: expression,
        __moduleExports: expression
    });

    var TYPE$6 = require$$0$1.TYPE;

    var IDENTIFIER$4 = TYPE$6.Identifier;
    var COMMA$1 = TYPE$6.Comma;
    var SEMICOLON = TYPE$6.Semicolon;
    var HYPHENMINUS$3 = TYPE$6.HyphenMinus;
    var EXCLAMATIONMARK$1 = TYPE$6.ExclamationMark;

    // var '(' ident (',' <value>? )? ')'
    var _var = function() {
        var children = new List$1();

        this.scanner.skipSC();

        var identStart = this.scanner.tokenStart;

        this.scanner.eat(HYPHENMINUS$3);
        if (this.scanner.source.charCodeAt(this.scanner.tokenStart) !== HYPHENMINUS$3) {
            this.scanner.error('HyphenMinus is expected');
        }
        this.scanner.eat(IDENTIFIER$4);

        children.appendData({
            type: 'Identifier',
            loc: this.getLocation(identStart, this.scanner.tokenStart),
            name: this.scanner.substrToCursor(identStart)
        });

        this.scanner.skipSC();

        if (this.scanner.tokenType === COMMA$1) {
            children.appendData(this.Operator());
            children.appendData(this.parseCustomProperty
                ? this.Value(null)
                : this.Raw(this.scanner.currentToken, EXCLAMATIONMARK$1, SEMICOLON, false, false)
            );
        }

        return children;
    };

    var _var$1 = /*#__PURE__*/Object.freeze({
        default: _var,
        __moduleExports: _var
    });

    var require$$1 = ( element$1 && element ) || element$1;

    var require$$2 = ( expression$1 && expression ) || expression$1;

    var require$$3 = ( _var$1 && _var ) || _var$1;

    var value = {
        getNode: require$$0$2,
        '-moz-element': require$$1,
        'element': require$$1,
        'expression': require$$2,
        'var': require$$3
    };
    var value_1 = value.getNode;

    var value$1 = /*#__PURE__*/Object.freeze({
        default: value,
        __moduleExports: value,
        getNode: value_1
    });

    var require$$0$3 = ( atruleExpression$1 && atruleExpression ) || atruleExpression$1;

    var require$$1$1 = ( selector$1 && selector ) || selector$1;

    var require$$2$1 = ( value$1 && value ) || value$1;

    var scope = {
        AtruleExpression: require$$0$3,
        Selector: require$$1$1,
        Value: require$$2$1
    };
    var scope_1 = scope.AtruleExpression;
    var scope_2 = scope.Selector;
    var scope_3 = scope.Value;

    var scope$1 = /*#__PURE__*/Object.freeze({
        default: scope,
        __moduleExports: scope,
        AtruleExpression: scope_1,
        Selector: scope_2,
        Value: scope_3
    });

    var fontFace = {
        parse: {
            expression: null,
            block: function() {
                return this.Block(this.Declaration);
            }
        }
    };
    var fontFace_1 = fontFace.parse;

    var fontFace$1 = /*#__PURE__*/Object.freeze({
        default: fontFace,
        __moduleExports: fontFace,
        parse: fontFace_1
    });

    var TYPE$7 = require$$0$1.TYPE;

    var STRING$3 = TYPE$7.String;
    var IDENTIFIER$5 = TYPE$7.Identifier;
    var URL$3 = TYPE$7.Url;
    var LEFTPARENTHESIS$2 = TYPE$7.LeftParenthesis;

    var _import = {
        parse: {
            expression: function() {
                var children = new List$1();

                this.scanner.skipSC();

                switch (this.scanner.tokenType) {
                    case STRING$3:
                        children.appendData(this.String());
                        break;

                    case URL$3:
                        children.appendData(this.Url());
                        break;

                    default:
                        this.scanner.error('String or url() is expected');
                }

                if (this.scanner.lookupNonWSType(0) === IDENTIFIER$5 ||
                    this.scanner.lookupNonWSType(0) === LEFTPARENTHESIS$2) {
                    children.appendData(this.WhiteSpace());
                    children.appendData(this.MediaQueryList());
                }

                return children;
            },
            block: null
        }
    };
    var _import_1 = _import.parse;

    var _import$1 = /*#__PURE__*/Object.freeze({
        default: _import,
        __moduleExports: _import,
        parse: _import_1
    });

    var media = {
        parse: {
            expression: function() {
                return new List$1().appendData(
                    this.MediaQueryList()
                );
            },
            block: function() {
                return this.Block(this.Rule);
            }
        }
    };
    var media_1 = media.parse;

    var media$1 = /*#__PURE__*/Object.freeze({
        default: media,
        __moduleExports: media,
        parse: media_1
    });

    var TYPE$8 = require$$0$1.TYPE;
    var LEFTCURLYBRACKET$1 = TYPE$8.LeftCurlyBracket;

    var page = {
        parse: {
            expression: function() {
                if (this.scanner.lookupNonWSType(0) === LEFTCURLYBRACKET$1) {
                    return null;
                }

                return new List$1().appendData(
                    this.SelectorList()
                );
            },
            block: function() {
                return this.Block(this.Declaration);
            }
        }
    };
    var page_1 = page.parse;

    var page$1 = /*#__PURE__*/Object.freeze({
        default: page,
        __moduleExports: page,
        parse: page_1
    });

    var TYPE$9 = require$$0$1.TYPE;

    var WHITESPACE$3 = TYPE$9.WhiteSpace;
    var COMMENT$3 = TYPE$9.Comment;
    var IDENTIFIER$6 = TYPE$9.Identifier;
    var FUNCTION$3 = TYPE$9.Function;
    var LEFTPARENTHESIS$3 = TYPE$9.LeftParenthesis;
    var HYPHENMINUS$4 = TYPE$9.HyphenMinus;
    var COLON$1 = TYPE$9.Colon;

    function consumeRaw() {
        return new List$1().appendData(
            this.Raw(this.scanner.currentToken, 0, 0, false, false)
        );
    }

    function parentheses() {
        var index = 0;

        this.scanner.skipSC();

        // TODO: make it simplier
        if (this.scanner.tokenType === IDENTIFIER$6) {
            index = 1;
        } else if (this.scanner.tokenType === HYPHENMINUS$4 &&
                   this.scanner.lookupType(1) === IDENTIFIER$6) {
            index = 2;
        }

        if (index !== 0 && this.scanner.lookupNonWSType(index) === COLON$1) {
            return new List$1().appendData(
                this.Declaration()
            );
        }

        return readSequence.call(this);
    }

    function readSequence() {
        var children = new List$1();
        var space = null;
        var child;

        this.scanner.skipSC();

        scan:
        while (!this.scanner.eof) {
            switch (this.scanner.tokenType) {
                case WHITESPACE$3:
                    space = this.WhiteSpace();
                    continue;

                case COMMENT$3:
                    this.scanner.next();
                    continue;

                case FUNCTION$3:
                    child = this.Function(consumeRaw, this.scope.AtruleExpression);
                    break;

                case IDENTIFIER$6:
                    child = this.Identifier();
                    break;

                case LEFTPARENTHESIS$3:
                    child = this.Parentheses(parentheses, this.scope.AtruleExpression);
                    break;

                default:
                    break scan;
            }

            if (space !== null) {
                children.appendData(space);
                space = null;
            }

            children.appendData(child);
        }

        return children;
    }

    var supports = {
        parse: {
            expression: function() {
                var children = readSequence.call(this);

                if (children.isEmpty()) {
                    this.scanner.error('Condition is expected');
                }

                return children;
            },
            block: function() {
                return this.Block(this.Rule);
            }
        }
    };
    var supports_1 = supports.parse;

    var supports$1 = /*#__PURE__*/Object.freeze({
        default: supports,
        __moduleExports: supports,
        parse: supports_1
    });

    var require$$0$4 = ( fontFace$1 && fontFace ) || fontFace$1;

    var require$$1$2 = ( _import$1 && _import ) || _import$1;

    var require$$2$2 = ( media$1 && media ) || media$1;

    var require$$3$1 = ( page$1 && page ) || page$1;

    var require$$4 = ( supports$1 && supports ) || supports$1;

    var atrule = {
        'font-face': require$$0$4,
        'import': require$$1$2,
        'media': require$$2$2,
        'page': require$$3$1,
        'supports': require$$4
    };

    var atrule$1 = /*#__PURE__*/Object.freeze({
        default: atrule,
        __moduleExports: atrule
    });

    var dir = {
        parse: function() {
            return new List$1().appendData(
                this.Identifier()
            );
        }
    };
    var dir_1 = dir.parse;

    var dir$1 = /*#__PURE__*/Object.freeze({
        default: dir,
        __moduleExports: dir,
        parse: dir_1
    });

    var has$1 = {
        parse: function() {
            return new List$1().appendData(
                this.SelectorList()
            );
        }
    };
    var has_1 = has$1.parse;

    var has$2 = /*#__PURE__*/Object.freeze({
        default: has$1,
        __moduleExports: has$1,
        parse: has_1
    });

    var lang = {
        parse: function() {
            return new List$1().appendData(
                this.Identifier()
            );
        }
    };
    var lang_1 = lang.parse;

    var lang$1 = /*#__PURE__*/Object.freeze({
        default: lang,
        __moduleExports: lang,
        parse: lang_1
    });

    var selectorList = {
        parse: function selectorList() {
            return new List$1().appendData(
                this.SelectorList()
            );
        }
    };
    var selectorList_1 = selectorList.parse;

    var selectorList$1 = /*#__PURE__*/Object.freeze({
        default: selectorList,
        __moduleExports: selectorList,
        parse: selectorList_1
    });

    var require$$0$5 = ( selectorList$1 && selectorList ) || selectorList$1;

    var matches = require$$0$5;

    var matches$1 = /*#__PURE__*/Object.freeze({
        default: matches,
        __moduleExports: matches
    });

    var not = require$$0$5;

    var not$1 = /*#__PURE__*/Object.freeze({
        default: not,
        __moduleExports: not
    });

    var ALLOW_OF_CLAUSE = true;

    var nthWithOfClause = {
        parse: function() {
            return new List$1().appendData(
                this.Nth(ALLOW_OF_CLAUSE)
            );
        }
    };
    var nthWithOfClause_1 = nthWithOfClause.parse;

    var nthWithOfClause$1 = /*#__PURE__*/Object.freeze({
        default: nthWithOfClause,
        __moduleExports: nthWithOfClause,
        parse: nthWithOfClause_1
    });

    var require$$0$6 = ( nthWithOfClause$1 && nthWithOfClause ) || nthWithOfClause$1;

    var nthChild = require$$0$6;

    var nthChild$1 = /*#__PURE__*/Object.freeze({
        default: nthChild,
        __moduleExports: nthChild
    });

    var nthLastChild = require$$0$6;

    var nthLastChild$1 = /*#__PURE__*/Object.freeze({
        default: nthLastChild,
        __moduleExports: nthLastChild
    });

    var DISALLOW_OF_CLAUSE = false;

    var nth = {
        parse: function nth() {
            return new List$1().appendData(
                this.Nth(DISALLOW_OF_CLAUSE)
            );
        }
    };
    var nth_1 = nth.parse;

    var nth$1 = /*#__PURE__*/Object.freeze({
        default: nth,
        __moduleExports: nth,
        parse: nth_1
    });

    var require$$0$7 = ( nth$1 && nth ) || nth$1;

    var nthLastOfType = require$$0$7;

    var nthLastOfType$1 = /*#__PURE__*/Object.freeze({
        default: nthLastOfType,
        __moduleExports: nthLastOfType
    });

    var nthOfType = require$$0$7;

    var nthOfType$1 = /*#__PURE__*/Object.freeze({
        default: nthOfType,
        __moduleExports: nthOfType
    });

    var slotted = {
        parse: function compoundSelector() {
            return new List$1().appendData(
                this.Selector()
            );
        }
    };
    var slotted_1 = slotted.parse;

    var slotted$1 = /*#__PURE__*/Object.freeze({
        default: slotted,
        __moduleExports: slotted,
        parse: slotted_1
    });

    var require$$0$8 = ( dir$1 && dir ) || dir$1;

    var require$$1$3 = ( has$2 && has$1 ) || has$2;

    var require$$2$3 = ( lang$1 && lang ) || lang$1;

    var require$$3$2 = ( matches$1 && matches ) || matches$1;

    var require$$4$1 = ( not$1 && not ) || not$1;

    var require$$5 = ( nthChild$1 && nthChild ) || nthChild$1;

    var require$$6 = ( nthLastChild$1 && nthLastChild ) || nthLastChild$1;

    var require$$7 = ( nthLastOfType$1 && nthLastOfType ) || nthLastOfType$1;

    var require$$8 = ( nthOfType$1 && nthOfType ) || nthOfType$1;

    var require$$9 = ( slotted$1 && slotted ) || slotted$1;

    var pseudo = {
        'dir': require$$0$8,
        'has': require$$1$3,
        'lang': require$$2$3,
        'matches': require$$3$2,
        'not': require$$4$1,
        'nth-child': require$$5,
        'nth-last-child': require$$6,
        'nth-last-of-type': require$$7,
        'nth-of-type': require$$8,
        'slotted': require$$9
    };

    var pseudo$1 = /*#__PURE__*/Object.freeze({
        default: pseudo,
        __moduleExports: pseudo
    });

    var cmpChar$2 = require$$0$1.cmpChar;
    var isNumber$2 = require$$0$1.isNumber;
    var TYPE$10 = require$$0$1.TYPE;

    var IDENTIFIER$7 = TYPE$10.Identifier;
    var NUMBER$4 = TYPE$10.Number;
    var PLUSSIGN$4 = TYPE$10.PlusSign;
    var HYPHENMINUS$5 = TYPE$10.HyphenMinus;
    var N$3 = 110; // 'n'.charCodeAt(0)
    var DISALLOW_SIGN = true;
    var ALLOW_SIGN = false;

    function checkTokenIsInteger(scanner, disallowSign) {
        var pos = scanner.tokenStart;

        if (scanner.source.charCodeAt(pos) === PLUSSIGN$4 ||
            scanner.source.charCodeAt(pos) === HYPHENMINUS$5) {
            if (disallowSign) {
                scanner.error();
            }
            pos++;
        }

        for (; pos < scanner.tokenEnd; pos++) {
            if (!isNumber$2(scanner.source.charCodeAt(pos))) {
                scanner.error('Unexpected input', pos);
            }
        }
    }

    // An+B microsyntax https://www.w3.org/TR/css-syntax-3/#anb
    var AnPlusB = {
        name: 'AnPlusB',
        structure: {
            a: [String, null],
            b: [String, null]
        },
        parse: function() {
            var start = this.scanner.tokenStart;
            var end = start;
            var prefix = '';
            var a = null;
            var b = null;

            if (this.scanner.tokenType === NUMBER$4 ||
                this.scanner.tokenType === PLUSSIGN$4) {
                checkTokenIsInteger(this.scanner, ALLOW_SIGN);
                prefix = this.scanner.getTokenValue();
                this.scanner.next();
                end = this.scanner.tokenStart;
            }

            if (this.scanner.tokenType === IDENTIFIER$7) {
                var bStart = this.scanner.tokenStart;

                if (cmpChar$2(this.scanner.source, bStart, HYPHENMINUS$5)) {
                    if (prefix === '') {
                        prefix = '-';
                        bStart++;
                    } else {
                        this.scanner.error('Unexpected hyphen minus');
                    }
                }

                if (!cmpChar$2(this.scanner.source, bStart, N$3)) {
                    this.scanner.error();
                }

                a = prefix === ''  ? '1'  :
                    prefix === '+' ? '+1' :
                    prefix === '-' ? '-1' :
                    prefix;

                var len = this.scanner.tokenEnd - bStart;
                if (len > 1) {
                    // ..n-..
                    if (this.scanner.source.charCodeAt(bStart + 1) !== HYPHENMINUS$5) {
                        this.scanner.error('Unexpected input', bStart + 1);
                    }

                    if (len > 2) {
                        // ..n-{number}..
                        this.scanner.tokenStart = bStart + 2;
                    } else {
                        // ..n- {number}
                        this.scanner.next();
                        this.scanner.skipSC();
                    }

                    checkTokenIsInteger(this.scanner, DISALLOW_SIGN);
                    b = '-' + this.scanner.getTokenValue();
                    this.scanner.next();
                    end = this.scanner.tokenStart;
                } else {
                    prefix = '';
                    this.scanner.next();
                    end = this.scanner.tokenStart;
                    this.scanner.skipSC();

                    if (this.scanner.tokenType === HYPHENMINUS$5 ||
                        this.scanner.tokenType === PLUSSIGN$4) {
                        prefix = this.scanner.getTokenValue();
                        this.scanner.next();
                        this.scanner.skipSC();
                    }

                    if (this.scanner.tokenType === NUMBER$4) {
                        checkTokenIsInteger(this.scanner, prefix !== '');

                        if (!isNumber$2(this.scanner.source.charCodeAt(this.scanner.tokenStart))) {
                            prefix = this.scanner.source.charAt(this.scanner.tokenStart);
                            this.scanner.tokenStart++;
                        }

                        if (prefix === '') {
                            // should be an operator before number
                            this.scanner.error();
                        } else if (prefix === '+') {
                            // plus is using by default
                            prefix = '';
                        }

                        b = prefix + this.scanner.getTokenValue();

                        this.scanner.next();
                        end = this.scanner.tokenStart;
                    } else {
                        if (prefix) {
                            this.scanner.eat(NUMBER$4);
                        }
                    }
                }
            } else {
                if (prefix === '' || prefix === '+') { // no number
                    this.scanner.error(
                        'Number or identifier is expected',
                        this.scanner.tokenStart + (
                            this.scanner.tokenType === PLUSSIGN$4 ||
                            this.scanner.tokenType === HYPHENMINUS$5
                        )
                    );
                }

                b = prefix;
            }

            return {
                type: 'AnPlusB',
                loc: this.getLocation(start, end),
                a: a,
                b: b
            };
        },
        generate: function(processChunk, node) {
            var a = node.a !== null && node.a !== undefined;
            var b = node.b !== null && node.b !== undefined;

            if (a) {
                processChunk(
                    node.a === '+1' ? '+n' :
                    node.a ===  '1' ?  'n' :
                    node.a === '-1' ? '-n' :
                    node.a + 'n'
                );

                if (b) {
                    b = String(node.b);
                    if (b.charAt(0) === '-' || b.charAt(0) === '+') {
                        processChunk(b.charAt(0));
                        processChunk(b.substr(1));
                    } else {
                        processChunk('+');
                        processChunk(b);
                    }
                }
            } else {
                processChunk(String(node.b));
            }
        }
    };
    var AnPlusB_1 = AnPlusB.name;
    var AnPlusB_2 = AnPlusB.structure;
    var AnPlusB_3 = AnPlusB.parse;
    var AnPlusB_4 = AnPlusB.generate;

    var AnPlusB$1 = /*#__PURE__*/Object.freeze({
        default: AnPlusB,
        __moduleExports: AnPlusB,
        name: AnPlusB_1,
        structure: AnPlusB_2,
        parse: AnPlusB_3,
        generate: AnPlusB_4
    });

    var TYPE$11 = require$$0$1.TYPE;

    var ATRULE$2 = TYPE$11.Atrule;
    var SEMICOLON$1 = TYPE$11.Semicolon;
    var LEFTCURLYBRACKET$2 = TYPE$11.LeftCurlyBracket;
    var RIGHTCURLYBRACKET$1 = TYPE$11.RightCurlyBracket;

    function isBlockAtrule() {
        for (var offset = 1, type; type = this.scanner.lookupType(offset); offset++) {
            if (type === RIGHTCURLYBRACKET$1) {
                return true;
            }

            if (type === LEFTCURLYBRACKET$2 ||
                type === ATRULE$2) {
                return false;
            }
        }

        this.scanner.skip(offset);
        this.scanner.eat(RIGHTCURLYBRACKET$1);
    }

    var Atrule = {
        name: 'Atrule',
        structure: {
            name: String,
            expression: ['AtruleExpression', null],
            block: ['Block', null]
        },
        parse: function() {
            var start = this.scanner.tokenStart;
            var name;
            var nameLowerCase;
            var expression = null;
            var block = null;

            this.scanner.eat(ATRULE$2);

            name = this.scanner.substrToCursor(start + 1);
            nameLowerCase = name.toLowerCase();
            this.scanner.skipSC();

            expression = this.AtruleExpression(name);

            // turn empty AtruleExpression into null
            if (expression.children.head === null) {
                expression = null;
            }

            this.scanner.skipSC();

            if (this.atrule.hasOwnProperty(nameLowerCase)) {
                if (typeof this.atrule[nameLowerCase].block === 'function') {
                    if (this.scanner.tokenType !== LEFTCURLYBRACKET$2) {
                        // FIXME: make tolerant
                        this.scanner.error('Curly bracket is expected');
                    }

                    block = this.atrule[nameLowerCase].block.call(this);
                } else {
                    if (!this.tolerant || !this.scanner.eof) {
                        this.scanner.eat(SEMICOLON$1);
                    }
                }
            } else {
                switch (this.scanner.tokenType) {
                    case SEMICOLON$1:
                        this.scanner.next();
                        break;

                    case LEFTCURLYBRACKET$2:
                        // TODO: should consume block content as Raw?
                        block = this.Block(isBlockAtrule.call(this) ? this.Declaration : this.Rule);
                        break;

                    default:
                        if (!this.tolerant) {
                            this.scanner.error('Semicolon or block is expected');
                        }
                }
            }

            return {
                type: 'Atrule',
                loc: this.getLocation(start, this.scanner.tokenStart),
                name: name,
                expression: expression,
                block: block
            };
        },
        generate: function(processChunk, node) {
            processChunk('@');
            processChunk(node.name);

            if (node.expression !== null) {
                processChunk(' ');
                this.generate(processChunk, node.expression);
            }

            if (node.block) {
                this.generate(processChunk, node.block);
            } else {
                processChunk(';');
            }
        },
        walkContext: 'atrule'
    };
    var Atrule_1 = Atrule.name;
    var Atrule_2 = Atrule.structure;
    var Atrule_3 = Atrule.parse;
    var Atrule_4 = Atrule.generate;
    var Atrule_5 = Atrule.walkContext;

    var Atrule$1 = /*#__PURE__*/Object.freeze({
        default: Atrule,
        __moduleExports: Atrule,
        name: Atrule_1,
        structure: Atrule_2,
        parse: Atrule_3,
        generate: Atrule_4,
        walkContext: Atrule_5
    });

    var TYPE$12 = require$$0$1.TYPE;
    var SEMICOLON$2 = TYPE$12.Semicolon;
    var LEFTCURLYBRACKET$3 = TYPE$12.LeftCurlyBracket;

    function consumeRaw$1(startToken) {
        return new List$1().appendData(
            this.Raw(startToken, SEMICOLON$2, LEFTCURLYBRACKET$3, false, true)
        );
    }

    function consumeDefaultSequence() {
        return this.readSequence(this.scope.AtruleExpression);
    }

    var AtruleExpression = {
        name: 'AtruleExpression',
        structure: {
            children: [[]]
        },
        parse: function(name) {
            var children = null;
            var startToken = this.scanner.currentToken;

            if (name !== null) {
                name = name.toLowerCase();
            }

            if (this.parseAtruleExpression) {
                // custom consumer
                if (this.atrule.hasOwnProperty(name)) {
                    if (typeof this.atrule[name].expression === 'function') {
                        children = this.tolerantParse(this.atrule[name].expression, consumeRaw$1);
                    }
                } else {
                    // default consumer
                    this.scanner.skipSC();
                    children = this.tolerantParse(consumeDefaultSequence, consumeRaw$1);
                }

                if (this.tolerant) {
                    if (this.scanner.eof || (this.scanner.tokenType !== SEMICOLON$2 && this.scanner.tokenType !== LEFTCURLYBRACKET$3)) {
                        children = consumeRaw$1.call(this, startToken);
                    }
                }
            } else {
                children = consumeRaw$1.call(this, startToken);
            }

            if (children === null) {
                children = new List$1();
            }

            return {
                type: 'AtruleExpression',
                loc: this.getLocationFromList(children),
                children: children
            };
        },
        generate: function(processChunk, node) {
            this.each(processChunk, node);
        },
        walkContext: 'atruleExpression'
    };
    var AtruleExpression_1 = AtruleExpression.name;
    var AtruleExpression_2 = AtruleExpression.structure;
    var AtruleExpression_3 = AtruleExpression.parse;
    var AtruleExpression_4 = AtruleExpression.generate;
    var AtruleExpression_5 = AtruleExpression.walkContext;

    var AtruleExpression$1 = /*#__PURE__*/Object.freeze({
        default: AtruleExpression,
        __moduleExports: AtruleExpression,
        name: AtruleExpression_1,
        structure: AtruleExpression_2,
        parse: AtruleExpression_3,
        generate: AtruleExpression_4,
        walkContext: AtruleExpression_5
    });

    var TYPE$13 = require$$0$1.TYPE;

    var IDENTIFIER$8 = TYPE$13.Identifier;
    var STRING$4 = TYPE$13.String;
    var DOLLARSIGN = TYPE$13.DollarSign;
    var ASTERISK$2 = TYPE$13.Asterisk;
    var COLON$2 = TYPE$13.Colon;
    var EQUALSSIGN = TYPE$13.EqualsSign;
    var LEFTSQUAREBRACKET$3 = TYPE$13.LeftSquareBracket;
    var RIGHTSQUAREBRACKET$1 = TYPE$13.RightSquareBracket;
    var CIRCUMFLEXACCENT = TYPE$13.CircumflexAccent;
    var VERTICALLINE$1 = TYPE$13.VerticalLine;
    var TILDE$1 = TYPE$13.Tilde;

    function getAttributeName() {
        if (this.scanner.eof) {
            this.scanner.error('Unexpected end of input');
        }

        var start = this.scanner.tokenStart;
        var expectIdentifier = false;
        var checkColon = true;

        if (this.scanner.tokenType === ASTERISK$2) {
            expectIdentifier = true;
            checkColon = false;
            this.scanner.next();
        } else if (this.scanner.tokenType !== VERTICALLINE$1) {
            this.scanner.eat(IDENTIFIER$8);
        }

        if (this.scanner.tokenType === VERTICALLINE$1) {
            if (this.scanner.lookupType(1) !== EQUALSSIGN) {
                this.scanner.next();
                this.scanner.eat(IDENTIFIER$8);
            } else if (expectIdentifier) {
                this.scanner.error('Identifier is expected', this.scanner.tokenEnd);
            }
        } else if (expectIdentifier) {
            this.scanner.error('Vertical line is expected');
        }

        if (checkColon && this.scanner.tokenType === COLON$2) {
            this.scanner.next();
            this.scanner.eat(IDENTIFIER$8);
        }

        return {
            type: 'Identifier',
            loc: this.getLocation(start, this.scanner.tokenStart),
            name: this.scanner.substrToCursor(start)
        };
    }

    function getOperator() {
        var start = this.scanner.tokenStart;
        var tokenType = this.scanner.tokenType;

        if (tokenType !== EQUALSSIGN &&        // =
            tokenType !== TILDE$1 &&             // ~=
            tokenType !== CIRCUMFLEXACCENT &&  // ^=
            tokenType !== DOLLARSIGN &&        // $=
            tokenType !== ASTERISK$2 &&          // *=
            tokenType !== VERTICALLINE$1         // |=
        ) {
            this.scanner.error('Attribute selector (=, ~=, ^=, $=, *=, |=) is expected');
        }

        if (tokenType === EQUALSSIGN) {
            this.scanner.next();
        } else {
            this.scanner.next();
            this.scanner.eat(EQUALSSIGN);
        }

        return this.scanner.substrToCursor(start);
    }

    // '[' S* attrib_name ']'
    // '[' S* attrib_name S* attrib_matcher S* [ IDENT | STRING ] S* attrib_flags? S* ']'
    var AttributeSelector = {
        name: 'AttributeSelector',
        structure: {
            name: 'Identifier',
            matcher: [String, null],
            value: ['String', 'Identifier', null],
            flags: [String, null]
        },
        parse: function() {
            var start = this.scanner.tokenStart;
            var name;
            var matcher = null;
            var value = null;
            var flags = null;

            this.scanner.eat(LEFTSQUAREBRACKET$3);
            this.scanner.skipSC();

            name = getAttributeName.call(this);
            this.scanner.skipSC();

            if (this.scanner.tokenType !== RIGHTSQUAREBRACKET$1) {
                // avoid case `[name i]`
                if (this.scanner.tokenType !== IDENTIFIER$8) {
                    matcher = getOperator.call(this);

                    this.scanner.skipSC();

                    value = this.scanner.tokenType === STRING$4
                        ? this.String()
                        : this.Identifier();

                    this.scanner.skipSC();
                }

                // attribute flags
                if (this.scanner.tokenType === IDENTIFIER$8) {
                    flags = this.scanner.getTokenValue();
                    this.scanner.next();

                    this.scanner.skipSC();
                }
            }

            this.scanner.eat(RIGHTSQUAREBRACKET$1);

            return {
                type: 'AttributeSelector',
                loc: this.getLocation(start, this.scanner.tokenStart),
                name: name,
                matcher: matcher,
                value: value,
                flags: flags
            };
        },
        generate: function(processChunk, node) {
            var flagsPrefix = ' ';

            processChunk('[');
            this.generate(processChunk, node.name);

            if (node.matcher !== null) {
                processChunk(node.matcher);

                if (node.value !== null) {
                    this.generate(processChunk, node.value);

                    // space between string and flags is not required
                    if (node.value.type === 'String') {
                        flagsPrefix = '';
                    }
                }
            }

            if (node.flags !== null) {
                processChunk(flagsPrefix);
                processChunk(node.flags);
            }

            processChunk(']');
        }
    };
    var AttributeSelector_1 = AttributeSelector.name;
    var AttributeSelector_2 = AttributeSelector.structure;
    var AttributeSelector_3 = AttributeSelector.parse;
    var AttributeSelector_4 = AttributeSelector.generate;

    var AttributeSelector$1 = /*#__PURE__*/Object.freeze({
        default: AttributeSelector,
        __moduleExports: AttributeSelector,
        name: AttributeSelector_1,
        structure: AttributeSelector_2,
        parse: AttributeSelector_3,
        generate: AttributeSelector_4
    });

    var TYPE$14 = require$$0$1.TYPE;

    var WHITESPACE$4 = TYPE$14.WhiteSpace;
    var COMMENT$4 = TYPE$14.Comment;
    var SEMICOLON$3 = TYPE$14.Semicolon;
    var ATRULE$3 = TYPE$14.Atrule;
    var LEFTCURLYBRACKET$4 = TYPE$14.LeftCurlyBracket;
    var RIGHTCURLYBRACKET$2 = TYPE$14.RightCurlyBracket;

    function consumeRaw$2(startToken) {
        return this.Raw(startToken, 0, SEMICOLON$3, true, true);
    }

    var Block = {
        name: 'Block',
        structure: {
            children: [['Atrule', 'Rule', 'Declaration']]
        },
        parse: function(defaultConsumer) {
            if (!defaultConsumer) {
                defaultConsumer = this.Declaration;
            }

            var start = this.scanner.tokenStart;
            var children = new List$1();

            this.scanner.eat(LEFTCURLYBRACKET$4);

            scan:
            while (!this.scanner.eof) {
                switch (this.scanner.tokenType) {
                    case RIGHTCURLYBRACKET$2:
                        break scan;

                    case WHITESPACE$4:
                    case COMMENT$4:
                    case SEMICOLON$3:
                        this.scanner.next();
                        break;

                    case ATRULE$3:
                        children.appendData(this.tolerantParse(this.Atrule, consumeRaw$2));
                        break;

                    default:
                        children.appendData(this.tolerantParse(defaultConsumer, consumeRaw$2));
                }
            }

            if (!this.tolerant || !this.scanner.eof) {
                this.scanner.eat(RIGHTCURLYBRACKET$2);
            }

            return {
                type: 'Block',
                loc: this.getLocation(start, this.scanner.tokenStart),
                children: children
            };
        },
        generate: function(processChunk, node) {
            processChunk('{');
            this.each(processChunk, node);
            processChunk('}');
        },
        walkContext: 'block'
    };
    var Block_1 = Block.name;
    var Block_2 = Block.structure;
    var Block_3 = Block.parse;
    var Block_4 = Block.generate;
    var Block_5 = Block.walkContext;

    var Block$1 = /*#__PURE__*/Object.freeze({
        default: Block,
        __moduleExports: Block,
        name: Block_1,
        structure: Block_2,
        parse: Block_3,
        generate: Block_4,
        walkContext: Block_5
    });

    var TYPE$15 = require$$0$1.TYPE;
    var LEFTSQUAREBRACKET$4 = TYPE$15.LeftSquareBracket;
    var RIGHTSQUAREBRACKET$2 = TYPE$15.RightSquareBracket;

    // currently only Grid Layout uses square brackets, but left it universal
    // https://drafts.csswg.org/css-grid/#track-sizing
    // [ ident* ]
    var Brackets = {
        name: 'Brackets',
        structure: {
            children: [[]]
        },
        parse: function(readSequence, recognizer) {
            var start = this.scanner.tokenStart;
            var children = null;

            this.scanner.eat(LEFTSQUAREBRACKET$4);
            children = readSequence.call(this, recognizer);
            this.scanner.eat(RIGHTSQUAREBRACKET$2);

            return {
                type: 'Brackets',
                loc: this.getLocation(start, this.scanner.tokenStart),
                children: children
            };
        },
        generate: function(processChunk, node) {
            processChunk('[');
            this.each(processChunk, node);
            processChunk(']');
        }
    };
    var Brackets_1 = Brackets.name;
    var Brackets_2 = Brackets.structure;
    var Brackets_3 = Brackets.parse;
    var Brackets_4 = Brackets.generate;

    var Brackets$1 = /*#__PURE__*/Object.freeze({
        default: Brackets,
        __moduleExports: Brackets,
        name: Brackets_1,
        structure: Brackets_2,
        parse: Brackets_3,
        generate: Brackets_4
    });

    var CDC$2 = require$$0$1.TYPE.CDC;

    var CDC_1 = {
        name: 'CDC',
        structure: [],
        parse: function() {
            var start = this.scanner.tokenStart;

            this.scanner.eat(CDC$2); // -->

            return {
                type: 'CDC',
                loc: this.getLocation(start, this.scanner.tokenStart)
            };
        },
        generate: function(processChunk) {
            processChunk('-->');
        }
    };
    var CDC_2 = CDC_1.name;
    var CDC_3 = CDC_1.structure;
    var CDC_4 = CDC_1.parse;
    var CDC_5 = CDC_1.generate;

    var CDC$3 = /*#__PURE__*/Object.freeze({
        default: CDC_1,
        __moduleExports: CDC_1,
        name: CDC_2,
        structure: CDC_3,
        parse: CDC_4,
        generate: CDC_5
    });

    var CDO$2 = require$$0$1.TYPE.CDO;

    var CDO_1 = {
        name: 'CDO',
        structure: [],
        parse: function() {
            var start = this.scanner.tokenStart;

            this.scanner.eat(CDO$2); // <!--

            return {
                type: 'CDO',
                loc: this.getLocation(start, this.scanner.tokenStart)
            };
        },
        generate: function(processChunk) {
            processChunk('<!--');
        }
    };
    var CDO_2 = CDO_1.name;
    var CDO_3 = CDO_1.structure;
    var CDO_4 = CDO_1.parse;
    var CDO_5 = CDO_1.generate;

    var CDO$3 = /*#__PURE__*/Object.freeze({
        default: CDO_1,
        __moduleExports: CDO_1,
        name: CDO_2,
        structure: CDO_3,
        parse: CDO_4,
        generate: CDO_5
    });

    var TYPE$16 = require$$0$1.TYPE;
    var IDENTIFIER$9 = TYPE$16.Identifier;
    var FULLSTOP$3 = TYPE$16.FullStop;

    // '.' ident
    var ClassSelector = {
        name: 'ClassSelector',
        structure: {
            name: String
        },
        parse: function() {
            this.scanner.eat(FULLSTOP$3);

            return {
                type: 'ClassSelector',
                loc: this.getLocation(this.scanner.tokenStart - 1, this.scanner.tokenEnd),
                name: this.scanner.consume(IDENTIFIER$9)
            };
        },
        generate: function(processChunk, node) {
            processChunk('.');
            processChunk(node.name);
        }
    };
    var ClassSelector_1 = ClassSelector.name;
    var ClassSelector_2 = ClassSelector.structure;
    var ClassSelector_3 = ClassSelector.parse;
    var ClassSelector_4 = ClassSelector.generate;

    var ClassSelector$1 = /*#__PURE__*/Object.freeze({
        default: ClassSelector,
        __moduleExports: ClassSelector,
        name: ClassSelector_1,
        structure: ClassSelector_2,
        parse: ClassSelector_3,
        generate: ClassSelector_4
    });

    var TYPE$17 = require$$0$1.TYPE;

    var PLUSSIGN$5 = TYPE$17.PlusSign;
    var SOLIDUS$2 = TYPE$17.Solidus;
    var GREATERTHANSIGN$2 = TYPE$17.GreaterThanSign;
    var TILDE$2 = TYPE$17.Tilde;

    // + | > | ~ | /deep/
    var Combinator = {
        name: 'Combinator',
        structure: {
            name: String
        },
        parse: function() {
            var start = this.scanner.tokenStart;

            switch (this.scanner.tokenType) {
                case GREATERTHANSIGN$2:
                case PLUSSIGN$5:
                case TILDE$2:
                    this.scanner.next();
                    break;

                case SOLIDUS$2:
                    this.scanner.next();
                    this.scanner.expectIdentifier('deep');
                    this.scanner.eat(SOLIDUS$2);
                    break;

                default:
                    this.scanner.error('Combinator is expected');
            }

            return {
                type: 'Combinator',
                loc: this.getLocation(start, this.scanner.tokenStart),
                name: this.scanner.substrToCursor(start)
            };
        },
        generate: function(processChunk, node) {
            processChunk(node.name);
        }
    };
    var Combinator_1 = Combinator.name;
    var Combinator_2 = Combinator.structure;
    var Combinator_3 = Combinator.parse;
    var Combinator_4 = Combinator.generate;

    var Combinator$1 = /*#__PURE__*/Object.freeze({
        default: Combinator,
        __moduleExports: Combinator,
        name: Combinator_1,
        structure: Combinator_2,
        parse: Combinator_3,
        generate: Combinator_4
    });

    var TYPE$18 = require$$0$1.TYPE;

    var ASTERISK$3 = TYPE$18.Asterisk;
    var SOLIDUS$3 = TYPE$18.Solidus;

    // '/*' .* '*/'
    var Comment = {
        name: 'Comment',
        structure: {
            value: String
        },
        parse: function() {
            var start = this.scanner.tokenStart;
            var end = this.scanner.tokenEnd;

            if ((end - start + 2) >= 2 &&
                this.scanner.source.charCodeAt(end - 2) === ASTERISK$3 &&
                this.scanner.source.charCodeAt(end - 1) === SOLIDUS$3) {
                end -= 2;
            }

            this.scanner.next();

            return {
                type: 'Comment',
                loc: this.getLocation(start, this.scanner.tokenStart),
                value: this.scanner.source.substring(start + 2, end)
            };
        },
        generate: function(processChunk, node) {
            processChunk('/*');
            processChunk(node.value);
            processChunk('*/');
        }
    };
    var Comment_1 = Comment.name;
    var Comment_2 = Comment.structure;
    var Comment_3 = Comment.parse;
    var Comment_4 = Comment.generate;

    var Comment$1 = /*#__PURE__*/Object.freeze({
        default: Comment,
        __moduleExports: Comment,
        name: Comment_1,
        structure: Comment_2,
        parse: Comment_3,
        generate: Comment_4
    });

    var TYPE$19 = require$$0$1.TYPE;

    var IDENTIFIER$10 = TYPE$19.Identifier;
    var COLON$3 = TYPE$19.Colon;
    var EXCLAMATIONMARK$2 = TYPE$19.ExclamationMark;
    var SOLIDUS$4 = TYPE$19.Solidus;
    var ASTERISK$4 = TYPE$19.Asterisk;
    var DOLLARSIGN$1 = TYPE$19.DollarSign;
    var HYPHENMINUS$6 = TYPE$19.HyphenMinus;
    var SEMICOLON$4 = TYPE$19.Semicolon;
    var RIGHTCURLYBRACKET$3 = TYPE$19.RightCurlyBracket;
    var RIGHTPARENTHESIS$1 = TYPE$19.RightParenthesis;
    var PLUSSIGN$6 = TYPE$19.PlusSign;
    var NUMBERSIGN$2 = TYPE$19.NumberSign;

    var Declaration = {
        name: 'Declaration',
        structure: {
            important: [Boolean, String],
            property: String,
            value: ['Value', 'Raw']
        },
        parse: function() {
            var start = this.scanner.tokenStart;
            var property = readProperty.call(this);
            var important = false;
            var value;

            this.scanner.skipSC();
            this.scanner.eat(COLON$3);

            if (isCustomProperty(property) ? this.parseCustomProperty : this.parseValue) {
                value = this.Value(property);
            } else {
                value = this.Raw(this.scanner.currentToken, EXCLAMATIONMARK$2, SEMICOLON$4, false, false);
            }

            if (this.scanner.tokenType === EXCLAMATIONMARK$2) {
                important = getImportant(this.scanner);
                this.scanner.skipSC();
            }

            // TODO: include or not to include semicolon to range?
            // if (this.scanner.tokenType === SEMICOLON) {
            //     this.scanner.next();
            // }

            if (!this.scanner.eof &&
                this.scanner.tokenType !== SEMICOLON$4 &&
                this.scanner.tokenType !== RIGHTPARENTHESIS$1 &&
                this.scanner.tokenType !== RIGHTCURLYBRACKET$3) {
                this.scanner.error();
            }

            return {
                type: 'Declaration',
                loc: this.getLocation(start, this.scanner.tokenStart),
                important: important,
                property: property,
                value: value
            };
        },
        generate: function(processChunk, node, item) {
            processChunk(node.property);
            processChunk(':');
            this.generate(processChunk, node.value);

            if (node.important) {
                processChunk(node.important === true ? '!important' : '!' + node.important);
            }

            if (item && item.next) {
                processChunk(';');
            }
        },
        walkContext: 'declaration'
    };

    function isCustomProperty(name) {
        return name.length >= 2 &&
               name.charCodeAt(0) === HYPHENMINUS$6 &&
               name.charCodeAt(1) === HYPHENMINUS$6;
    }

    function readProperty() {
        var start = this.scanner.tokenStart;
        var prefix = 0;

        // hacks
        switch (this.scanner.tokenType) {
            case ASTERISK$4:
            case DOLLARSIGN$1:
            case PLUSSIGN$6:
            case NUMBERSIGN$2:
                prefix = 1;
                break;

            // TODO: not sure we should support this hack
            case SOLIDUS$4:
                prefix = this.scanner.lookupType(1) === SOLIDUS$4 ? 2 : 1;
                break;
        }

        if (this.scanner.lookupType(prefix) === HYPHENMINUS$6) {
            prefix++;
        }

        if (prefix) {
            this.scanner.skip(prefix);
        }

        this.scanner.eat(IDENTIFIER$10);

        return this.scanner.substrToCursor(start);
    }

    // ! ws* important
    function getImportant(scanner) {
        scanner.eat(EXCLAMATIONMARK$2);
        scanner.skipSC();

        var important = scanner.consume(IDENTIFIER$10);

        // store original value in case it differ from `important`
        // for better original source restoring and hacks like `!ie` support
        return important === 'important' ? true : important;
    }
    var Declaration_1 = Declaration.name;
    var Declaration_2 = Declaration.structure;
    var Declaration_3 = Declaration.parse;
    var Declaration_4 = Declaration.generate;
    var Declaration_5 = Declaration.walkContext;

    var Declaration$1 = /*#__PURE__*/Object.freeze({
        default: Declaration,
        __moduleExports: Declaration,
        name: Declaration_1,
        structure: Declaration_2,
        parse: Declaration_3,
        generate: Declaration_4,
        walkContext: Declaration_5
    });

    var TYPE$20 = require$$0$1.TYPE;

    var WHITESPACE$5 = TYPE$20.WhiteSpace;
    var COMMENT$5 = TYPE$20.Comment;
    var SEMICOLON$5 = TYPE$20.Semicolon;

    function consumeRaw$3(startToken) {
        return this.Raw(startToken, 0, SEMICOLON$5, true, true);
    }

    var DeclarationList = {
        name: 'DeclarationList',
        structure: {
            children: [['Declaration']]
        },
        parse: function() {
            var children = new List$1();

            scan:
            while (!this.scanner.eof) {
                switch (this.scanner.tokenType) {
                    case WHITESPACE$5:
                    case COMMENT$5:
                    case SEMICOLON$5:
                        this.scanner.next();
                        break;

                    default:
                        children.appendData(this.tolerantParse(this.Declaration, consumeRaw$3));
                }
            }

            return {
                type: 'DeclarationList',
                loc: this.getLocationFromList(children),
                children: children
            };
        },
        generate: function(processChunk, node) {
            this.each(processChunk, node);
        }
    };
    var DeclarationList_1 = DeclarationList.name;
    var DeclarationList_2 = DeclarationList.structure;
    var DeclarationList_3 = DeclarationList.parse;
    var DeclarationList_4 = DeclarationList.generate;

    var DeclarationList$1 = /*#__PURE__*/Object.freeze({
        default: DeclarationList,
        __moduleExports: DeclarationList,
        name: DeclarationList_1,
        structure: DeclarationList_2,
        parse: DeclarationList_3,
        generate: DeclarationList_4
    });

    var NUMBER$5 = require$$0$1.TYPE.Number;

    // special reader for units to avoid adjoined IE hacks (i.e. '1px\9')
    function readUnit(scanner) {
        var unit = scanner.getTokenValue();
        var backSlashPos = unit.indexOf('\\');

        if (backSlashPos > 0) {
            // patch token offset
            scanner.tokenStart += backSlashPos;

            // return part before backslash
            return unit.substring(0, backSlashPos);
        }

        // no backslash in unit name
        scanner.next();

        return unit;
    }

    // number ident
    var Dimension = {
        name: 'Dimension',
        structure: {
            value: String,
            unit: String
        },
        parse: function() {
            var start = this.scanner.tokenStart;
            var value = this.scanner.consume(NUMBER$5);
            var unit = readUnit(this.scanner);

            return {
                type: 'Dimension',
                loc: this.getLocation(start, this.scanner.tokenStart),
                value: value,
                unit: unit
            };
        },
        generate: function(processChunk, node) {
            processChunk(node.value);
            processChunk(node.unit);
        }
    };
    var Dimension_1 = Dimension.name;
    var Dimension_2 = Dimension.structure;
    var Dimension_3 = Dimension.parse;
    var Dimension_4 = Dimension.generate;

    var Dimension$1 = /*#__PURE__*/Object.freeze({
        default: Dimension,
        __moduleExports: Dimension,
        name: Dimension_1,
        structure: Dimension_2,
        parse: Dimension_3,
        generate: Dimension_4
    });

    var TYPE$21 = require$$0$1.TYPE;
    var RIGHTPARENTHESIS$2 = TYPE$21.RightParenthesis;

    // <function-token> <sequence> ')'
    var _Function = {
        name: 'Function',
        structure: {
            name: String,
            children: [[]]
        },
        parse: function(readSequence, recognizer) {
            var start = this.scanner.tokenStart;
            var name = this.scanner.consumeFunctionName();
            var nameLowerCase = name.toLowerCase();
            var children;

            children = recognizer.hasOwnProperty(nameLowerCase)
                ? recognizer[nameLowerCase].call(this, recognizer)
                : readSequence.call(this, recognizer);

            this.scanner.eat(RIGHTPARENTHESIS$2);

            return {
                type: 'Function',
                loc: this.getLocation(start, this.scanner.tokenStart),
                name: name,
                children: children
            };
        },
        generate: function(processChunk, node) {
            processChunk(node.name);
            processChunk('(');
            this.each(processChunk, node);
            processChunk(')');
        },
        walkContext: 'function'
    };
    var _Function_1 = _Function.name;
    var _Function_2 = _Function.structure;
    var _Function_3 = _Function.parse;
    var _Function_4 = _Function.generate;
    var _Function_5 = _Function.walkContext;

    var _Function$1 = /*#__PURE__*/Object.freeze({
        default: _Function,
        __moduleExports: _Function,
        name: _Function_1,
        structure: _Function_2,
        parse: _Function_3,
        generate: _Function_4,
        walkContext: _Function_5
    });

    var isHex$1 = require$$0$1.isHex;
    var TYPE$22 = require$$0$1.TYPE;

    var IDENTIFIER$11 = TYPE$22.Identifier;
    var NUMBER$6 = TYPE$22.Number;
    var NUMBERSIGN$3 = TYPE$22.NumberSign;

    function consumeHexSequence(scanner, required) {
        if (!isHex$1(scanner.source.charCodeAt(scanner.tokenStart))) {
            if (required) {
                scanner.error('Unexpected input', scanner.tokenStart);
            } else {
                return;
            }
        }

        for (var pos = scanner.tokenStart + 1; pos < scanner.tokenEnd; pos++) {
            var code = scanner.source.charCodeAt(pos);

            // break on non-hex char
            if (!isHex$1(code)) {
                // break token, exclude symbol
                scanner.tokenStart = pos;
                return;
            }
        }

        // token is full hex sequence, go to next token
        scanner.next();
    }

    // # ident
    var HexColor = {
        name: 'HexColor',
        structure: {
            value: String
        },
        parse: function() {
            var start = this.scanner.tokenStart;

            this.scanner.eat(NUMBERSIGN$3);

            scan:
            switch (this.scanner.tokenType) {
                case NUMBER$6:
                    consumeHexSequence(this.scanner, true);

                    // if token is identifier then number consists of hex only,
                    // try to add identifier to result
                    if (this.scanner.tokenType === IDENTIFIER$11) {
                        consumeHexSequence(this.scanner, false);
                    }

                    break;

                case IDENTIFIER$11:
                    consumeHexSequence(this.scanner, true);
                    break;

                default:
                    this.scanner.error('Number or identifier is expected');
            }

            return {
                type: 'HexColor',
                loc: this.getLocation(start, this.scanner.tokenStart),
                value: this.scanner.substrToCursor(start + 1) // skip #
            };
        },
        generate: function(processChunk, node) {
            processChunk('#');
            processChunk(node.value);
        }
    };
    var HexColor_1 = HexColor.name;
    var HexColor_2 = HexColor.structure;
    var HexColor_3 = HexColor.parse;
    var HexColor_4 = HexColor.generate;

    var HexColor$1 = /*#__PURE__*/Object.freeze({
        default: HexColor,
        __moduleExports: HexColor,
        name: HexColor_1,
        structure: HexColor_2,
        parse: HexColor_3,
        generate: HexColor_4
    });

    var TYPE$23 = require$$0$1.TYPE;
    var IDENTIFIER$12 = TYPE$23.Identifier;

    var Identifier = {
        name: 'Identifier',
        structure: {
            name: String
        },
        parse: function() {
            return {
                type: 'Identifier',
                loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
                name: this.scanner.consume(IDENTIFIER$12)
            };
        },
        generate: function(processChunk, node) {
            processChunk(node.name);
        }
    };
    var Identifier_1 = Identifier.name;
    var Identifier_2 = Identifier.structure;
    var Identifier_3 = Identifier.parse;
    var Identifier_4 = Identifier.generate;

    var Identifier$1 = /*#__PURE__*/Object.freeze({
        default: Identifier,
        __moduleExports: Identifier,
        name: Identifier_1,
        structure: Identifier_2,
        parse: Identifier_3,
        generate: Identifier_4
    });

    var TYPE$24 = require$$0$1.TYPE;
    var IDENTIFIER$13 = TYPE$24.Identifier;
    var NUMBERSIGN$4 = TYPE$24.NumberSign;

    // '#' ident
    var IdSelector = {
        name: 'IdSelector',
        structure: {
            name: String
        },
        parse: function() {
            this.scanner.eat(NUMBERSIGN$4);

            return {
                type: 'IdSelector',
                loc: this.getLocation(this.scanner.tokenStart - 1, this.scanner.tokenEnd),
                name: this.scanner.consume(IDENTIFIER$13)
            };
        },
        generate: function(processChunk, node) {
            processChunk('#');
            processChunk(node.name);
        }
    };
    var IdSelector_1 = IdSelector.name;
    var IdSelector_2 = IdSelector.structure;
    var IdSelector_3 = IdSelector.parse;
    var IdSelector_4 = IdSelector.generate;

    var IdSelector$1 = /*#__PURE__*/Object.freeze({
        default: IdSelector,
        __moduleExports: IdSelector,
        name: IdSelector_1,
        structure: IdSelector_2,
        parse: IdSelector_3,
        generate: IdSelector_4
    });

    var TYPE$25 = require$$0$1.TYPE;

    var IDENTIFIER$14 = TYPE$25.Identifier;
    var NUMBER$7 = TYPE$25.Number;
    var LEFTPARENTHESIS$4 = TYPE$25.LeftParenthesis;
    var RIGHTPARENTHESIS$3 = TYPE$25.RightParenthesis;
    var COLON$4 = TYPE$25.Colon;
    var SOLIDUS$5 = TYPE$25.Solidus;

    var MediaFeature = {
        name: 'MediaFeature',
        structure: {
            name: String,
            value: ['Identifier', 'Number', 'Dimension', 'Ratio', null]
        },
        parse: function() {
            var start = this.scanner.tokenStart;
            var name;
            var value = null;

            this.scanner.eat(LEFTPARENTHESIS$4);
            this.scanner.skipSC();

            name = this.scanner.consume(IDENTIFIER$14);
            this.scanner.skipSC();

            if (this.scanner.tokenType !== RIGHTPARENTHESIS$3) {
                this.scanner.eat(COLON$4);
                this.scanner.skipSC();

                switch (this.scanner.tokenType) {
                    case NUMBER$7:
                        if (this.scanner.lookupType(1) === IDENTIFIER$14) {
                            value = this.Dimension();
                        } else if (this.scanner.lookupNonWSType(1) === SOLIDUS$5) {
                            value = this.Ratio();
                        } else {
                            value = this.Number();
                        }

                        break;

                    case IDENTIFIER$14:
                        value = this.Identifier();

                        break;

                    default:
                        this.scanner.error('Number, dimension, ratio or identifier is expected');
                }

                this.scanner.skipSC();
            }

            this.scanner.eat(RIGHTPARENTHESIS$3);

            return {
                type: 'MediaFeature',
                loc: this.getLocation(start, this.scanner.tokenStart),
                name: name,
                value: value
            };
        },
        generate: function(processChunk, node) {
            processChunk('(');
            processChunk(node.name);
            if (node.value !== null) {
                processChunk(':');
                this.generate(processChunk, node.value);
            }
            processChunk(')');
        }
    };
    var MediaFeature_1 = MediaFeature.name;
    var MediaFeature_2 = MediaFeature.structure;
    var MediaFeature_3 = MediaFeature.parse;
    var MediaFeature_4 = MediaFeature.generate;

    var MediaFeature$1 = /*#__PURE__*/Object.freeze({
        default: MediaFeature,
        __moduleExports: MediaFeature,
        name: MediaFeature_1,
        structure: MediaFeature_2,
        parse: MediaFeature_3,
        generate: MediaFeature_4
    });

    var TYPE$26 = require$$0$1.TYPE;

    var WHITESPACE$6 = TYPE$26.WhiteSpace;
    var COMMENT$6 = TYPE$26.Comment;
    var IDENTIFIER$15 = TYPE$26.Identifier;
    var LEFTPARENTHESIS$5 = TYPE$26.LeftParenthesis;

    var MediaQuery = {
        name: 'MediaQuery',
        structure: {
            children: [['Identifier', 'MediaFeature', 'WhiteSpace']]
        },
        parse: function() {
            this.scanner.skipSC();

            var children = new List$1();
            var child = null;
            var space = null;

            scan:
            while (!this.scanner.eof) {
                switch (this.scanner.tokenType) {
                    case COMMENT$6:
                        this.scanner.next();
                        continue;

                    case WHITESPACE$6:
                        space = this.WhiteSpace();
                        continue;

                    case IDENTIFIER$15:
                        child = this.Identifier();
                        break;

                    case LEFTPARENTHESIS$5:
                        child = this.MediaFeature();
                        break;

                    default:
                        break scan;
                }

                if (space !== null) {
                    children.appendData(space);
                    space = null;
                }

                children.appendData(child);
            }

            if (child === null) {
                this.scanner.error('Identifier or parenthesis is expected');
            }

            return {
                type: 'MediaQuery',
                loc: this.getLocationFromList(children),
                children: children
            };
        },
        generate: function(processChunk, node) {
            this.each(processChunk, node);
        }
    };
    var MediaQuery_1 = MediaQuery.name;
    var MediaQuery_2 = MediaQuery.structure;
    var MediaQuery_3 = MediaQuery.parse;
    var MediaQuery_4 = MediaQuery.generate;

    var MediaQuery$1 = /*#__PURE__*/Object.freeze({
        default: MediaQuery,
        __moduleExports: MediaQuery,
        name: MediaQuery_1,
        structure: MediaQuery_2,
        parse: MediaQuery_3,
        generate: MediaQuery_4
    });

    var COMMA$2 = require$$0$1.TYPE.Comma;

    var MediaQueryList = {
        name: 'MediaQueryList',
        structure: {
            children: [['MediaQuery']]
        },
        parse: function(relative) {
            var children = new List$1();

            this.scanner.skipSC();

            while (!this.scanner.eof) {
                children.appendData(this.MediaQuery(relative));

                if (this.scanner.tokenType !== COMMA$2) {
                    break;
                }

                this.scanner.next();
            }

            return {
                type: 'MediaQueryList',
                loc: this.getLocationFromList(children),
                children: children
            };
        },
        generate: function(processChunk, node) {
            this.eachComma(processChunk, node);
        }
    };
    var MediaQueryList_1 = MediaQueryList.name;
    var MediaQueryList_2 = MediaQueryList.structure;
    var MediaQueryList_3 = MediaQueryList.parse;
    var MediaQueryList_4 = MediaQueryList.generate;

    var MediaQueryList$1 = /*#__PURE__*/Object.freeze({
        default: MediaQueryList,
        __moduleExports: MediaQueryList,
        name: MediaQueryList_1,
        structure: MediaQueryList_2,
        parse: MediaQueryList_3,
        generate: MediaQueryList_4
    });

    // https://drafts.csswg.org/css-syntax-3/#the-anb-type
    var Nth = {
        name: 'Nth',
        structure: {
            nth: ['AnPlusB', 'Identifier'],
            selector: ['SelectorList', null]
        },
        parse: function(allowOfClause) {
            this.scanner.skipSC();

            var start = this.scanner.tokenStart;
            var end = start;
            var selector = null;
            var query;

            if (this.scanner.lookupValue(0, 'odd') || this.scanner.lookupValue(0, 'even')) {
                query = this.Identifier();
            } else {
                query = this.AnPlusB();
            }

            this.scanner.skipSC();

            if (allowOfClause && this.scanner.lookupValue(0, 'of')) {
                this.scanner.next();

                selector = this.SelectorList();

                if (this.needPositions) {
                    end = selector.children.last().loc.end.offset;
                }
            } else {
                if (this.needPositions) {
                    end = query.loc.end.offset;
                }
            }

            return {
                type: 'Nth',
                loc: this.getLocation(start, end),
                nth: query,
                selector: selector
            };
        },
        generate: function(processChunk, node) {
            this.generate(processChunk, node.nth);
            if (node.selector !== null) {
                processChunk(' of ');
                this.generate(processChunk, node.selector);
            }
        }
    };
    var Nth_1 = Nth.name;
    var Nth_2 = Nth.structure;
    var Nth_3 = Nth.parse;
    var Nth_4 = Nth.generate;

    var Nth$1 = /*#__PURE__*/Object.freeze({
        default: Nth,
        __moduleExports: Nth,
        name: Nth_1,
        structure: Nth_2,
        parse: Nth_3,
        generate: Nth_4
    });

    var NUMBER$8 = require$$0$1.TYPE.Number;

    var _Number = {
        name: 'Number',
        structure: {
            value: String
        },
        parse: function() {
            return {
                type: 'Number',
                loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
                value: this.scanner.consume(NUMBER$8)
            };
        },
        generate: function(processChunk, node) {
            processChunk(node.value);
        }
    };
    var _Number_1 = _Number.name;
    var _Number_2 = _Number.structure;
    var _Number_3 = _Number.parse;
    var _Number_4 = _Number.generate;

    var _Number$1 = /*#__PURE__*/Object.freeze({
        default: _Number,
        __moduleExports: _Number,
        name: _Number_1,
        structure: _Number_2,
        parse: _Number_3,
        generate: _Number_4
    });

    // '/' | '*' | ',' | ':' | '+' | '-'
    var Operator = {
        name: 'Operator',
        structure: {
            value: String
        },
        parse: function() {
            var start = this.scanner.tokenStart;

            this.scanner.next();

            return {
                type: 'Operator',
                loc: this.getLocation(start, this.scanner.tokenStart),
                value: this.scanner.substrToCursor(start)
            };
        },
        generate: function(processChunk, node) {
            processChunk(node.value);
        }
    };
    var Operator_1 = Operator.name;
    var Operator_2 = Operator.structure;
    var Operator_3 = Operator.parse;
    var Operator_4 = Operator.generate;

    var Operator$1 = /*#__PURE__*/Object.freeze({
        default: Operator,
        __moduleExports: Operator,
        name: Operator_1,
        structure: Operator_2,
        parse: Operator_3,
        generate: Operator_4
    });

    var TYPE$27 = require$$0$1.TYPE;
    var LEFTPARENTHESIS$6 = TYPE$27.LeftParenthesis;
    var RIGHTPARENTHESIS$4 = TYPE$27.RightParenthesis;

    var Parentheses = {
        name: 'Parentheses',
        structure: {
            children: [[]]
        },
        parse: function(readSequence, recognizer) {
            var start = this.scanner.tokenStart;
            var children = null;

            this.scanner.eat(LEFTPARENTHESIS$6);
            children = readSequence.call(this, recognizer);
            this.scanner.eat(RIGHTPARENTHESIS$4);

            return {
                type: 'Parentheses',
                loc: this.getLocation(start, this.scanner.tokenStart),
                children: children
            };
        },
        generate: function(processChunk, node) {
            processChunk('(');
            this.each(processChunk, node);
            processChunk(')');
        }
    };
    var Parentheses_1 = Parentheses.name;
    var Parentheses_2 = Parentheses.structure;
    var Parentheses_3 = Parentheses.parse;
    var Parentheses_4 = Parentheses.generate;

    var Parentheses$1 = /*#__PURE__*/Object.freeze({
        default: Parentheses,
        __moduleExports: Parentheses,
        name: Parentheses_1,
        structure: Parentheses_2,
        parse: Parentheses_3,
        generate: Parentheses_4
    });

    var TYPE$28 = require$$0$1.TYPE;

    var NUMBER$9 = TYPE$28.Number;
    var PERCENTSIGN$1 = TYPE$28.PercentSign;

    var Percentage = {
        name: 'Percentage',
        structure: {
            value: String
        },
        parse: function() {
            var start = this.scanner.tokenStart;
            var number = this.scanner.consume(NUMBER$9);

            this.scanner.eat(PERCENTSIGN$1);

            return {
                type: 'Percentage',
                loc: this.getLocation(start, this.scanner.tokenStart),
                value: number
            };
        },
        generate: function(processChunk, node) {
            processChunk(node.value);
            processChunk('%');
        }
    };
    var Percentage_1 = Percentage.name;
    var Percentage_2 = Percentage.structure;
    var Percentage_3 = Percentage.parse;
    var Percentage_4 = Percentage.generate;

    var Percentage$1 = /*#__PURE__*/Object.freeze({
        default: Percentage,
        __moduleExports: Percentage,
        name: Percentage_1,
        structure: Percentage_2,
        parse: Percentage_3,
        generate: Percentage_4
    });

    var TYPE$29 = require$$0$1.TYPE;

    var IDENTIFIER$16 = TYPE$29.Identifier;
    var FUNCTION$4 = TYPE$29.Function;
    var COLON$5 = TYPE$29.Colon;
    var RIGHTPARENTHESIS$5 = TYPE$29.RightParenthesis;

    // : ident [ '(' .. ')' ]?
    var PseudoClassSelector = {
        name: 'PseudoClassSelector',
        structure: {
            name: String,
            children: [['Raw'], null]
        },
        parse: function() {
            var start = this.scanner.tokenStart;
            var children = null;
            var name;
            var nameLowerCase;

            this.scanner.eat(COLON$5);

            if (this.scanner.tokenType === FUNCTION$4) {
                name = this.scanner.consumeFunctionName();
                nameLowerCase = name.toLowerCase();

                if (this.pseudo.hasOwnProperty(nameLowerCase)) {
                    this.scanner.skipSC();
                    children = this.pseudo[nameLowerCase].call(this);
                    this.scanner.skipSC();
                } else {
                    children = new List$1().appendData(
                        this.Raw(this.scanner.currentToken, 0, 0, false, false)
                    );
                }

                this.scanner.eat(RIGHTPARENTHESIS$5);
            } else {
                name = this.scanner.consume(IDENTIFIER$16);
            }

            return {
                type: 'PseudoClassSelector',
                loc: this.getLocation(start, this.scanner.tokenStart),
                name: name,
                children: children
            };
        },
        generate: function(processChunk, node) {
            processChunk(':');
            processChunk(node.name);

            if (node.children !== null) {
                processChunk('(');
                this.each(processChunk, node);
                processChunk(')');
            }
        },
        walkContext: 'function'
    };
    var PseudoClassSelector_1 = PseudoClassSelector.name;
    var PseudoClassSelector_2 = PseudoClassSelector.structure;
    var PseudoClassSelector_3 = PseudoClassSelector.parse;
    var PseudoClassSelector_4 = PseudoClassSelector.generate;
    var PseudoClassSelector_5 = PseudoClassSelector.walkContext;

    var PseudoClassSelector$1 = /*#__PURE__*/Object.freeze({
        default: PseudoClassSelector,
        __moduleExports: PseudoClassSelector,
        name: PseudoClassSelector_1,
        structure: PseudoClassSelector_2,
        parse: PseudoClassSelector_3,
        generate: PseudoClassSelector_4,
        walkContext: PseudoClassSelector_5
    });

    var TYPE$30 = require$$0$1.TYPE;

    var IDENTIFIER$17 = TYPE$30.Identifier;
    var FUNCTION$5 = TYPE$30.Function;
    var COLON$6 = TYPE$30.Colon;
    var RIGHTPARENTHESIS$6 = TYPE$30.RightParenthesis;

    // :: ident [ '(' .. ')' ]?
    var PseudoElementSelector = {
        name: 'PseudoElementSelector',
        structure: {
            name: String,
            children: [['Raw'], null]
        },
        parse: function() {
            var start = this.scanner.tokenStart;
            var children = null;
            var name;
            var nameLowerCase;

            this.scanner.eat(COLON$6);
            this.scanner.eat(COLON$6);

            if (this.scanner.tokenType === FUNCTION$5) {
                name = this.scanner.consumeFunctionName();
                nameLowerCase = name.toLowerCase();

                if (this.pseudo.hasOwnProperty(nameLowerCase)) {
                    this.scanner.skipSC();
                    children = this.pseudo[nameLowerCase].call(this);
                    this.scanner.skipSC();
                } else {
                    children = new List$1().appendData(
                        this.Raw(this.scanner.currentToken, 0, 0, false, false)
                    );
                }

                this.scanner.eat(RIGHTPARENTHESIS$6);
            } else {
                name = this.scanner.consume(IDENTIFIER$17);
            }

            return {
                type: 'PseudoElementSelector',
                loc: this.getLocation(start, this.scanner.tokenStart),
                name: name,
                children: children
            };
        },
        generate: function(processChunk, node) {
            processChunk('::');
            processChunk(node.name);

            if (node.children !== null) {
                processChunk('(');
                this.each(processChunk, node);
                processChunk(')');
            }
        },
        walkContext: 'function'
    };
    var PseudoElementSelector_1 = PseudoElementSelector.name;
    var PseudoElementSelector_2 = PseudoElementSelector.structure;
    var PseudoElementSelector_3 = PseudoElementSelector.parse;
    var PseudoElementSelector_4 = PseudoElementSelector.generate;
    var PseudoElementSelector_5 = PseudoElementSelector.walkContext;

    var PseudoElementSelector$1 = /*#__PURE__*/Object.freeze({
        default: PseudoElementSelector,
        __moduleExports: PseudoElementSelector,
        name: PseudoElementSelector_1,
        structure: PseudoElementSelector_2,
        parse: PseudoElementSelector_3,
        generate: PseudoElementSelector_4,
        walkContext: PseudoElementSelector_5
    });

    var isNumber$3 = require$$0$1.isNumber;
    var TYPE$31 = require$$0$1.TYPE;
    var NUMBER$10 = TYPE$31.Number;
    var SOLIDUS$6 = TYPE$31.Solidus;
    var FULLSTOP$4 = TYPE$31.FullStop;

    // Terms of <ratio> should to be a positive number (not zero or negative)
    // (see https://drafts.csswg.org/mediaqueries-3/#values)
    // However, -o-min-device-pixel-ratio takes fractional values as a ratio's term
    // and this is using by various sites. Therefore we relax checking on parse
    // to test a term is unsigned number without exponent part.
    // Additional checks may to be applied on lexer validation.
    function consumeNumber(scanner) {
        var value = scanner.consumeNonWS(NUMBER$10);

        for (var i = 0; i < value.length; i++) {
            var code = value.charCodeAt(i);
            if (!isNumber$3(code) && code !== FULLSTOP$4) {
                scanner.error('Unsigned number is expected', scanner.tokenStart - value.length + i);
            }
        }

        if (Number(value) === 0) {
            scanner.error('Zero number is not allowed', scanner.tokenStart - value.length);
        }

        return value;
    }

    // <positive-integer> S* '/' S* <positive-integer>
    var Ratio = {
        name: 'Ratio',
        structure: {
            left: String,
            right: String
        },
        parse: function() {
            var start = this.scanner.tokenStart;
            var left = consumeNumber(this.scanner);
            var right;

            this.scanner.eatNonWS(SOLIDUS$6);
            right = consumeNumber(this.scanner);

            return {
                type: 'Ratio',
                loc: this.getLocation(start, this.scanner.tokenStart),
                left: left,
                right: right
            };
        },
        generate: function(processChunk, node) {
            processChunk(node.left);
            processChunk('/');
            processChunk(node.right);
        }
    };
    var Ratio_1 = Ratio.name;
    var Ratio_2 = Ratio.structure;
    var Ratio_3 = Ratio.parse;
    var Ratio_4 = Ratio.generate;

    var Ratio$1 = /*#__PURE__*/Object.freeze({
        default: Ratio,
        __moduleExports: Ratio,
        name: Ratio_1,
        structure: Ratio_2,
        parse: Ratio_3,
        generate: Ratio_4
    });

    var Raw = {
        name: 'Raw',
        structure: {
            value: String
        },
        parse: function(startToken, endTokenType1, endTokenType2, includeTokenType2, excludeWhiteSpace) {
            var startOffset = this.scanner.getTokenStart(startToken);
            var endOffset;

            this.scanner.skip(
                this.scanner.getRawLength(
                    startToken,
                    endTokenType1,
                    endTokenType2,
                    includeTokenType2
                )
            );

            if (excludeWhiteSpace && this.scanner.tokenStart > startOffset) {
                endOffset = this.scanner.getOffsetExcludeWS();
            } else {
                endOffset = this.scanner.tokenStart;
            }

            return {
                type: 'Raw',
                loc: this.getLocation(startOffset, endOffset),
                value: this.scanner.source.substring(startOffset, endOffset)
            };
        },
        generate: function(processChunk, node) {
            processChunk(node.value);
        }
    };
    var Raw_1 = Raw.name;
    var Raw_2 = Raw.structure;
    var Raw_3 = Raw.parse;
    var Raw_4 = Raw.generate;

    var Raw$1 = /*#__PURE__*/Object.freeze({
        default: Raw,
        __moduleExports: Raw,
        name: Raw_1,
        structure: Raw_2,
        parse: Raw_3,
        generate: Raw_4
    });

    var TYPE$32 = require$$0$1.TYPE;

    var LEFTCURLYBRACKET$5 = TYPE$32.LeftCurlyBracket;

    function consumeRaw$4(startToken) {
        return this.Raw(startToken, LEFTCURLYBRACKET$5, 0, false, true);
    }

    var Rule = {
        name: 'Rule',
        structure: {
            selector: ['SelectorList', 'Raw'],
            block: ['Block']
        },
        parse: function() {
            var startToken = this.scanner.currentToken;
            var startOffset = this.scanner.tokenStart;
            var selector = this.parseSelector
                ? this.tolerantParse(this.SelectorList, consumeRaw$4)
                : consumeRaw$4.call(this, startToken);
            var block = this.Block(this.Declaration);

            return {
                type: 'Rule',
                loc: this.getLocation(startOffset, this.scanner.tokenStart),
                selector: selector,
                block: block
            };
        },
        generate: function(processChunk, node) {
            this.generate(processChunk, node.selector);
            this.generate(processChunk, node.block);
        },
        walkContext: 'rule'
    };
    var Rule_1 = Rule.name;
    var Rule_2 = Rule.structure;
    var Rule_3 = Rule.parse;
    var Rule_4 = Rule.generate;
    var Rule_5 = Rule.walkContext;

    var Rule$1 = /*#__PURE__*/Object.freeze({
        default: Rule,
        __moduleExports: Rule,
        name: Rule_1,
        structure: Rule_2,
        parse: Rule_3,
        generate: Rule_4,
        walkContext: Rule_5
    });

    var Selector = {
        name: 'Selector',
        structure: {
            children: [[
                'TypeSelector',
                'IdSelector',
                'ClassSelector',
                'AttributeSelector',
                'PseudoClassSelector',
                'PseudoElementSelector',
                'Combinator',
                'WhiteSpace'
            ]]
        },
        parse: function() {
            var children = this.readSequence(this.scope.Selector);

            // nothing were consumed
            if (children.isEmpty()) {
                this.scanner.error('Selector is expected');
            }

            return {
                type: 'Selector',
                loc: this.getLocationFromList(children),
                children: children
            };
        },
        generate: function(processChunk, node) {
            this.each(processChunk, node);
        }
    };
    var Selector_1 = Selector.name;
    var Selector_2 = Selector.structure;
    var Selector_3 = Selector.parse;
    var Selector_4 = Selector.generate;

    var Selector$1 = /*#__PURE__*/Object.freeze({
        default: Selector,
        __moduleExports: Selector,
        name: Selector_1,
        structure: Selector_2,
        parse: Selector_3,
        generate: Selector_4
    });

    var TYPE$33 = require$$0$1.TYPE;

    var COMMA$3 = TYPE$33.Comma;
    var LEFTCURLYBRACKET$6 = TYPE$33.LeftCurlyBracket;

    var SelectorList = {
        name: 'SelectorList',
        structure: {
            children: [['Selector', 'Raw']]
        },
        parse: function() {
            var children = new List$1();

            while (!this.scanner.eof) {
                children.appendData(this.parseSelector
                    ? this.Selector()
                    : this.Raw(this.scanner.currentToken, COMMA$3, LEFTCURLYBRACKET$6, false, false)
                );

                if (this.scanner.tokenType === COMMA$3) {
                    this.scanner.next();
                    continue;
                }

                break;
            }

            return {
                type: 'SelectorList',
                loc: this.getLocationFromList(children),
                children: children
            };
        },
        generate: function(processChunk, node) {
            this.eachComma(processChunk, node);
        },
        walkContext: 'selector'
    };
    var SelectorList_1 = SelectorList.name;
    var SelectorList_2 = SelectorList.structure;
    var SelectorList_3 = SelectorList.parse;
    var SelectorList_4 = SelectorList.generate;
    var SelectorList_5 = SelectorList.walkContext;

    var SelectorList$1 = /*#__PURE__*/Object.freeze({
        default: SelectorList,
        __moduleExports: SelectorList,
        name: SelectorList_1,
        structure: SelectorList_2,
        parse: SelectorList_3,
        generate: SelectorList_4,
        walkContext: SelectorList_5
    });

    var STRING$5 = require$$0$1.TYPE.String;

    var _String = {
        name: 'String',
        structure: {
            value: String
        },
        parse: function() {
            return {
                type: 'String',
                loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
                value: this.scanner.consume(STRING$5)
            };
        },
        generate: function(processChunk, node) {
            processChunk(node.value);
        }
    };
    var _String_1 = _String.name;
    var _String_2 = _String.structure;
    var _String_3 = _String.parse;
    var _String_4 = _String.generate;

    var _String$1 = /*#__PURE__*/Object.freeze({
        default: _String,
        __moduleExports: _String,
        name: _String_1,
        structure: _String_2,
        parse: _String_3,
        generate: _String_4
    });

    var TYPE$34 = require$$0$1.TYPE;

    var WHITESPACE$7 = TYPE$34.WhiteSpace;
    var COMMENT$7 = TYPE$34.Comment;
    var EXCLAMATIONMARK$3 = TYPE$34.ExclamationMark;
    var ATRULE$4 = TYPE$34.Atrule;
    var CDO$4 = TYPE$34.CDO;
    var CDC$4 = TYPE$34.CDC;

    function consumeRaw$5(startToken) {
        return this.Raw(startToken, 0, 0, false, false);
    }

    var StyleSheet = {
        name: 'StyleSheet',
        structure: {
            children: [['Comment', 'Atrule', 'Rule', 'Raw']]
        },
        parse: function() {
            var start = this.scanner.tokenStart;
            var children = new List$1();
            var child;

            scan:
            while (!this.scanner.eof) {
                switch (this.scanner.tokenType) {
                    case WHITESPACE$7:
                        this.scanner.next();
                        continue;

                    case COMMENT$7:
                        // ignore comments except exclamation comments (i.e. /*! .. */) on top level
                        if (this.scanner.source.charCodeAt(this.scanner.tokenStart + 2) !== EXCLAMATIONMARK$3) {
                            this.scanner.next();
                            continue;
                        }

                        child = this.Comment();
                        break;

                    case CDO$4: // <!--
                        child = this.CDO();
                        break;

                    case CDC$4: // -->
                        child = this.CDC();
                        break;

                    // CSS Syntax Module Level 3
                    // §2.2 Error handling
                    // At the "top level" of a stylesheet, an <at-keyword-token> starts an at-rule.
                    case ATRULE$4:
                        child = this.Atrule();
                        break;

                    // Anything else starts a qualified rule ...
                    default:
                        child = this.tolerantParse(this.Rule, consumeRaw$5);
                }

                children.appendData(child);
            }

            return {
                type: 'StyleSheet',
                loc: this.getLocation(start, this.scanner.tokenStart),
                children: children
            };
        },
        generate: function(processChunk, node) {
            this.each(processChunk, node);
        },
        walkContext: 'stylesheet'
    };
    var StyleSheet_1 = StyleSheet.name;
    var StyleSheet_2 = StyleSheet.structure;
    var StyleSheet_3 = StyleSheet.parse;
    var StyleSheet_4 = StyleSheet.generate;
    var StyleSheet_5 = StyleSheet.walkContext;

    var StyleSheet$1 = /*#__PURE__*/Object.freeze({
        default: StyleSheet,
        __moduleExports: StyleSheet,
        name: StyleSheet_1,
        structure: StyleSheet_2,
        parse: StyleSheet_3,
        generate: StyleSheet_4,
        walkContext: StyleSheet_5
    });

    var TYPE$35 = require$$0$1.TYPE;

    var IDENTIFIER$18 = TYPE$35.Identifier;
    var ASTERISK$5 = TYPE$35.Asterisk;
    var VERTICALLINE$2 = TYPE$35.VerticalLine;

    function eatIdentifierOrAsterisk() {
        if (this.scanner.tokenType !== IDENTIFIER$18 &&
            this.scanner.tokenType !== ASTERISK$5) {
            this.scanner.error('Identifier or asterisk is expected');
        }

        this.scanner.next();
    }

    // ident
    // ident|ident
    // ident|*
    // *
    // *|ident
    // *|*
    // |ident
    // |*
    var TypeSelector = {
        name: 'TypeSelector',
        structure: {
            name: String
        },
        parse: function() {
            var start = this.scanner.tokenStart;

            if (this.scanner.tokenType === VERTICALLINE$2) {
                this.scanner.next();
                eatIdentifierOrAsterisk.call(this);
            } else {
                eatIdentifierOrAsterisk.call(this);

                if (this.scanner.tokenType === VERTICALLINE$2) {
                    this.scanner.next();
                    eatIdentifierOrAsterisk.call(this);
                }
            }

            return {
                type: 'TypeSelector',
                loc: this.getLocation(start, this.scanner.tokenStart),
                name: this.scanner.substrToCursor(start)
            };
        },
        generate: function(processChunk, node) {
            processChunk(node.name);
        }
    };
    var TypeSelector_1 = TypeSelector.name;
    var TypeSelector_2 = TypeSelector.structure;
    var TypeSelector_3 = TypeSelector.parse;
    var TypeSelector_4 = TypeSelector.generate;

    var TypeSelector$1 = /*#__PURE__*/Object.freeze({
        default: TypeSelector,
        __moduleExports: TypeSelector,
        name: TypeSelector_1,
        structure: TypeSelector_2,
        parse: TypeSelector_3,
        generate: TypeSelector_4
    });

    var isHex$2 = require$$0$1.isHex;
    var TYPE$36 = require$$0$1.TYPE;

    var IDENTIFIER$19 = TYPE$36.Identifier;
    var NUMBER$11 = TYPE$36.Number;
    var PLUSSIGN$7 = TYPE$36.PlusSign;
    var HYPHENMINUS$7 = TYPE$36.HyphenMinus;
    var FULLSTOP$5 = TYPE$36.FullStop;
    var QUESTIONMARK = TYPE$36.QuestionMark;

    function scanUnicodeNumber(scanner) {
        for (var pos = scanner.tokenStart + 1; pos < scanner.tokenEnd; pos++) {
            var code = scanner.source.charCodeAt(pos);

            // break on fullstop or hyperminus/plussign after exponent
            if (code === FULLSTOP$5 || code === PLUSSIGN$7) {
                // break token, exclude symbol
                scanner.tokenStart = pos;
                return false;
            }
        }

        return true;
    }

    // https://drafts.csswg.org/css-syntax-3/#urange
    function scanUnicodeRange(scanner) {
        var hexStart = scanner.tokenStart + 1; // skip +
        var hexLength = 0;

        scan: {
            if (scanner.tokenType === NUMBER$11) {
                if (scanner.source.charCodeAt(scanner.tokenStart) !== FULLSTOP$5 && scanUnicodeNumber(scanner)) {
                    scanner.next();
                } else if (scanner.source.charCodeAt(scanner.tokenStart) !== HYPHENMINUS$7) {
                    break scan;
                }
            } else {
                scanner.next(); // PLUSSIGN
            }

            if (scanner.tokenType === HYPHENMINUS$7) {
                scanner.next();
            }

            if (scanner.tokenType === NUMBER$11) {
                scanner.next();
            }

            if (scanner.tokenType === IDENTIFIER$19) {
                scanner.next();
            }

            if (scanner.tokenStart === hexStart) {
                scanner.error('Unexpected input', hexStart);
            }
        }

        // validate for U+x{1,6} or U+x{1,6}-x{1,6}
        // where x is [0-9a-fA-F]
        for (var i = hexStart, wasHyphenMinus = false; i < scanner.tokenStart; i++) {
            var code = scanner.source.charCodeAt(i);

            if (isHex$2(code) === false && (code !== HYPHENMINUS$7 || wasHyphenMinus)) {
                scanner.error('Unexpected input', i);
            }

            if (code === HYPHENMINUS$7) {
                // hex sequence shouldn't be an empty
                if (hexLength === 0) {
                    scanner.error('Unexpected input', i);
                }

                wasHyphenMinus = true;
                hexLength = 0;
            } else {
                hexLength++;

                // too long hex sequence
                if (hexLength > 6) {
                    scanner.error('Too long hex sequence', i);
                }
            }

        }

        // check we have a non-zero sequence
        if (hexLength === 0) {
            scanner.error('Unexpected input', i - 1);
        }

        // U+abc???
        if (!wasHyphenMinus) {
            // consume as many U+003F QUESTION MARK (?) code points as possible
            for (; hexLength < 6 && !scanner.eof; scanner.next()) {
                if (scanner.tokenType !== QUESTIONMARK) {
                    break;
                }

                hexLength++;
            }
        }
    }

    var UnicodeRange = {
        name: 'UnicodeRange',
        structure: {
            value: String
        },
        parse: function() {
            var start = this.scanner.tokenStart;

            this.scanner.next(); // U or u
            scanUnicodeRange(this.scanner);

            return {
                type: 'UnicodeRange',
                loc: this.getLocation(start, this.scanner.tokenStart),
                value: this.scanner.substrToCursor(start)
            };
        },
        generate: function(processChunk, node) {
            processChunk(node.value);
        }
    };
    var UnicodeRange_1 = UnicodeRange.name;
    var UnicodeRange_2 = UnicodeRange.structure;
    var UnicodeRange_3 = UnicodeRange.parse;
    var UnicodeRange_4 = UnicodeRange.generate;

    var UnicodeRange$1 = /*#__PURE__*/Object.freeze({
        default: UnicodeRange,
        __moduleExports: UnicodeRange,
        name: UnicodeRange_1,
        structure: UnicodeRange_2,
        parse: UnicodeRange_3,
        generate: UnicodeRange_4
    });

    var TYPE$37 = require$$0$1.TYPE;

    var STRING$6 = TYPE$37.String;
    var URL$4 = TYPE$37.Url;
    var RAW$2 = TYPE$37.Raw;
    var RIGHTPARENTHESIS$7 = TYPE$37.RightParenthesis;

    // url '(' S* (string | raw) S* ')'
    var Url = {
        name: 'Url',
        structure: {
            value: ['String', 'Raw']
        },
        parse: function() {
            var start = this.scanner.tokenStart;
            var value;

            this.scanner.eat(URL$4);
            this.scanner.skipSC();

            switch (this.scanner.tokenType) {
                case STRING$6:
                    value = this.String();
                    break;

                case RAW$2:
                    value = this.Raw(this.scanner.currentToken, 0, RAW$2, true, false);
                    break;

                default:
                    this.scanner.error('String or Raw is expected');
            }

            this.scanner.skipSC();
            this.scanner.eat(RIGHTPARENTHESIS$7);

            return {
                type: 'Url',
                loc: this.getLocation(start, this.scanner.tokenStart),
                value: value
            };
        },
        generate: function(processChunk, node) {
            processChunk('url');
            processChunk('(');
            this.generate(processChunk, node.value);
            processChunk(')');
        }
    };
    var Url_1 = Url.name;
    var Url_2 = Url.structure;
    var Url_3 = Url.parse;
    var Url_4 = Url.generate;

    var Url$1 = /*#__PURE__*/Object.freeze({
        default: Url,
        __moduleExports: Url,
        name: Url_1,
        structure: Url_2,
        parse: Url_3,
        generate: Url_4
    });

    var endsWith$1 = require$$0$1.endsWith;
    var TYPE$38 = require$$0$1.TYPE;

    var WHITESPACE$8 = TYPE$38.WhiteSpace;
    var COMMENT$8 = TYPE$38.Comment;
    var FUNCTION$6 = TYPE$38.Function;
    var COLON$7 = TYPE$38.Colon;
    var SEMICOLON$6 = TYPE$38.Semicolon;
    var EXCLAMATIONMARK$4 = TYPE$38.ExclamationMark;

    // 'progid:' ws* 'DXImageTransform.Microsoft.' ident ws* '(' .* ')'
    function checkProgid(scanner) {
        var offset = 0;

        for (var type; type = scanner.lookupType(offset); offset++) {
            if (type !== WHITESPACE$8 && type !== COMMENT$8) {
                break;
            }
        }

        if (scanner.lookupValue(offset, 'alpha(') ||
            scanner.lookupValue(offset, 'chroma(') ||
            scanner.lookupValue(offset, 'dropshadow(')) {
            if (scanner.lookupType(offset) !== FUNCTION$6) {
                return false;
            }
        } else {
            if (scanner.lookupValue(offset, 'progid') === false ||
                scanner.lookupType(offset + 1) !== COLON$7) {
                return false;
            }
        }

        return true;
    }

    var Value = {
        name: 'Value',
        structure: {
            children: [[]]
        },
        parse: function(property) {
            // special parser for filter property since it can contains non-standart syntax for old IE
            if (property !== null && endsWith$1(property, 'filter') && checkProgid(this.scanner)) {
                this.scanner.skipSC();
                return this.Raw(this.scanner.currentToken, EXCLAMATIONMARK$4, SEMICOLON$6, false, false);
            }

            var start = this.scanner.tokenStart;
            var children = this.readSequence(this.scope.Value);

            return {
                type: 'Value',
                loc: this.getLocation(start, this.scanner.tokenStart),
                children: children
            };
        },
        generate: function(processChunk, node) {
            this.each(processChunk, node);
        }
    };
    var Value_1 = Value.name;
    var Value_2 = Value.structure;
    var Value_3 = Value.parse;
    var Value_4 = Value.generate;

    var Value$1 = /*#__PURE__*/Object.freeze({
        default: Value,
        __moduleExports: Value,
        name: Value_1,
        structure: Value_2,
        parse: Value_3,
        generate: Value_4
    });

    var WHITESPACE$9 = require$$0$1.TYPE.WhiteSpace;
    var SPACE$2 = Object.freeze({
        type: 'WhiteSpace',
        loc: null,
        value: ' '
    });

    var WhiteSpace = {
        name: 'WhiteSpace',
        structure: {
            value: String
        },
        parse: function() {
            this.scanner.eat(WHITESPACE$9);
            return SPACE$2;

            // return {
            //     type: 'WhiteSpace',
            //     loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
            //     value: this.scanner.consume(WHITESPACE)
            // };
        },
        generate: function(processChunk, node) {
            processChunk(node.value);
        }
    };
    var WhiteSpace_1 = WhiteSpace.name;
    var WhiteSpace_2 = WhiteSpace.structure;
    var WhiteSpace_3 = WhiteSpace.parse;
    var WhiteSpace_4 = WhiteSpace.generate;

    var WhiteSpace$1 = /*#__PURE__*/Object.freeze({
        default: WhiteSpace,
        __moduleExports: WhiteSpace,
        name: WhiteSpace_1,
        structure: WhiteSpace_2,
        parse: WhiteSpace_3,
        generate: WhiteSpace_4
    });

    var require$$0$9 = ( AnPlusB$1 && AnPlusB ) || AnPlusB$1;

    var require$$1$4 = ( Atrule$1 && Atrule ) || Atrule$1;

    var require$$2$4 = ( AtruleExpression$1 && AtruleExpression ) || AtruleExpression$1;

    var require$$3$3 = ( AttributeSelector$1 && AttributeSelector ) || AttributeSelector$1;

    var require$$4$2 = ( Block$1 && Block ) || Block$1;

    var require$$5$1 = ( Brackets$1 && Brackets ) || Brackets$1;

    var require$$6$1 = ( CDC$3 && CDC_1 ) || CDC$3;

    var require$$7$1 = ( CDO$3 && CDO_1 ) || CDO$3;

    var require$$8$1 = ( ClassSelector$1 && ClassSelector ) || ClassSelector$1;

    var require$$9$1 = ( Combinator$1 && Combinator ) || Combinator$1;

    var require$$10 = ( Comment$1 && Comment ) || Comment$1;

    var require$$11 = ( Declaration$1 && Declaration ) || Declaration$1;

    var require$$12 = ( DeclarationList$1 && DeclarationList ) || DeclarationList$1;

    var require$$13 = ( Dimension$1 && Dimension ) || Dimension$1;

    var require$$14 = ( _Function$1 && _Function ) || _Function$1;

    var require$$15 = ( HexColor$1 && HexColor ) || HexColor$1;

    var require$$16 = ( Identifier$1 && Identifier ) || Identifier$1;

    var require$$17 = ( IdSelector$1 && IdSelector ) || IdSelector$1;

    var require$$18 = ( MediaFeature$1 && MediaFeature ) || MediaFeature$1;

    var require$$19 = ( MediaQuery$1 && MediaQuery ) || MediaQuery$1;

    var require$$20 = ( MediaQueryList$1 && MediaQueryList ) || MediaQueryList$1;

    var require$$21 = ( Nth$1 && Nth ) || Nth$1;

    var require$$22 = ( _Number$1 && _Number ) || _Number$1;

    var require$$23 = ( Operator$1 && Operator ) || Operator$1;

    var require$$24 = ( Parentheses$1 && Parentheses ) || Parentheses$1;

    var require$$25 = ( Percentage$1 && Percentage ) || Percentage$1;

    var require$$26 = ( PseudoClassSelector$1 && PseudoClassSelector ) || PseudoClassSelector$1;

    var require$$27 = ( PseudoElementSelector$1 && PseudoElementSelector ) || PseudoElementSelector$1;

    var require$$28 = ( Ratio$1 && Ratio ) || Ratio$1;

    var require$$29 = ( Raw$1 && Raw ) || Raw$1;

    var require$$30 = ( Rule$1 && Rule ) || Rule$1;

    var require$$31 = ( Selector$1 && Selector ) || Selector$1;

    var require$$32 = ( SelectorList$1 && SelectorList ) || SelectorList$1;

    var require$$33 = ( _String$1 && _String ) || _String$1;

    var require$$34 = ( StyleSheet$1 && StyleSheet ) || StyleSheet$1;

    var require$$35 = ( TypeSelector$1 && TypeSelector ) || TypeSelector$1;

    var require$$36 = ( UnicodeRange$1 && UnicodeRange ) || UnicodeRange$1;

    var require$$37 = ( Url$1 && Url ) || Url$1;

    var require$$38 = ( Value$1 && Value ) || Value$1;

    var require$$39 = ( WhiteSpace$1 && WhiteSpace ) || WhiteSpace$1;

    var node = {
        AnPlusB: require$$0$9,
        Atrule: require$$1$4,
        AtruleExpression: require$$2$4,
        AttributeSelector: require$$3$3,
        Block: require$$4$2,
        Brackets: require$$5$1,
        CDC: require$$6$1,
        CDO: require$$7$1,
        ClassSelector: require$$8$1,
        Combinator: require$$9$1,
        Comment: require$$10,
        Declaration: require$$11,
        DeclarationList: require$$12,
        Dimension: require$$13,
        Function: require$$14,
        HexColor: require$$15,
        Identifier: require$$16,
        IdSelector: require$$17,
        MediaFeature: require$$18,
        MediaQuery: require$$19,
        MediaQueryList: require$$20,
        Nth: require$$21,
        Number: require$$22,
        Operator: require$$23,
        Parentheses: require$$24,
        Percentage: require$$25,
        PseudoClassSelector: require$$26,
        PseudoElementSelector: require$$27,
        Ratio: require$$28,
        Raw: require$$29,
        Rule: require$$30,
        Selector: require$$31,
        SelectorList: require$$32,
        String: require$$33,
        StyleSheet: require$$34,
        TypeSelector: require$$35,
        UnicodeRange: require$$36,
        Url: require$$37,
        Value: require$$38,
        WhiteSpace: require$$39
    };
    var node_1 = node.AnPlusB;
    var node_2 = node.Atrule;
    var node_3 = node.AtruleExpression;
    var node_4 = node.AttributeSelector;
    var node_5 = node.Block;
    var node_6 = node.Brackets;
    var node_7 = node.CDC;
    var node_8 = node.CDO;
    var node_9 = node.ClassSelector;
    var node_10 = node.Combinator;
    var node_11 = node.Comment;
    var node_12 = node.Declaration;
    var node_13 = node.DeclarationList;
    var node_14 = node.Dimension;
    var node_15 = node.HexColor;
    var node_16 = node.Identifier;
    var node_17 = node.IdSelector;
    var node_18 = node.MediaFeature;
    var node_19 = node.MediaQuery;
    var node_20 = node.MediaQueryList;
    var node_21 = node.Nth;
    var node_22 = node.Operator;
    var node_23 = node.Parentheses;
    var node_24 = node.Percentage;
    var node_25 = node.PseudoClassSelector;
    var node_26 = node.PseudoElementSelector;
    var node_27 = node.Ratio;
    var node_28 = node.Raw;
    var node_29 = node.Rule;
    var node_30 = node.Selector;
    var node_31 = node.SelectorList;
    var node_32 = node.StyleSheet;
    var node_33 = node.TypeSelector;
    var node_34 = node.UnicodeRange;
    var node_35 = node.Url;
    var node_36 = node.Value;
    var node_37 = node.WhiteSpace;

    var node$1 = /*#__PURE__*/Object.freeze({
        default: node,
        __moduleExports: node,
        AnPlusB: node_1,
        Atrule: node_2,
        AtruleExpression: node_3,
        AttributeSelector: node_4,
        Block: node_5,
        Brackets: node_6,
        CDC: node_7,
        CDO: node_8,
        ClassSelector: node_9,
        Combinator: node_10,
        Comment: node_11,
        Declaration: node_12,
        DeclarationList: node_13,
        Dimension: node_14,
        HexColor: node_15,
        Identifier: node_16,
        IdSelector: node_17,
        MediaFeature: node_18,
        MediaQuery: node_19,
        MediaQueryList: node_20,
        Nth: node_21,
        Operator: node_22,
        Parentheses: node_23,
        Percentage: node_24,
        PseudoClassSelector: node_25,
        PseudoElementSelector: node_26,
        Ratio: node_27,
        Raw: node_28,
        Rule: node_29,
        Selector: node_30,
        SelectorList: node_31,
        StyleSheet: node_32,
        TypeSelector: node_33,
        UnicodeRange: node_34,
        Url: node_35,
        Value: node_36,
        WhiteSpace: node_37
    });

    var require$$0$10 = ( scope$1 && scope ) || scope$1;

    var require$$1$5 = ( atrule$1 && atrule ) || atrule$1;

    var require$$2$5 = ( pseudo$1 && pseudo ) || pseudo$1;

    var require$$3$4 = ( node$1 && node ) || node$1;

    var parser = {
        parseContext: {
            default: 'StyleSheet',
            stylesheet: 'StyleSheet',
            atrule: 'Atrule',
            atruleExpression: function(options) {
                return this.AtruleExpression(options.atrule ? String(options.atrule) : null);
            },
            mediaQueryList: 'MediaQueryList',
            mediaQuery: 'MediaQuery',
            rule: 'Rule',
            selectorList: 'SelectorList',
            selector: 'Selector',
            block: function() {
                return this.Block(this.Declaration);
            },
            declarationList: 'DeclarationList',
            declaration: 'Declaration',
            value: function(options) {
                return this.Value(options.property ? String(options.property) : null);
            }
        },
        scope: require$$0$10,
        atrule: require$$1$5,
        pseudo: require$$2$5,
        node: require$$3$4
    };
    var parser_1 = parser.parseContext;
    var parser_2 = parser.scope;
    var parser_3 = parser.atrule;
    var parser_4 = parser.pseudo;
    var parser_5 = parser.node;

    var parser$1 = /*#__PURE__*/Object.freeze({
        default: parser,
        __moduleExports: parser,
        parseContext: parser_1,
        scope: parser_2,
        atrule: parser_3,
        pseudo: parser_4,
        node: parser_5
    });

    var createParser = ( create$1 && create ) || create$1;

    var config = ( parser$1 && parser ) || parser$1;

    var parser$2 = createParser(config);

    function walk ( ast, ref) {
    	var enter = ref.enter;
    	var leave = ref.leave;

    	visit( ast, null, enter, leave );
    }

    var shouldSkip = false;
    var context = { skip: function () { return shouldSkip = true; } };

    var childKeys = {};

    var toString$1 = Object.prototype.toString;

    function isArray$1 ( thing ) {
    	return toString$1.call( thing ) === '[object Array]';
    }

    function visit ( node, parent, enter, leave, prop, index ) {
    	if ( !node ) { return; }

    	if ( enter ) {
    		var _shouldSkip = shouldSkip;
    		shouldSkip = false;
    		enter.call( context, node, parent, prop, index );
    		var skipped = shouldSkip;
    		shouldSkip = _shouldSkip;

    		if ( skipped ) { return; }
    	}

    	var keys = childKeys[ node.type ] || (
    		childKeys[ node.type ] = Object.keys( node ).filter( function (key) { return typeof node[ key ] === 'object'; } )
    	);

    	for ( var i = 0; i < keys.length; i += 1 ) {
    		var key = keys[i];
    		var value = node[ key ];

    		if ( isArray$1( value ) ) {
    			for ( var j = 0; j < value.length; j += 1 ) {
    				visit( value[j], node, enter, leave, key, j );
    			}
    		}

    		else if ( value && value.type ) {
    			visit( value, node, enter, leave, key, null );
    		}
    	}

    	if ( leave ) {
    		leave( node, parent, prop, index );
    	}
    }

    function readStyle(parser, start, attributes) {
        const contentStart = parser.index;
        const styles = parser.readUntil(/<\/style>/);
        const contentEnd = parser.index;
        let ast;
        try {
            ast = parser$2(styles, {
                positions: true,
                offset: contentStart,
            });
        }
        catch (err) {
            if (err.name === 'CssSyntaxError') {
                parser.error({
                    code: `css-syntax-error`,
                    message: err.message
                }, err.offset);
            }
            else {
                throw err;
            }
        }
        ast = JSON.parse(JSON.stringify(ast));
        // tidy up AST
        walk(ast, {
            enter: (node) => {
                // replace `ref:a` nodes
                if (node.type === 'Selector') {
                    for (let i = 0; i < node.children.length; i += 1) {
                        const a = node.children[i];
                        const b = node.children[i + 1];
                        if (isRefSelector(a, b)) {
                            node.children.splice(i, 2, {
                                type: 'RefSelector',
                                start: a.loc.start.offset,
                                end: b.loc.end.offset,
                                name: b.name
                            });
                        }
                    }
                }
                if (node.loc) {
                    node.start = node.loc.start.offset;
                    node.end = node.loc.end.offset;
                    delete node.loc;
                }
            }
        });
        parser.eat('</style>', true);
        const end = parser.index;
        return {
            start,
            end,
            attributes,
            children: ast.children,
            content: {
                start: contentStart,
                end: contentEnd,
                styles,
            },
        };
    }
    function isRefSelector(a, b) {
        if (!b)
            return false;
        return (a.type === 'TypeSelector' &&
            a.name === 'ref' &&
            b.type === 'PseudoClassSelector');
    }

    const DIRECTIVES = {
        Ref: {
            names: ['ref'],
            attribute(start, end, type, name) {
                return { start, end, type, name };
            },
            allowedExpressionTypes: [],
            error: 'ref directives cannot have a value'
        },
        EventHandler: {
            names: ['on'],
            attribute(start, end, type, name, expression) {
                return { start, end, type, name, expression };
            },
            allowedExpressionTypes: ['CallExpression'],
            error: 'Expected a method call'
        },
        Binding: {
            names: ['bind'],
            attribute(start, end, type, name, expression) {
                return {
                    start, end, type, name,
                    value: expression || {
                        type: 'Identifier',
                        start: start + 5,
                        end,
                        name,
                    }
                };
            },
            allowedExpressionTypes: ['Identifier', 'MemberExpression'],
            error: 'Can only bind to an identifier (e.g. `foo`) or a member expression (e.g. `foo.bar` or `foo[baz]`)'
        },
        Transition: {
            names: ['in', 'out', 'transition'],
            attribute(start, end, type, name, expression, directiveName) {
                return {
                    start, end, type, name, expression,
                    intro: directiveName === 'in' || directiveName === 'transition',
                    outro: directiveName === 'out' || directiveName === 'transition',
                };
            },
            allowedExpressionTypes: ['ObjectExpression'],
            error: 'Transition argument must be an object literal, e.g. `{ duration: 400 }`'
        },
        Animation: {
            names: ['animate'],
            attribute(start, end, type, name, expression) {
                return { start, end, type, name, expression };
            },
            allowedExpressionTypes: ['ObjectExpression'],
            error: 'Animation argument must be an object literal, e.g. `{ duration: 400 }`'
        },
        Action: {
            names: ['use'],
            attribute(start, end, type, name, expression) {
                return { start, end, type, name, expression };
            },
            allowedExpressionTypes: ['Identifier', 'MemberExpression', 'ObjectExpression', 'Literal', 'CallExpression'],
            error: 'Data passed to actions must be an identifier (e.g. `foo`), a member expression ' +
                '(e.g. `foo.bar` or `foo[baz]`), a method call (e.g. `foo()`), or a literal (e.g. `true` or `\'a string\'`'
        },
    };
    const lookupByName = {};
    Object.keys(DIRECTIVES).forEach(name => {
        const directive = DIRECTIVES[name];
        directive.names.forEach(type => lookupByName[type] = name);
    });
    function readExpression$1(parser, start, quoteMark) {
        let str = '';
        let escaped = false;
        for (let i = start; i < parser.template.length; i += 1) {
            const char = parser.template[i];
            if (quoteMark) {
                if (char === quoteMark) {
                    if (escaped) {
                        str += quoteMark;
                    }
                    else {
                        break;
                    }
                }
                else if (escaped) {
                    str += '\\' + char;
                    escaped = false;
                }
                else if (char === '\\') {
                    escaped = true;
                }
                else {
                    str += char;
                }
            }
            else if (/[\s\/>]/.test(char)) {
                break;
            }
            else {
                str += char;
            }
        }
        const expression = parseExpressionAt(repeat(' ', start) + str, start, {
            ecmaVersion: 9,
        });
        parser.index = expression.end;
        parser.allowWhitespace();
        if (quoteMark)
            parser.eat(quoteMark, true);
        return expression;
    }
    function readDirective(parser, start, attrName) {
        const [directiveName, name] = attrName.split(':');
        if (name === undefined)
            return; // No colon in the name
        if (directiveName === '') {
            // not a directive — :foo is short for foo={{foo}}
            return {
                start: start,
                end: start + name.length + 1,
                type: 'Attribute',
                name,
                value: getShorthandValue(start + 1, name)
            };
        }
        const type = lookupByName[directiveName];
        if (!type)
            return; // not a registered directive
        const directive = DIRECTIVES[type];
        let expression = null;
        if (parser.eat('=')) {
            const quoteMark = parser.eat(`'`) ? `'` : parser.eat(`"`) ? `"` : null;
            const expressionStart = parser.index;
            try {
                expression = readExpression$1(parser, expressionStart, quoteMark);
                if (directive.allowedExpressionTypes.indexOf(expression.type) === -1) {
                    parser.error({
                        code: `invalid-directive-value`,
                        message: directive.error
                    }, expressionStart);
                }
            }
            catch (err) {
                if (parser.template[expressionStart] === '{') {
                    // assume the mistake was wrapping the directive arguments.
                    // this could yield false positives! but hopefully not too many
                    let message = 'directive values should not be wrapped';
                    const expressionEnd = parser.template.indexOf('}', expressionStart);
                    if (expressionEnd !== -1) {
                        const value = parser.template.slice(expressionStart + 1, expressionEnd);
                        message += ` — use '${value}', not '{${value}}'`;
                    }
                    parser.error({
                        code: `invalid-directive-value`,
                        message
                    }, expressionStart);
                }
                throw err;
            }
        }
        return directive.attribute(start, parser.index, type, name, expression, directiveName);
    }
    function getShorthandValue(start, name) {
        const end = start + name.length;
        return [
            {
                type: 'AttributeShorthand',
                start,
                end,
                expression: {
                    type: 'Identifier',
                    start,
                    end,
                    name,
                },
            },
        ];
    }

    // https://dev.w3.org/html5/html-author/charref
    var htmlEntities = {
        CounterClockwiseContourIntegral: 8755,
        ClockwiseContourIntegral: 8754,
        DoubleLongLeftRightArrow: 10234,
        DiacriticalDoubleAcute: 733,
        NotSquareSupersetEqual: 8931,
        CloseCurlyDoubleQuote: 8221,
        DoubleContourIntegral: 8751,
        FilledVerySmallSquare: 9642,
        NegativeVeryThinSpace: 8203,
        NotPrecedesSlantEqual: 8928,
        NotRightTriangleEqual: 8941,
        NotSucceedsSlantEqual: 8929,
        CapitalDifferentialD: 8517,
        DoubleLeftRightArrow: 8660,
        DoubleLongRightArrow: 10233,
        EmptyVerySmallSquare: 9643,
        NestedGreaterGreater: 8811,
        NotDoubleVerticalBar: 8742,
        NotLeftTriangleEqual: 8940,
        NotSquareSubsetEqual: 8930,
        OpenCurlyDoubleQuote: 8220,
        ReverseUpEquilibrium: 10607,
        DoubleLongLeftArrow: 10232,
        DownLeftRightVector: 10576,
        LeftArrowRightArrow: 8646,
        NegativeMediumSpace: 8203,
        RightArrowLeftArrow: 8644,
        SquareSupersetEqual: 8850,
        leftrightsquigarrow: 8621,
        DownRightTeeVector: 10591,
        DownRightVectorBar: 10583,
        LongLeftRightArrow: 10231,
        Longleftrightarrow: 10234,
        NegativeThickSpace: 8203,
        PrecedesSlantEqual: 8828,
        ReverseEquilibrium: 8651,
        RightDoubleBracket: 10215,
        RightDownTeeVector: 10589,
        RightDownVectorBar: 10581,
        RightTriangleEqual: 8885,
        SquareIntersection: 8851,
        SucceedsSlantEqual: 8829,
        blacktriangleright: 9656,
        longleftrightarrow: 10231,
        DoubleUpDownArrow: 8661,
        DoubleVerticalBar: 8741,
        DownLeftTeeVector: 10590,
        DownLeftVectorBar: 10582,
        FilledSmallSquare: 9724,
        GreaterSlantEqual: 10878,
        LeftDoubleBracket: 10214,
        LeftDownTeeVector: 10593,
        LeftDownVectorBar: 10585,
        LeftTriangleEqual: 8884,
        NegativeThinSpace: 8203,
        NotReverseElement: 8716,
        NotTildeFullEqual: 8775,
        RightAngleBracket: 10217,
        RightUpDownVector: 10575,
        SquareSubsetEqual: 8849,
        VerticalSeparator: 10072,
        blacktriangledown: 9662,
        blacktriangleleft: 9666,
        leftrightharpoons: 8651,
        rightleftharpoons: 8652,
        twoheadrightarrow: 8608,
        DiacriticalAcute: 180,
        DiacriticalGrave: 96,
        DiacriticalTilde: 732,
        DoubleRightArrow: 8658,
        DownArrowUpArrow: 8693,
        EmptySmallSquare: 9723,
        GreaterEqualLess: 8923,
        GreaterFullEqual: 8807,
        LeftAngleBracket: 10216,
        LeftUpDownVector: 10577,
        LessEqualGreater: 8922,
        NonBreakingSpace: 160,
        NotRightTriangle: 8939,
        NotSupersetEqual: 8841,
        RightTriangleBar: 10704,
        RightUpTeeVector: 10588,
        RightUpVectorBar: 10580,
        UnderParenthesis: 9181,
        UpArrowDownArrow: 8645,
        circlearrowright: 8635,
        downharpoonright: 8642,
        ntrianglerighteq: 8941,
        rightharpoondown: 8641,
        rightrightarrows: 8649,
        twoheadleftarrow: 8606,
        vartriangleright: 8883,
        CloseCurlyQuote: 8217,
        ContourIntegral: 8750,
        DoubleDownArrow: 8659,
        DoubleLeftArrow: 8656,
        DownRightVector: 8641,
        LeftRightVector: 10574,
        LeftTriangleBar: 10703,
        LeftUpTeeVector: 10592,
        LeftUpVectorBar: 10584,
        LowerRightArrow: 8600,
        NotGreaterEqual: 8817,
        NotGreaterTilde: 8821,
        NotLeftTriangle: 8938,
        OverParenthesis: 9180,
        RightDownVector: 8642,
        ShortRightArrow: 8594,
        UpperRightArrow: 8599,
        bigtriangledown: 9661,
        circlearrowleft: 8634,
        curvearrowright: 8631,
        downharpoonleft: 8643,
        leftharpoondown: 8637,
        leftrightarrows: 8646,
        nLeftrightarrow: 8654,
        nleftrightarrow: 8622,
        ntrianglelefteq: 8940,
        rightleftarrows: 8644,
        rightsquigarrow: 8605,
        rightthreetimes: 8908,
        straightepsilon: 1013,
        trianglerighteq: 8885,
        vartriangleleft: 8882,
        DiacriticalDot: 729,
        DoubleRightTee: 8872,
        DownLeftVector: 8637,
        GreaterGreater: 10914,
        HorizontalLine: 9472,
        InvisibleComma: 8291,
        InvisibleTimes: 8290,
        LeftDownVector: 8643,
        LeftRightArrow: 8596,
        Leftrightarrow: 8660,
        LessSlantEqual: 10877,
        LongRightArrow: 10230,
        Longrightarrow: 10233,
        LowerLeftArrow: 8601,
        NestedLessLess: 8810,
        NotGreaterLess: 8825,
        NotLessGreater: 8824,
        NotSubsetEqual: 8840,
        NotVerticalBar: 8740,
        OpenCurlyQuote: 8216,
        ReverseElement: 8715,
        RightTeeVector: 10587,
        RightVectorBar: 10579,
        ShortDownArrow: 8595,
        ShortLeftArrow: 8592,
        SquareSuperset: 8848,
        TildeFullEqual: 8773,
        UpperLeftArrow: 8598,
        ZeroWidthSpace: 8203,
        curvearrowleft: 8630,
        doublebarwedge: 8966,
        downdownarrows: 8650,
        hookrightarrow: 8618,
        leftleftarrows: 8647,
        leftrightarrow: 8596,
        leftthreetimes: 8907,
        longrightarrow: 10230,
        looparrowright: 8620,
        nshortparallel: 8742,
        ntriangleright: 8939,
        rightarrowtail: 8611,
        rightharpoonup: 8640,
        trianglelefteq: 8884,
        upharpoonright: 8638,
        ApplyFunction: 8289,
        DifferentialD: 8518,
        DoubleLeftTee: 10980,
        DoubleUpArrow: 8657,
        LeftTeeVector: 10586,
        LeftVectorBar: 10578,
        LessFullEqual: 8806,
        LongLeftArrow: 10229,
        Longleftarrow: 10232,
        NotTildeEqual: 8772,
        NotTildeTilde: 8777,
        Poincareplane: 8460,
        PrecedesEqual: 10927,
        PrecedesTilde: 8830,
        RightArrowBar: 8677,
        RightTeeArrow: 8614,
        RightTriangle: 8883,
        RightUpVector: 8638,
        SucceedsEqual: 10928,
        SucceedsTilde: 8831,
        SupersetEqual: 8839,
        UpEquilibrium: 10606,
        VerticalTilde: 8768,
        VeryThinSpace: 8202,
        bigtriangleup: 9651,
        blacktriangle: 9652,
        divideontimes: 8903,
        fallingdotseq: 8786,
        hookleftarrow: 8617,
        leftarrowtail: 8610,
        leftharpoonup: 8636,
        longleftarrow: 10229,
        looparrowleft: 8619,
        measuredangle: 8737,
        ntriangleleft: 8938,
        shortparallel: 8741,
        smallsetminus: 8726,
        triangleright: 9657,
        upharpoonleft: 8639,
        DownArrowBar: 10515,
        DownTeeArrow: 8615,
        ExponentialE: 8519,
        GreaterEqual: 8805,
        GreaterTilde: 8819,
        HilbertSpace: 8459,
        HumpDownHump: 8782,
        Intersection: 8898,
        LeftArrowBar: 8676,
        LeftTeeArrow: 8612,
        LeftTriangle: 8882,
        LeftUpVector: 8639,
        NotCongruent: 8802,
        NotLessEqual: 8816,
        NotLessTilde: 8820,
        Proportional: 8733,
        RightCeiling: 8969,
        RoundImplies: 10608,
        ShortUpArrow: 8593,
        SquareSubset: 8847,
        UnderBracket: 9141,
        VerticalLine: 124,
        blacklozenge: 10731,
        exponentiale: 8519,
        risingdotseq: 8787,
        triangledown: 9663,
        triangleleft: 9667,
        CircleMinus: 8854,
        CircleTimes: 8855,
        Equilibrium: 8652,
        GreaterLess: 8823,
        LeftCeiling: 8968,
        LessGreater: 8822,
        MediumSpace: 8287,
        NotPrecedes: 8832,
        NotSucceeds: 8833,
        OverBracket: 9140,
        RightVector: 8640,
        Rrightarrow: 8667,
        RuleDelayed: 10740,
        SmallCircle: 8728,
        SquareUnion: 8852,
        SubsetEqual: 8838,
        UpDownArrow: 8597,
        Updownarrow: 8661,
        VerticalBar: 8739,
        backepsilon: 1014,
        blacksquare: 9642,
        circledcirc: 8858,
        circleddash: 8861,
        curlyeqprec: 8926,
        curlyeqsucc: 8927,
        diamondsuit: 9830,
        eqslantless: 10901,
        expectation: 8496,
        nRightarrow: 8655,
        nrightarrow: 8603,
        preccurlyeq: 8828,
        precnapprox: 10937,
        quaternions: 8461,
        straightphi: 981,
        succcurlyeq: 8829,
        succnapprox: 10938,
        thickapprox: 8776,
        updownarrow: 8597,
        Bernoullis: 8492,
        CirclePlus: 8853,
        EqualTilde: 8770,
        Fouriertrf: 8497,
        ImaginaryI: 8520,
        Laplacetrf: 8466,
        LeftVector: 8636,
        Lleftarrow: 8666,
        NotElement: 8713,
        NotGreater: 8815,
        Proportion: 8759,
        RightArrow: 8594,
        RightFloor: 8971,
        Rightarrow: 8658,
        TildeEqual: 8771,
        TildeTilde: 8776,
        UnderBrace: 9183,
        UpArrowBar: 10514,
        UpTeeArrow: 8613,
        circledast: 8859,
        complement: 8705,
        curlywedge: 8911,
        eqslantgtr: 10902,
        gtreqqless: 10892,
        lessapprox: 10885,
        lesseqqgtr: 10891,
        lmoustache: 9136,
        longmapsto: 10236,
        mapstodown: 8615,
        mapstoleft: 8612,
        nLeftarrow: 8653,
        nleftarrow: 8602,
        precapprox: 10935,
        rightarrow: 8594,
        rmoustache: 9137,
        sqsubseteq: 8849,
        sqsupseteq: 8850,
        subsetneqq: 10955,
        succapprox: 10936,
        supsetneqq: 10956,
        upuparrows: 8648,
        varepsilon: 949,
        varnothing: 8709,
        Backslash: 8726,
        CenterDot: 183,
        CircleDot: 8857,
        Congruent: 8801,
        Coproduct: 8720,
        DoubleDot: 168,
        DownArrow: 8595,
        DownBreve: 785,
        Downarrow: 8659,
        HumpEqual: 8783,
        LeftArrow: 8592,
        LeftFloor: 8970,
        Leftarrow: 8656,
        LessTilde: 8818,
        Mellintrf: 8499,
        MinusPlus: 8723,
        NotCupCap: 8813,
        NotExists: 8708,
        OverBrace: 9182,
        PlusMinus: 177,
        Therefore: 8756,
        ThinSpace: 8201,
        TripleDot: 8411,
        UnionPlus: 8846,
        backprime: 8245,
        backsimeq: 8909,
        bigotimes: 10754,
        centerdot: 183,
        checkmark: 10003,
        complexes: 8450,
        dotsquare: 8865,
        downarrow: 8595,
        gtrapprox: 10886,
        gtreqless: 8923,
        heartsuit: 9829,
        leftarrow: 8592,
        lesseqgtr: 8922,
        nparallel: 8742,
        nshortmid: 8740,
        nsubseteq: 8840,
        nsupseteq: 8841,
        pitchfork: 8916,
        rationals: 8474,
        spadesuit: 9824,
        subseteqq: 10949,
        subsetneq: 8842,
        supseteqq: 10950,
        supsetneq: 8843,
        therefore: 8756,
        triangleq: 8796,
        varpropto: 8733,
        DDotrahd: 10513,
        DotEqual: 8784,
        Integral: 8747,
        LessLess: 10913,
        NotEqual: 8800,
        NotTilde: 8769,
        PartialD: 8706,
        Precedes: 8826,
        RightTee: 8866,
        Succeeds: 8827,
        SuchThat: 8715,
        Superset: 8835,
        Uarrocir: 10569,
        UnderBar: 818,
        andslope: 10840,
        angmsdaa: 10664,
        angmsdab: 10665,
        angmsdac: 10666,
        angmsdad: 10667,
        angmsdae: 10668,
        angmsdaf: 10669,
        angmsdag: 10670,
        angmsdah: 10671,
        angrtvbd: 10653,
        approxeq: 8778,
        awconint: 8755,
        backcong: 8780,
        barwedge: 8965,
        bbrktbrk: 9142,
        bigoplus: 10753,
        bigsqcup: 10758,
        biguplus: 10756,
        bigwedge: 8896,
        boxminus: 8863,
        boxtimes: 8864,
        capbrcup: 10825,
        circledR: 174,
        circledS: 9416,
        cirfnint: 10768,
        clubsuit: 9827,
        cupbrcap: 10824,
        curlyvee: 8910,
        cwconint: 8754,
        doteqdot: 8785,
        dotminus: 8760,
        drbkarow: 10512,
        dzigrarr: 10239,
        elinters: 9191,
        emptyset: 8709,
        eqvparsl: 10725,
        fpartint: 10765,
        geqslant: 10878,
        gesdotol: 10884,
        gnapprox: 10890,
        hksearow: 10533,
        hkswarow: 10534,
        imagline: 8464,
        imagpart: 8465,
        infintie: 10717,
        integers: 8484,
        intercal: 8890,
        intlarhk: 10775,
        laemptyv: 10676,
        ldrushar: 10571,
        leqslant: 10877,
        lesdotor: 10883,
        llcorner: 8990,
        lnapprox: 10889,
        lrcorner: 8991,
        lurdshar: 10570,
        mapstoup: 8613,
        multimap: 8888,
        naturals: 8469,
        otimesas: 10806,
        parallel: 8741,
        plusacir: 10787,
        pointint: 10773,
        precneqq: 10933,
        precnsim: 8936,
        profalar: 9006,
        profline: 8978,
        profsurf: 8979,
        raemptyv: 10675,
        realpart: 8476,
        rppolint: 10770,
        rtriltri: 10702,
        scpolint: 10771,
        setminus: 8726,
        shortmid: 8739,
        smeparsl: 10724,
        sqsubset: 8847,
        sqsupset: 8848,
        subseteq: 8838,
        succneqq: 10934,
        succnsim: 8937,
        supseteq: 8839,
        thetasym: 977,
        thicksim: 8764,
        timesbar: 10801,
        triangle: 9653,
        triminus: 10810,
        trpezium: 9186,
        ulcorner: 8988,
        urcorner: 8989,
        varkappa: 1008,
        varsigma: 962,
        vartheta: 977,
        Because: 8757,
        Cayleys: 8493,
        Cconint: 8752,
        Cedilla: 184,
        Diamond: 8900,
        DownTee: 8868,
        Element: 8712,
        Epsilon: 917,
        Implies: 8658,
        LeftTee: 8867,
        NewLine: 10,
        NoBreak: 8288,
        NotLess: 8814,
        Omicron: 927,
        OverBar: 175,
        Product: 8719,
        UpArrow: 8593,
        Uparrow: 8657,
        Upsilon: 933,
        alefsym: 8501,
        angrtvb: 8894,
        angzarr: 9084,
        asympeq: 8781,
        backsim: 8765,
        because: 8757,
        bemptyv: 10672,
        between: 8812,
        bigcirc: 9711,
        bigodot: 10752,
        bigstar: 9733,
        boxplus: 8862,
        ccupssm: 10832,
        cemptyv: 10674,
        cirscir: 10690,
        coloneq: 8788,
        congdot: 10861,
        cudarrl: 10552,
        cudarrr: 10549,
        cularrp: 10557,
        curarrm: 10556,
        dbkarow: 10511,
        ddagger: 8225,
        ddotseq: 10871,
        demptyv: 10673,
        diamond: 8900,
        digamma: 989,
        dotplus: 8724,
        dwangle: 10662,
        epsilon: 949,
        eqcolon: 8789,
        equivDD: 10872,
        gesdoto: 10882,
        gtquest: 10876,
        gtrless: 8823,
        harrcir: 10568,
        intprod: 10812,
        isindot: 8949,
        larrbfs: 10527,
        larrsim: 10611,
        lbrksld: 10639,
        lbrkslu: 10637,
        ldrdhar: 10599,
        lesdoto: 10881,
        lessdot: 8918,
        lessgtr: 8822,
        lesssim: 8818,
        lotimes: 10804,
        lozenge: 9674,
        ltquest: 10875,
        luruhar: 10598,
        maltese: 10016,
        minusdu: 10794,
        napprox: 8777,
        natural: 9838,
        nearrow: 8599,
        nexists: 8708,
        notinva: 8713,
        notinvb: 8951,
        notinvc: 8950,
        notniva: 8716,
        notnivb: 8958,
        notnivc: 8957,
        npolint: 10772,
        nsqsube: 8930,
        nsqsupe: 8931,
        nvinfin: 10718,
        nwarrow: 8598,
        olcross: 10683,
        omicron: 959,
        orderof: 8500,
        orslope: 10839,
        pertenk: 8241,
        planckh: 8462,
        pluscir: 10786,
        plussim: 10790,
        plustwo: 10791,
        precsim: 8830,
        quatint: 10774,
        questeq: 8799,
        rarrbfs: 10528,
        rarrsim: 10612,
        rbrksld: 10638,
        rbrkslu: 10640,
        rdldhar: 10601,
        realine: 8475,
        rotimes: 10805,
        ruluhar: 10600,
        searrow: 8600,
        simplus: 10788,
        simrarr: 10610,
        subedot: 10947,
        submult: 10945,
        subplus: 10943,
        subrarr: 10617,
        succsim: 8831,
        supdsub: 10968,
        supedot: 10948,
        suphsub: 10967,
        suplarr: 10619,
        supmult: 10946,
        supplus: 10944,
        swarrow: 8601,
        topfork: 10970,
        triplus: 10809,
        tritime: 10811,
        uparrow: 8593,
        upsilon: 965,
        uwangle: 10663,
        vzigzag: 10650,
        zigrarr: 8669,
        Aacute: 193,
        Abreve: 258,
        Agrave: 192,
        Assign: 8788,
        Atilde: 195,
        Barwed: 8966,
        Bumpeq: 8782,
        Cacute: 262,
        Ccaron: 268,
        Ccedil: 199,
        Colone: 10868,
        Conint: 8751,
        CupCap: 8781,
        Dagger: 8225,
        Dcaron: 270,
        DotDot: 8412,
        Dstrok: 272,
        Eacute: 201,
        Ecaron: 282,
        Egrave: 200,
        Exists: 8707,
        ForAll: 8704,
        Gammad: 988,
        Gbreve: 286,
        Gcedil: 290,
        HARDcy: 1066,
        Hstrok: 294,
        Iacute: 205,
        Igrave: 204,
        Itilde: 296,
        Jsercy: 1032,
        Kcedil: 310,
        Lacute: 313,
        Lambda: 923,
        Lcaron: 317,
        Lcedil: 315,
        Lmidot: 319,
        Lstrok: 321,
        Nacute: 323,
        Ncaron: 327,
        Ncedil: 325,
        Ntilde: 209,
        Oacute: 211,
        Odblac: 336,
        Ograve: 210,
        Oslash: 216,
        Otilde: 213,
        Otimes: 10807,
        Racute: 340,
        Rarrtl: 10518,
        Rcaron: 344,
        Rcedil: 342,
        SHCHcy: 1065,
        SOFTcy: 1068,
        Sacute: 346,
        Scaron: 352,
        Scedil: 350,
        Square: 9633,
        Subset: 8912,
        Supset: 8913,
        Tcaron: 356,
        Tcedil: 354,
        Tstrok: 358,
        Uacute: 218,
        Ubreve: 364,
        Udblac: 368,
        Ugrave: 217,
        Utilde: 360,
        Vdashl: 10982,
        Verbar: 8214,
        Vvdash: 8874,
        Yacute: 221,
        Zacute: 377,
        Zcaron: 381,
        aacute: 225,
        abreve: 259,
        agrave: 224,
        andand: 10837,
        angmsd: 8737,
        angsph: 8738,
        apacir: 10863,
        approx: 8776,
        atilde: 227,
        barvee: 8893,
        barwed: 8965,
        becaus: 8757,
        bernou: 8492,
        bigcap: 8898,
        bigcup: 8899,
        bigvee: 8897,
        bkarow: 10509,
        bottom: 8869,
        bowtie: 8904,
        boxbox: 10697,
        bprime: 8245,
        brvbar: 166,
        bullet: 8226,
        bumpeq: 8783,
        cacute: 263,
        capand: 10820,
        capcap: 10827,
        capcup: 10823,
        capdot: 10816,
        ccaron: 269,
        ccedil: 231,
        circeq: 8791,
        cirmid: 10991,
        colone: 8788,
        commat: 64,
        compfn: 8728,
        conint: 8750,
        coprod: 8720,
        copysr: 8471,
        cularr: 8630,
        cupcap: 10822,
        cupcup: 10826,
        cupdot: 8845,
        curarr: 8631,
        curren: 164,
        cylcty: 9005,
        dagger: 8224,
        daleth: 8504,
        dcaron: 271,
        dfisht: 10623,
        divide: 247,
        divonx: 8903,
        dlcorn: 8990,
        dlcrop: 8973,
        dollar: 36,
        drcorn: 8991,
        drcrop: 8972,
        dstrok: 273,
        eacute: 233,
        easter: 10862,
        ecaron: 283,
        ecolon: 8789,
        egrave: 232,
        egsdot: 10904,
        elsdot: 10903,
        emptyv: 8709,
        emsp13: 8196,
        emsp14: 8197,
        eparsl: 10723,
        eqcirc: 8790,
        equals: 61,
        equest: 8799,
        female: 9792,
        ffilig: 64259,
        ffllig: 64260,
        forall: 8704,
        frac12: 189,
        frac13: 8531,
        frac14: 188,
        frac15: 8533,
        frac16: 8537,
        frac18: 8539,
        frac23: 8532,
        frac25: 8534,
        frac34: 190,
        frac35: 8535,
        frac38: 8540,
        frac45: 8536,
        frac56: 8538,
        frac58: 8541,
        frac78: 8542,
        gacute: 501,
        gammad: 989,
        gbreve: 287,
        gesdot: 10880,
        gesles: 10900,
        gtlPar: 10645,
        gtrarr: 10616,
        gtrdot: 8919,
        gtrsim: 8819,
        hairsp: 8202,
        hamilt: 8459,
        hardcy: 1098,
        hearts: 9829,
        hellip: 8230,
        hercon: 8889,
        homtht: 8763,
        horbar: 8213,
        hslash: 8463,
        hstrok: 295,
        hybull: 8259,
        hyphen: 8208,
        iacute: 237,
        igrave: 236,
        iiiint: 10764,
        iinfin: 10716,
        incare: 8453,
        inodot: 305,
        intcal: 8890,
        iquest: 191,
        isinsv: 8947,
        itilde: 297,
        jsercy: 1112,
        kappav: 1008,
        kcedil: 311,
        kgreen: 312,
        lAtail: 10523,
        lacute: 314,
        lagran: 8466,
        lambda: 955,
        langle: 10216,
        larrfs: 10525,
        larrhk: 8617,
        larrlp: 8619,
        larrpl: 10553,
        larrtl: 8610,
        latail: 10521,
        lbrace: 123,
        lbrack: 91,
        lcaron: 318,
        lcedil: 316,
        ldquor: 8222,
        lesdot: 10879,
        lesges: 10899,
        lfisht: 10620,
        lfloor: 8970,
        lharul: 10602,
        llhard: 10603,
        lmidot: 320,
        lmoust: 9136,
        loplus: 10797,
        lowast: 8727,
        lowbar: 95,
        lparlt: 10643,
        lrhard: 10605,
        lsaquo: 8249,
        lsquor: 8218,
        lstrok: 322,
        lthree: 8907,
        ltimes: 8905,
        ltlarr: 10614,
        ltrPar: 10646,
        mapsto: 8614,
        marker: 9646,
        mcomma: 10793,
        midast: 42,
        midcir: 10992,
        middot: 183,
        minusb: 8863,
        minusd: 8760,
        mnplus: 8723,
        models: 8871,
        mstpos: 8766,
        nVDash: 8879,
        nVdash: 8878,
        nacute: 324,
        ncaron: 328,
        ncedil: 326,
        nearhk: 10532,
        nequiv: 8802,
        nesear: 10536,
        nexist: 8708,
        nltrie: 8940,
        nprcue: 8928,
        nrtrie: 8941,
        nsccue: 8929,
        nsimeq: 8772,
        ntilde: 241,
        numero: 8470,
        nvDash: 8877,
        nvHarr: 10500,
        nvdash: 8876,
        nvlArr: 10498,
        nvrArr: 10499,
        nwarhk: 10531,
        nwnear: 10535,
        oacute: 243,
        odblac: 337,
        odsold: 10684,
        ograve: 242,
        ominus: 8854,
        origof: 8886,
        oslash: 248,
        otilde: 245,
        otimes: 8855,
        parsim: 10995,
        percnt: 37,
        period: 46,
        permil: 8240,
        phmmat: 8499,
        planck: 8463,
        plankv: 8463,
        plusdo: 8724,
        plusdu: 10789,
        plusmn: 177,
        preceq: 10927,
        primes: 8473,
        prnsim: 8936,
        propto: 8733,
        prurel: 8880,
        puncsp: 8200,
        qprime: 8279,
        rAtail: 10524,
        racute: 341,
        rangle: 10217,
        rarrap: 10613,
        rarrfs: 10526,
        rarrhk: 8618,
        rarrlp: 8620,
        rarrpl: 10565,
        rarrtl: 8611,
        ratail: 10522,
        rbrace: 125,
        rbrack: 93,
        rcaron: 345,
        rcedil: 343,
        rdquor: 8221,
        rfisht: 10621,
        rfloor: 8971,
        rharul: 10604,
        rmoust: 9137,
        roplus: 10798,
        rpargt: 10644,
        rsaquo: 8250,
        rsquor: 8217,
        rthree: 8908,
        rtimes: 8906,
        sacute: 347,
        scaron: 353,
        scedil: 351,
        scnsim: 8937,
        searhk: 10533,
        seswar: 10537,
        sfrown: 8994,
        shchcy: 1097,
        sigmaf: 962,
        sigmav: 962,
        simdot: 10858,
        smashp: 10803,
        softcy: 1100,
        solbar: 9023,
        spades: 9824,
        sqsube: 8849,
        sqsupe: 8850,
        square: 9633,
        squarf: 9642,
        ssetmn: 8726,
        ssmile: 8995,
        sstarf: 8902,
        subdot: 10941,
        subset: 8834,
        subsim: 10951,
        subsub: 10965,
        subsup: 10963,
        succeq: 10928,
        supdot: 10942,
        supset: 8835,
        supsim: 10952,
        supsub: 10964,
        supsup: 10966,
        swarhk: 10534,
        swnwar: 10538,
        target: 8982,
        tcaron: 357,
        tcedil: 355,
        telrec: 8981,
        there4: 8756,
        thetav: 977,
        thinsp: 8201,
        thksim: 8764,
        timesb: 8864,
        timesd: 10800,
        topbot: 9014,
        topcir: 10993,
        tprime: 8244,
        tridot: 9708,
        tstrok: 359,
        uacute: 250,
        ubreve: 365,
        udblac: 369,
        ufisht: 10622,
        ugrave: 249,
        ulcorn: 8988,
        ulcrop: 8975,
        urcorn: 8989,
        urcrop: 8974,
        utilde: 361,
        vangrt: 10652,
        varphi: 966,
        varrho: 1009,
        veebar: 8891,
        vellip: 8942,
        verbar: 124,
        wedbar: 10847,
        wedgeq: 8793,
        weierp: 8472,
        wreath: 8768,
        xoplus: 10753,
        xotime: 10754,
        xsqcup: 10758,
        xuplus: 10756,
        xwedge: 8896,
        yacute: 253,
        zacute: 378,
        zcaron: 382,
        zeetrf: 8488,
        AElig: 198,
        Acirc: 194,
        Alpha: 913,
        Amacr: 256,
        Aogon: 260,
        Aring: 197,
        Breve: 728,
        Ccirc: 264,
        Colon: 8759,
        Cross: 10799,
        Dashv: 10980,
        Delta: 916,
        Ecirc: 202,
        Emacr: 274,
        Eogon: 280,
        Equal: 10869,
        Gamma: 915,
        Gcirc: 284,
        Hacek: 711,
        Hcirc: 292,
        IJlig: 306,
        Icirc: 206,
        Imacr: 298,
        Iogon: 302,
        Iukcy: 1030,
        Jcirc: 308,
        Jukcy: 1028,
        Kappa: 922,
        OElig: 338,
        Ocirc: 212,
        Omacr: 332,
        Omega: 937,
        Prime: 8243,
        RBarr: 10512,
        Scirc: 348,
        Sigma: 931,
        THORN: 222,
        TRADE: 8482,
        TSHcy: 1035,
        Theta: 920,
        Tilde: 8764,
        Ubrcy: 1038,
        Ucirc: 219,
        Umacr: 362,
        Union: 8899,
        Uogon: 370,
        UpTee: 8869,
        Uring: 366,
        VDash: 8875,
        Vdash: 8873,
        Wcirc: 372,
        Wedge: 8896,
        Ycirc: 374,
        acirc: 226,
        acute: 180,
        aelig: 230,
        aleph: 8501,
        alpha: 945,
        amacr: 257,
        amalg: 10815,
        angle: 8736,
        angrt: 8735,
        angst: 8491,
        aogon: 261,
        aring: 229,
        asymp: 8776,
        awint: 10769,
        bcong: 8780,
        bdquo: 8222,
        bepsi: 1014,
        blank: 9251,
        blk12: 9618,
        blk14: 9617,
        blk34: 9619,
        block: 9608,
        boxDL: 9559,
        boxDR: 9556,
        boxDl: 9558,
        boxDr: 9555,
        boxHD: 9574,
        boxHU: 9577,
        boxHd: 9572,
        boxHu: 9575,
        boxUL: 9565,
        boxUR: 9562,
        boxUl: 9564,
        boxUr: 9561,
        boxVH: 9580,
        boxVL: 9571,
        boxVR: 9568,
        boxVh: 9579,
        boxVl: 9570,
        boxVr: 9567,
        boxdL: 9557,
        boxdR: 9554,
        boxdl: 9488,
        boxdr: 9484,
        boxhD: 9573,
        boxhU: 9576,
        boxhd: 9516,
        boxhu: 9524,
        boxuL: 9563,
        boxuR: 9560,
        boxul: 9496,
        boxur: 9492,
        boxvH: 9578,
        boxvL: 9569,
        boxvR: 9566,
        boxvh: 9532,
        boxvl: 9508,
        boxvr: 9500,
        breve: 728,
        bsemi: 8271,
        bsime: 8909,
        bsolb: 10693,
        bumpE: 10926,
        bumpe: 8783,
        caret: 8257,
        caron: 711,
        ccaps: 10829,
        ccirc: 265,
        ccups: 10828,
        cedil: 184,
        check: 10003,
        clubs: 9827,
        colon: 58,
        comma: 44,
        crarr: 8629,
        cross: 10007,
        csube: 10961,
        csupe: 10962,
        ctdot: 8943,
        cuepr: 8926,
        cuesc: 8927,
        cupor: 10821,
        cuvee: 8910,
        cuwed: 8911,
        cwint: 8753,
        dashv: 8867,
        dblac: 733,
        ddarr: 8650,
        delta: 948,
        dharl: 8643,
        dharr: 8642,
        diams: 9830,
        disin: 8946,
        doteq: 8784,
        dtdot: 8945,
        dtrif: 9662,
        duarr: 8693,
        duhar: 10607,
        eDDot: 10871,
        ecirc: 234,
        efDot: 8786,
        emacr: 275,
        empty: 8709,
        eogon: 281,
        eplus: 10865,
        epsiv: 949,
        eqsim: 8770,
        equiv: 8801,
        erDot: 8787,
        erarr: 10609,
        esdot: 8784,
        exist: 8707,
        fflig: 64256,
        filig: 64257,
        fllig: 64258,
        fltns: 9649,
        forkv: 10969,
        frasl: 8260,
        frown: 8994,
        gamma: 947,
        gcirc: 285,
        gescc: 10921,
        gimel: 8503,
        gneqq: 8809,
        gnsim: 8935,
        grave: 96,
        gsime: 10894,
        gsiml: 10896,
        gtcir: 10874,
        gtdot: 8919,
        harrw: 8621,
        hcirc: 293,
        hoarr: 8703,
        icirc: 238,
        iexcl: 161,
        iiint: 8749,
        iiota: 8489,
        ijlig: 307,
        imacr: 299,
        image: 8465,
        imath: 305,
        imped: 437,
        infin: 8734,
        iogon: 303,
        iprod: 10812,
        isinE: 8953,
        isins: 8948,
        isinv: 8712,
        iukcy: 1110,
        jcirc: 309,
        jmath: 567,
        jukcy: 1108,
        kappa: 954,
        lAarr: 8666,
        lBarr: 10510,
        langd: 10641,
        laquo: 171,
        larrb: 8676,
        lbarr: 10508,
        lbbrk: 10098,
        lbrke: 10635,
        lceil: 8968,
        ldquo: 8220,
        lescc: 10920,
        lhard: 8637,
        lharu: 8636,
        lhblk: 9604,
        llarr: 8647,
        lltri: 9722,
        lneqq: 8808,
        lnsim: 8934,
        loang: 10220,
        loarr: 8701,
        lobrk: 10214,
        lopar: 10629,
        lrarr: 8646,
        lrhar: 8651,
        lrtri: 8895,
        lsime: 10893,
        lsimg: 10895,
        lsquo: 8216,
        ltcir: 10873,
        ltdot: 8918,
        ltrie: 8884,
        ltrif: 9666,
        mDDot: 8762,
        mdash: 8212,
        micro: 181,
        minus: 8722,
        mumap: 8888,
        nabla: 8711,
        napos: 329,
        natur: 9838,
        ncong: 8775,
        ndash: 8211,
        neArr: 8663,
        nearr: 8599,
        ngsim: 8821,
        nhArr: 8654,
        nharr: 8622,
        nhpar: 10994,
        nlArr: 8653,
        nlarr: 8602,
        nless: 8814,
        nlsim: 8820,
        nltri: 8938,
        notin: 8713,
        notni: 8716,
        nprec: 8832,
        nrArr: 8655,
        nrarr: 8603,
        nrtri: 8939,
        nsime: 8772,
        nsmid: 8740,
        nspar: 8742,
        nsube: 8840,
        nsucc: 8833,
        nsupe: 8841,
        numsp: 8199,
        nwArr: 8662,
        nwarr: 8598,
        ocirc: 244,
        odash: 8861,
        oelig: 339,
        ofcir: 10687,
        ohbar: 10677,
        olarr: 8634,
        olcir: 10686,
        oline: 8254,
        omacr: 333,
        omega: 969,
        operp: 10681,
        oplus: 8853,
        orarr: 8635,
        order: 8500,
        ovbar: 9021,
        parsl: 11005,
        phone: 9742,
        plusb: 8862,
        pluse: 10866,
        pound: 163,
        prcue: 8828,
        prime: 8242,
        prnap: 10937,
        prsim: 8830,
        quest: 63,
        rAarr: 8667,
        rBarr: 10511,
        radic: 8730,
        rangd: 10642,
        range: 10661,
        raquo: 187,
        rarrb: 8677,
        rarrc: 10547,
        rarrw: 8605,
        ratio: 8758,
        rbarr: 10509,
        rbbrk: 10099,
        rbrke: 10636,
        rceil: 8969,
        rdquo: 8221,
        reals: 8477,
        rhard: 8641,
        rharu: 8640,
        rlarr: 8644,
        rlhar: 8652,
        rnmid: 10990,
        roang: 10221,
        roarr: 8702,
        robrk: 10215,
        ropar: 10630,
        rrarr: 8649,
        rsquo: 8217,
        rtrie: 8885,
        rtrif: 9656,
        sbquo: 8218,
        sccue: 8829,
        scirc: 349,
        scnap: 10938,
        scsim: 8831,
        sdotb: 8865,
        sdote: 10854,
        seArr: 8664,
        searr: 8600,
        setmn: 8726,
        sharp: 9839,
        sigma: 963,
        simeq: 8771,
        simgE: 10912,
        simlE: 10911,
        simne: 8774,
        slarr: 8592,
        smile: 8995,
        sqcap: 8851,
        sqcup: 8852,
        sqsub: 8847,
        sqsup: 8848,
        srarr: 8594,
        starf: 9733,
        strns: 175,
        subnE: 10955,
        subne: 8842,
        supnE: 10956,
        supne: 8843,
        swArr: 8665,
        swarr: 8601,
        szlig: 223,
        theta: 952,
        thkap: 8776,
        thorn: 254,
        tilde: 732,
        times: 215,
        trade: 8482,
        trisb: 10701,
        tshcy: 1115,
        twixt: 8812,
        ubrcy: 1118,
        ucirc: 251,
        udarr: 8645,
        udhar: 10606,
        uharl: 8639,
        uharr: 8638,
        uhblk: 9600,
        ultri: 9720,
        umacr: 363,
        uogon: 371,
        uplus: 8846,
        upsih: 978,
        uring: 367,
        urtri: 9721,
        utdot: 8944,
        utrif: 9652,
        uuarr: 8648,
        vBarv: 10985,
        vDash: 8872,
        varpi: 982,
        vdash: 8866,
        veeeq: 8794,
        vltri: 8882,
        vprop: 8733,
        vrtri: 8883,
        wcirc: 373,
        wedge: 8743,
        xcirc: 9711,
        xdtri: 9661,
        xhArr: 10234,
        xharr: 10231,
        xlArr: 10232,
        xlarr: 10229,
        xodot: 10752,
        xrArr: 10233,
        xrarr: 10230,
        xutri: 9651,
        ycirc: 375,
        Aopf: 120120,
        Ascr: 119964,
        Auml: 196,
        Barv: 10983,
        Beta: 914,
        Bopf: 120121,
        Bscr: 8492,
        CHcy: 1063,
        COPY: 169,
        Cdot: 266,
        Copf: 8450,
        Cscr: 119966,
        DJcy: 1026,
        DScy: 1029,
        DZcy: 1039,
        Darr: 8609,
        Dopf: 120123,
        Dscr: 119967,
        Edot: 278,
        Eopf: 120124,
        Escr: 8496,
        Esim: 10867,
        Euml: 203,
        Fopf: 120125,
        Fscr: 8497,
        GJcy: 1027,
        Gdot: 288,
        Gopf: 120126,
        Gscr: 119970,
        Hopf: 8461,
        Hscr: 8459,
        IEcy: 1045,
        IOcy: 1025,
        Idot: 304,
        Iopf: 120128,
        Iota: 921,
        Iscr: 8464,
        Iuml: 207,
        Jopf: 120129,
        Jscr: 119973,
        KHcy: 1061,
        KJcy: 1036,
        Kopf: 120130,
        Kscr: 119974,
        LJcy: 1033,
        Lang: 10218,
        Larr: 8606,
        Lopf: 120131,
        Lscr: 8466,
        Mopf: 120132,
        Mscr: 8499,
        NJcy: 1034,
        Nopf: 8469,
        Nscr: 119977,
        Oopf: 120134,
        Oscr: 119978,
        Ouml: 214,
        Popf: 8473,
        Pscr: 119979,
        QUOT: 34,
        Qopf: 8474,
        Qscr: 119980,
        Rang: 10219,
        Rarr: 8608,
        Ropf: 8477,
        Rscr: 8475,
        SHcy: 1064,
        Sopf: 120138,
        Sqrt: 8730,
        Sscr: 119982,
        Star: 8902,
        TScy: 1062,
        Topf: 120139,
        Tscr: 119983,
        Uarr: 8607,
        Uopf: 120140,
        Upsi: 978,
        Uscr: 119984,
        Uuml: 220,
        Vbar: 10987,
        Vert: 8214,
        Vopf: 120141,
        Vscr: 119985,
        Wopf: 120142,
        Wscr: 119986,
        Xopf: 120143,
        Xscr: 119987,
        YAcy: 1071,
        YIcy: 1031,
        YUcy: 1070,
        Yopf: 120144,
        Yscr: 119988,
        Yuml: 376,
        ZHcy: 1046,
        Zdot: 379,
        Zeta: 918,
        Zopf: 8484,
        Zscr: 119989,
        andd: 10844,
        andv: 10842,
        ange: 10660,
        aopf: 120146,
        apid: 8779,
        apos: 39,
        ascr: 119990,
        auml: 228,
        bNot: 10989,
        bbrk: 9141,
        beta: 946,
        beth: 8502,
        bnot: 8976,
        bopf: 120147,
        boxH: 9552,
        boxV: 9553,
        boxh: 9472,
        boxv: 9474,
        bscr: 119991,
        bsim: 8765,
        bsol: 92,
        bull: 8226,
        bump: 8782,
        cdot: 267,
        cent: 162,
        chcy: 1095,
        cirE: 10691,
        circ: 710,
        cire: 8791,
        comp: 8705,
        cong: 8773,
        copf: 120148,
        copy: 169,
        cscr: 119992,
        csub: 10959,
        csup: 10960,
        dArr: 8659,
        dHar: 10597,
        darr: 8595,
        dash: 8208,
        diam: 8900,
        djcy: 1106,
        dopf: 120149,
        dscr: 119993,
        dscy: 1109,
        dsol: 10742,
        dtri: 9663,
        dzcy: 1119,
        eDot: 8785,
        ecir: 8790,
        edot: 279,
        emsp: 8195,
        ensp: 8194,
        eopf: 120150,
        epar: 8917,
        epsi: 1013,
        escr: 8495,
        esim: 8770,
        euml: 235,
        euro: 8364,
        excl: 33,
        flat: 9837,
        fnof: 402,
        fopf: 120151,
        fork: 8916,
        fscr: 119995,
        gdot: 289,
        geqq: 8807,
        gjcy: 1107,
        gnap: 10890,
        gneq: 10888,
        gopf: 120152,
        gscr: 8458,
        gsim: 8819,
        gtcc: 10919,
        hArr: 8660,
        half: 189,
        harr: 8596,
        hbar: 8463,
        hopf: 120153,
        hscr: 119997,
        iecy: 1077,
        imof: 8887,
        iocy: 1105,
        iopf: 120154,
        iota: 953,
        iscr: 119998,
        isin: 8712,
        iuml: 239,
        jopf: 120155,
        jscr: 119999,
        khcy: 1093,
        kjcy: 1116,
        kopf: 120156,
        kscr: 120000,
        lArr: 8656,
        lHar: 10594,
        lang: 10216,
        larr: 8592,
        late: 10925,
        lcub: 123,
        ldca: 10550,
        ldsh: 8626,
        leqq: 8806,
        ljcy: 1113,
        lnap: 10889,
        lneq: 10887,
        lopf: 120157,
        lozf: 10731,
        lpar: 40,
        lscr: 120001,
        lsim: 8818,
        lsqb: 91,
        ltcc: 10918,
        ltri: 9667,
        macr: 175,
        male: 9794,
        malt: 10016,
        mlcp: 10971,
        mldr: 8230,
        mopf: 120158,
        mscr: 120002,
        nbsp: 160,
        ncap: 10819,
        ncup: 10818,
        ngeq: 8817,
        ngtr: 8815,
        nisd: 8954,
        njcy: 1114,
        nldr: 8229,
        nleq: 8816,
        nmid: 8740,
        nopf: 120159,
        npar: 8742,
        nscr: 120003,
        nsim: 8769,
        nsub: 8836,
        nsup: 8837,
        ntgl: 8825,
        ntlg: 8824,
        oast: 8859,
        ocir: 8858,
        odiv: 10808,
        odot: 8857,
        ogon: 731,
        oint: 8750,
        omid: 10678,
        oopf: 120160,
        opar: 10679,
        ordf: 170,
        ordm: 186,
        oror: 10838,
        oscr: 8500,
        osol: 8856,
        ouml: 246,
        para: 182,
        part: 8706,
        perp: 8869,
        phiv: 966,
        plus: 43,
        popf: 120161,
        prap: 10935,
        prec: 8826,
        prnE: 10933,
        prod: 8719,
        prop: 8733,
        pscr: 120005,
        qint: 10764,
        qopf: 120162,
        qscr: 120006,
        quot: 34,
        rArr: 8658,
        rHar: 10596,
        race: 10714,
        rang: 10217,
        rarr: 8594,
        rcub: 125,
        rdca: 10551,
        rdsh: 8627,
        real: 8476,
        rect: 9645,
        rhov: 1009,
        ring: 730,
        ropf: 120163,
        rpar: 41,
        rscr: 120007,
        rsqb: 93,
        rtri: 9657,
        scap: 10936,
        scnE: 10934,
        sdot: 8901,
        sect: 167,
        semi: 59,
        sext: 10038,
        shcy: 1096,
        sime: 8771,
        simg: 10910,
        siml: 10909,
        smid: 8739,
        smte: 10924,
        solb: 10692,
        sopf: 120164,
        spar: 8741,
        squf: 9642,
        sscr: 120008,
        star: 9734,
        subE: 10949,
        sube: 8838,
        succ: 8827,
        sung: 9834,
        sup1: 185,
        sup2: 178,
        sup3: 179,
        supE: 10950,
        supe: 8839,
        tbrk: 9140,
        tdot: 8411,
        tint: 8749,
        toea: 10536,
        topf: 120165,
        tosa: 10537,
        trie: 8796,
        tscr: 120009,
        tscy: 1094,
        uArr: 8657,
        uHar: 10595,
        uarr: 8593,
        uopf: 120166,
        upsi: 965,
        uscr: 120010,
        utri: 9653,
        uuml: 252,
        vArr: 8661,
        vBar: 10984,
        varr: 8597,
        vert: 124,
        vopf: 120167,
        vscr: 120011,
        wopf: 120168,
        wscr: 120012,
        xcap: 8898,
        xcup: 8899,
        xmap: 10236,
        xnis: 8955,
        xopf: 120169,
        xscr: 120013,
        xvee: 8897,
        yacy: 1103,
        yicy: 1111,
        yopf: 120170,
        yscr: 120014,
        yucy: 1102,
        yuml: 255,
        zdot: 380,
        zeta: 950,
        zhcy: 1078,
        zopf: 120171,
        zscr: 120015,
        zwnj: 8204,
        AMP: 38,
        Acy: 1040,
        Afr: 120068,
        And: 10835,
        Bcy: 1041,
        Bfr: 120069,
        Cap: 8914,
        Cfr: 8493,
        Chi: 935,
        Cup: 8915,
        Dcy: 1044,
        Del: 8711,
        Dfr: 120071,
        Dot: 168,
        ENG: 330,
        ETH: 208,
        Ecy: 1069,
        Efr: 120072,
        Eta: 919,
        Fcy: 1060,
        Ffr: 120073,
        Gcy: 1043,
        Gfr: 120074,
        Hat: 94,
        Hfr: 8460,
        Icy: 1048,
        Ifr: 8465,
        Int: 8748,
        Jcy: 1049,
        Jfr: 120077,
        Kcy: 1050,
        Kfr: 120078,
        Lcy: 1051,
        Lfr: 120079,
        Lsh: 8624,
        Map: 10501,
        Mcy: 1052,
        Mfr: 120080,
        Ncy: 1053,
        Nfr: 120081,
        Not: 10988,
        Ocy: 1054,
        Ofr: 120082,
        Pcy: 1055,
        Pfr: 120083,
        Phi: 934,
        Psi: 936,
        Qfr: 120084,
        REG: 174,
        Rcy: 1056,
        Rfr: 8476,
        Rho: 929,
        Rsh: 8625,
        Scy: 1057,
        Sfr: 120086,
        Sub: 8912,
        Sum: 8721,
        Sup: 8913,
        Tab: 9,
        Tau: 932,
        Tcy: 1058,
        Tfr: 120087,
        Ucy: 1059,
        Ufr: 120088,
        Vcy: 1042,
        Vee: 8897,
        Vfr: 120089,
        Wfr: 120090,
        Xfr: 120091,
        Ycy: 1067,
        Yfr: 120092,
        Zcy: 1047,
        Zfr: 8488,
        acd: 8767,
        acy: 1072,
        afr: 120094,
        amp: 38,
        and: 8743,
        ang: 8736,
        apE: 10864,
        ape: 8778,
        ast: 42,
        bcy: 1073,
        bfr: 120095,
        bot: 8869,
        cap: 8745,
        cfr: 120096,
        chi: 967,
        cir: 9675,
        cup: 8746,
        dcy: 1076,
        deg: 176,
        dfr: 120097,
        die: 168,
        div: 247,
        dot: 729,
        ecy: 1101,
        efr: 120098,
        egs: 10902,
        ell: 8467,
        els: 10901,
        eng: 331,
        eta: 951,
        eth: 240,
        fcy: 1092,
        ffr: 120099,
        gEl: 10892,
        gap: 10886,
        gcy: 1075,
        gel: 8923,
        geq: 8805,
        ges: 10878,
        gfr: 120100,
        ggg: 8921,
        glE: 10898,
        gla: 10917,
        glj: 10916,
        gnE: 8809,
        gne: 10888,
        hfr: 120101,
        icy: 1080,
        iff: 8660,
        ifr: 120102,
        int: 8747,
        jcy: 1081,
        jfr: 120103,
        kcy: 1082,
        kfr: 120104,
        lEg: 10891,
        lap: 10885,
        lat: 10923,
        lcy: 1083,
        leg: 8922,
        leq: 8804,
        les: 10877,
        lfr: 120105,
        lgE: 10897,
        lnE: 8808,
        lne: 10887,
        loz: 9674,
        lrm: 8206,
        lsh: 8624,
        map: 8614,
        mcy: 1084,
        mfr: 120106,
        mho: 8487,
        mid: 8739,
        nap: 8777,
        ncy: 1085,
        nfr: 120107,
        nge: 8817,
        ngt: 8815,
        nis: 8956,
        niv: 8715,
        nle: 8816,
        nlt: 8814,
        not: 172,
        npr: 8832,
        nsc: 8833,
        num: 35,
        ocy: 1086,
        ofr: 120108,
        ogt: 10689,
        ohm: 8486,
        olt: 10688,
        ord: 10845,
        orv: 10843,
        par: 8741,
        pcy: 1087,
        pfr: 120109,
        phi: 966,
        piv: 982,
        prE: 10931,
        pre: 10927,
        psi: 968,
        qfr: 120110,
        rcy: 1088,
        reg: 174,
        rfr: 120111,
        rho: 961,
        rlm: 8207,
        rsh: 8625,
        scE: 10932,
        sce: 10928,
        scy: 1089,
        sfr: 120112,
        shy: 173,
        sim: 8764,
        smt: 10922,
        sol: 47,
        squ: 9633,
        sub: 8834,
        sum: 8721,
        sup: 8835,
        tau: 964,
        tcy: 1090,
        tfr: 120113,
        top: 8868,
        ucy: 1091,
        ufr: 120114,
        uml: 168,
        vcy: 1074,
        vee: 8744,
        vfr: 120115,
        wfr: 120116,
        xfr: 120117,
        ycy: 1099,
        yen: 165,
        yfr: 120118,
        zcy: 1079,
        zfr: 120119,
        zwj: 8205,
        DD: 8517,
        GT: 62,
        Gg: 8921,
        Gt: 8811,
        Im: 8465,
        LT: 60,
        Ll: 8920,
        Lt: 8810,
        Mu: 924,
        Nu: 925,
        Or: 10836,
        Pi: 928,
        Pr: 10939,
        Re: 8476,
        Sc: 10940,
        Xi: 926,
        ac: 8766,
        af: 8289,
        ap: 8776,
        dd: 8518,
        ee: 8519,
        eg: 10906,
        el: 10905,
        gE: 8807,
        ge: 8805,
        gg: 8811,
        gl: 8823,
        gt: 62,
        ic: 8291,
        ii: 8520,
        in: 8712,
        it: 8290,
        lE: 8806,
        le: 8804,
        lg: 8822,
        ll: 8810,
        lt: 60,
        mp: 8723,
        mu: 956,
        ne: 8800,
        ni: 8715,
        nu: 957,
        oS: 9416,
        or: 8744,
        pi: 960,
        pm: 177,
        pr: 8826,
        rx: 8478,
        sc: 8827,
        wp: 8472,
        wr: 8768,
        xi: 958,
    };

    const windows1252 = [
        8364,
        129,
        8218,
        402,
        8222,
        8230,
        8224,
        8225,
        710,
        8240,
        352,
        8249,
        338,
        141,
        381,
        143,
        144,
        8216,
        8217,
        8220,
        8221,
        8226,
        8211,
        8212,
        732,
        8482,
        353,
        8250,
        339,
        157,
        382,
        376,
    ];
    const entityPattern = new RegExp(`&(#?(?:x[\\w\\d]+|\\d+|${Object.keys(htmlEntities).join('|')}));?`, 'g');
    function decodeCharacterReferences(html) {
        return html.replace(entityPattern, (match, entity) => {
            let code;
            // Handle named entities
            if (entity[0] !== '#') {
                code = htmlEntities[entity];
            }
            else if (entity[1] === 'x') {
                code = parseInt(entity.substring(2), 16);
            }
            else {
                code = parseInt(entity.substring(1), 10);
            }
            if (!code) {
                return match;
            }
            return String.fromCodePoint(validateCode(code));
        });
    }
    const NUL = 0;
    // some code points are verboten. If we were inserting HTML, the browser would replace the illegal
    // code points with alternatives in some cases - since we're bypassing that mechanism, we need
    // to replace them ourselves
    //
    // Source: http://en.wikipedia.org/wiki/Character_encodings_in_HTML#Illegal_characters
    function validateCode(code) {
        // line feed becomes generic whitespace
        if (code === 10) {
            return 32;
        }
        // ASCII range. (Why someone would use HTML entities for ASCII characters I don't know, but...)
        if (code < 128) {
            return code;
        }
        // code points 128-159 are dealt with leniently by browsers, but they're incorrect. We need
        // to correct the mistake or we'll end up with missing € signs and so on
        if (code <= 159) {
            return windows1252[code - 128];
        }
        // basic multilingual plane
        if (code < 55296) {
            return code;
        }
        // UTF-16 surrogate halves
        if (code <= 57343) {
            return NUL;
        }
        // rest of the basic multilingual plane
        if (code <= 65535) {
            return code;
        }
        // supplementary multilingual plane 0x10000 - 0x1ffff
        if (code >= 65536 && code <= 131071) {
            return code;
        }
        // supplementary ideographic plane 0x20000 - 0x2ffff
        if (code >= 131072 && code <= 196607) {
            return code;
        }
        return NUL;
    }

    const voidElementNames = /^(?:area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/;
    function isVoidElementName(name) {
        return voidElementNames.test(name) || name.toLowerCase() === '!doctype';
    }

    const validTagName = /^\!?[a-zA-Z]{1,}:?[a-zA-Z0-9\-]*/;
    const metaTags = new Map([
        ['svelte:window', 'Window'],
        ['svelte:head', 'Head']
    ]);
    const specials = new Map([
        [
            'script',
            {
                read: readScript,
                property: 'js',
            },
        ],
        [
            'style',
            {
                read: readStyle,
                property: 'css',
            },
        ],
    ]);
    const SELF = 'svelte:self';
    const COMPONENT = 'svelte:component';
    // based on http://developers.whatwg.org/syntax.html#syntax-tag-omission
    const disallowedContents = new Map([
        ['li', new Set(['li'])],
        ['dt', new Set(['dt', 'dd'])],
        ['dd', new Set(['dt', 'dd'])],
        [
            'p',
            new Set('address article aside blockquote div dl fieldset footer form h1 h2 h3 h4 h5 h6 header hgroup hr main menu nav ol p pre section table ul'.split(' ')),
        ],
        ['rt', new Set(['rt', 'rp'])],
        ['rp', new Set(['rt', 'rp'])],
        ['optgroup', new Set(['optgroup'])],
        ['option', new Set(['option', 'optgroup'])],
        ['thead', new Set(['tbody', 'tfoot'])],
        ['tbody', new Set(['tbody', 'tfoot'])],
        ['tfoot', new Set(['tbody'])],
        ['tr', new Set(['tr', 'tbody'])],
        ['td', new Set(['td', 'th', 'tr'])],
        ['th', new Set(['td', 'th', 'tr'])],
    ]);
    function parentIsHead(stack) {
        let i = stack.length;
        while (i--) {
            const { type } = stack[i];
            if (type === 'Head')
                return true;
            if (type === 'Element' || type === 'Component')
                return false;
        }
        return false;
    }
    function tag(parser) {
        const start = parser.index++;
        let parent = parser.current();
        if (parser.eat('!--')) {
            const data = parser.readUntil(/-->/);
            parser.eat('-->', true, 'comment was left open, expected -->');
            parser.current().children.push({
                start,
                end: parser.index,
                type: 'Comment',
                data,
            });
            return;
        }
        const isClosingTag = parser.eat('/');
        const name = readTagName(parser);
        if (metaTags.has(name)) {
            const slug = metaTags.get(name).toLowerCase();
            if (isClosingTag) {
                if (name === 'svelte:window' && parser.current().children.length) {
                    parser.error({
                        code: `invalid-window-content`,
                        message: `<${name}> cannot have children`
                    }, parser.current().children[0].start);
                }
            }
            else {
                if (name in parser.metaTags) {
                    parser.error({
                        code: `duplicate-${slug}`,
                        message: `A component can only have one <${name}> tag`
                    }, start);
                }
                if (parser.stack.length > 1) {
                    parser.error({
                        code: `invalid-${slug}-placement`,
                        message: `<${name}> tags cannot be inside elements or blocks`
                    }, start);
                }
                parser.metaTags[name] = true;
            }
        }
        const type = metaTags.has(name)
            ? metaTags.get(name)
            : (/[A-Z]/.test(name[0]) || name === 'svelte:self' || name === 'svelte:component') ? 'Component'
                : name === 'title' && parentIsHead(parser.stack) ? 'Title'
                    : name === 'slot' && !parser.customElement ? 'Slot' : 'Element';
        const element = {
            start,
            end: null,
            type,
            name,
            attributes: [],
            children: [],
        };
        parser.allowWhitespace();
        if (isClosingTag) {
            if (isVoidElementName(name)) {
                parser.error({
                    code: `invalid-void-content`,
                    message: `<${name}> is a void element and cannot have children, or a closing tag`
                }, start);
            }
            parser.eat('>', true);
            // close any elements that don't have their own closing tags, e.g. <div><p></div>
            while (parent.name !== name) {
                if (parent.type !== 'Element')
                    parser.error({
                        code: `invalid-closing-tag`,
                        message: `</${name}> attempted to close an element that was not open`
                    }, start);
                parent.end = start;
                parser.stack.pop();
                parent = parser.current();
            }
            parent.end = parser.index;
            parser.stack.pop();
            return;
        }
        else if (disallowedContents.has(parent.name)) {
            // can this be a child of the parent element, or does it implicitly
            // close it, like `<li>one<li>two`?
            if (disallowedContents.get(parent.name).has(name)) {
                parent.end = start;
                parser.stack.pop();
            }
        }
        if (name === 'slot') {
            let i = parser.stack.length;
            while (i--) {
                const item = parser.stack[i];
                if (item.type === 'EachBlock') {
                    parser.error({
                        code: `invalid-slot-placement`,
                        message: `<slot> cannot be a child of an each-block`
                    }, start);
                }
            }
        }
        const uniqueNames = new Set();
        let attribute;
        while ((attribute = readAttribute(parser, uniqueNames))) {
            if (attribute.type === 'Binding' && !parser.allowBindings) {
                parser.error({
                    code: `binding-disabled`,
                    message: `Two-way binding is disabled`
                }, attribute.start);
            }
            element.attributes.push(attribute);
            parser.allowWhitespace();
        }
        if (name === 'svelte:component') {
            // TODO post v2, treat this just as any other attribute
            const index = element.attributes.findIndex(attr => attr.name === 'this');
            if (!~index) {
                parser.error({
                    code: `missing-component-definition`,
                    message: `<svelte:component> must have a 'this' attribute`
                }, start);
            }
            const definition = element.attributes.splice(index, 1)[0];
            if (definition.value === true || definition.value.length !== 1 || definition.value[0].type === 'Text') {
                parser.error({
                    code: `invalid-component-definition`,
                    message: `invalid component definition`
                }, definition.start);
            }
            element.expression = definition.value[0].expression;
        }
        // special cases – top-level <script> and <style>
        if (specials.has(name) && parser.stack.length === 1) {
            const special = specials.get(name);
            if (parser[special.property]) {
                parser.index = start;
                parser.error({
                    code: `duplicate-${name}`,
                    message: `You can only have one top-level <${name}> tag per component`
                });
            }
            parser.eat('>', true);
            parser[special.property] = special.read(parser, start, element.attributes);
            return;
        }
        parser.current().children.push(element);
        const selfClosing = parser.eat('/') || isVoidElementName(name);
        parser.eat('>', true);
        if (selfClosing) {
            // don't push self-closing elements onto the stack
            element.end = parser.index;
        }
        else if (name === 'textarea') {
            // special case
            element.children = readSequence$1(parser, () => parser.template.slice(parser.index, parser.index + 11) === '</textarea>');
            parser.read(/<\/textarea>/);
            element.end = parser.index;
        }
        else if (name === 'script') {
            // special case
            const start = parser.index;
            const data = parser.readUntil(/<\/script>/);
            const end = parser.index;
            element.children.push({ start, end, type: 'Text', data });
            parser.eat('</script>', true);
            element.end = parser.index;
        }
        else if (name === 'style') {
            // special case
            const start = parser.index;
            const data = parser.readUntil(/<\/style>/);
            const end = parser.index;
            element.children.push({ start, end, type: 'Text', data });
            parser.eat('</style>', true);
        }
        else {
            parser.stack.push(element);
        }
    }
    function readTagName(parser) {
        const start = parser.index;
        if (parser.eat(SELF)) {
            // check we're inside a block, otherwise this
            // will cause infinite recursion
            let i = parser.stack.length;
            let legal = false;
            while (i--) {
                const fragment = parser.stack[i];
                if (fragment.type === 'IfBlock' || fragment.type === 'EachBlock') {
                    legal = true;
                    break;
                }
            }
            if (!legal) {
                parser.error({
                    code: `invalid-self-placement`,
                    message: `<${SELF}> components can only exist inside if-blocks or each-blocks`
                }, start);
            }
            return SELF;
        }
        if (parser.eat(COMPONENT))
            return COMPONENT;
        const name = parser.readUntil(/(\s|\/|>)/);
        if (metaTags.has(name))
            return name;
        if (!validTagName.test(name)) {
            parser.error({
                code: `invalid-tag-name`,
                message: `Expected valid tag name`
            }, start);
        }
        return name;
    }
    function readAttribute(parser, uniqueNames) {
        const start = parser.index;
        if (parser.eat('{')) {
            parser.allowWhitespace();
            if (parser.eat('...')) {
                const expression = readExpression(parser);
                parser.allowWhitespace();
                parser.eat('}', true);
                return {
                    start,
                    end: parser.index,
                    type: 'Spread',
                    expression
                };
            }
            else {
                const valueStart = parser.index;
                const name = parser.readIdentifier();
                parser.allowWhitespace();
                parser.eat('}', true);
                return {
                    start,
                    end: parser.index,
                    type: 'Attribute',
                    name,
                    value: [{
                            start: valueStart,
                            end: valueStart + name.length,
                            type: 'AttributeShorthand',
                            expression: {
                                start: valueStart,
                                end: valueStart + name.length,
                                type: 'Identifier',
                                name
                            }
                        }]
                };
            }
        }
        let name = parser.readUntil(/(\s|=|\/|>)/);
        if (!name)
            return null;
        if (uniqueNames.has(name)) {
            parser.error({
                code: `duplicate-attribute`,
                message: 'Attributes need to be unique'
            }, start);
        }
        uniqueNames.add(name);
        parser.allowWhitespace();
        const directive = readDirective(parser, start, name);
        if (directive)
            return directive;
        let value = parser.eat('=') ? readAttributeValue(parser) : true;
        return {
            start,
            end: parser.index,
            type: 'Attribute',
            name,
            value,
        };
    }
    function readAttributeValue(parser) {
        const quoteMark = parser.eat(`'`) ? `'` : parser.eat(`"`) ? `"` : null;
        const regex = quoteMark === `'`
            ? /'/
            : quoteMark === `"` ? /"/ : /[\s"'=<>\/`]/;
        const value = readSequence$1(parser, () => regex.test(parser.template[parser.index]));
        if (quoteMark)
            parser.index += 1;
        return value;
    }
    function readSequence$1(parser, done) {
        let currentChunk = {
            start: parser.index,
            end: null,
            type: 'Text',
            data: '',
        };
        const chunks = [];
        while (parser.index < parser.template.length) {
            const index = parser.index;
            if (done()) {
                currentChunk.end = parser.index;
                if (currentChunk.data)
                    chunks.push(currentChunk);
                chunks.forEach(chunk => {
                    if (chunk.type === 'Text')
                        chunk.data = decodeCharacterReferences(chunk.data);
                });
                return chunks;
            }
            else if (parser.eat('{')) {
                if (currentChunk.data) {
                    currentChunk.end = index;
                    chunks.push(currentChunk);
                }
                parser.allowWhitespace();
                const expression = readExpression(parser);
                parser.allowWhitespace();
                parser.eat('}', true);
                chunks.push({
                    start: index,
                    end: parser.index,
                    type: 'MustacheTag',
                    expression,
                });
                currentChunk = {
                    start: parser.index,
                    end: null,
                    type: 'Text',
                    data: '',
                };
            }
            else {
                currentChunk.data += parser.template[parser.index++];
            }
        }
        parser.error({
            code: `unexpected-eof`,
            message: `Unexpected end of input`
        });
    }

    function errorOnAssignmentPattern(parser) {
        if (parser.eat('=')) {
            parser.error({
                code: 'invalid-assignment-pattern',
                message: 'Assignment patterns are not supported'
            }, parser.index - 1);
        }
    }
    function readContext(parser) {
        const context = {
            start: parser.index,
            end: null,
            type: null
        };
        if (parser.eat('[')) {
            context.type = 'ArrayPattern';
            context.elements = [];
            do {
                parser.allowWhitespace();
                if (parser.template[parser.index] === ',') {
                    context.elements.push(null);
                }
                else {
                    context.elements.push(readContext(parser));
                    parser.allowWhitespace();
                }
            } while (parser.eat(','));
            errorOnAssignmentPattern(parser);
            parser.eat(']', true);
        }
        else if (parser.eat('{')) {
            context.type = 'ObjectPattern';
            context.properties = [];
            do {
                parser.allowWhitespace();
                const start = parser.index;
                const name = parser.readIdentifier();
                const key = {
                    start,
                    end: parser.index,
                    type: 'Identifier',
                    name
                };
                parser.allowWhitespace();
                const value = parser.eat(':')
                    ? (parser.allowWhitespace(), readContext(parser))
                    : key;
                const property = {
                    start,
                    end: value.end,
                    type: 'Property',
                    key,
                    value
                };
                context.properties.push(property);
                parser.allowWhitespace();
            } while (parser.eat(','));
            errorOnAssignmentPattern(parser);
            parser.eat('}', true);
        }
        else {
            const name = parser.readIdentifier();
            if (name) {
                context.type = 'Identifier';
                context.end = parser.index;
                context.name = name;
            }
            else {
                parser.error({
                    code: 'invalid-context',
                    message: 'Expected a name, array pattern or object pattern'
                });
            }
            errorOnAssignmentPattern(parser);
        }
        return context;
    }

    const whitespace = /[ \t\r\n]/;
    const dimensions = /^(?:offset|client)(?:Width|Height)$/;

    function trimStart(str) {
        let i = 0;
        while (whitespace.test(str[i]))
            i += 1;
        return str.slice(i);
    }
    function trimEnd(str) {
        let i = str.length;
        while (whitespace.test(str[i - 1]))
            i -= 1;
        return str.slice(0, i);
    }

    function trimWhitespace(block, trimBefore, trimAfter) {
        if (!block.children || block.children.length === 0)
            return; // AwaitBlock
        const firstChild = block.children[0];
        const lastChild = block.children[block.children.length - 1];
        if (firstChild.type === 'Text' && trimBefore) {
            firstChild.data = trimStart(firstChild.data);
            if (!firstChild.data)
                block.children.shift();
        }
        if (lastChild.type === 'Text' && trimAfter) {
            lastChild.data = trimEnd(lastChild.data);
            if (!lastChild.data)
                block.children.pop();
        }
        if (block.else) {
            trimWhitespace(block.else, trimBefore, trimAfter);
        }
        if (firstChild.elseif) {
            trimWhitespace(firstChild, trimBefore, trimAfter);
        }
    }
    function mustache(parser) {
        const start = parser.index;
        parser.index += 1;
        parser.allowWhitespace();
        // {{/if}} or {{/each}}
        if (parser.eat('/')) {
            let block = parser.current();
            let expected;
            if (block.type === 'ElseBlock' || block.type === 'PendingBlock' || block.type === 'ThenBlock' || block.type === 'CatchBlock') {
                block.end = start;
                parser.stack.pop();
                block = parser.current();
                expected = 'await';
            }
            if (block.type === 'IfBlock') {
                expected = 'if';
            }
            else if (block.type === 'EachBlock') {
                expected = 'each';
            }
            else if (block.type === 'AwaitBlock') {
                expected = 'await';
            }
            else {
                parser.error({
                    code: `unexpected-block-close`,
                    message: `Unexpected block closing tag`
                });
            }
            parser.eat(expected, true);
            parser.allowWhitespace();
            parser.eat('}', true);
            while (block.elseif) {
                block.end = parser.index;
                parser.stack.pop();
                block = parser.current();
                if (block.else) {
                    block.else.end = start;
                }
            }
            // strip leading/trailing whitespace as necessary
            const charBefore = parser.template[block.start - 1];
            const charAfter = parser.template[parser.index];
            const trimBefore = !charBefore || whitespace.test(charBefore);
            const trimAfter = !charAfter || whitespace.test(charAfter);
            trimWhitespace(block, trimBefore, trimAfter);
            block.end = parser.index;
            parser.stack.pop();
        }
        else if (parser.eat(':elseif')) {
            const block = parser.current();
            if (block.type !== 'IfBlock')
                parser.error({
                    code: `invalid-elseif-placement`,
                    message: 'Cannot have an {{elseif ...}} block outside an {{#if ...}} block'
                });
            parser.requireWhitespace();
            const expression = readExpression(parser);
            parser.allowWhitespace();
            parser.eat('}', true);
            block.else = {
                start: parser.index,
                end: null,
                type: 'ElseBlock',
                children: [
                    {
                        start: parser.index,
                        end: null,
                        type: 'IfBlock',
                        elseif: true,
                        expression,
                        children: [],
                    },
                ],
            };
            parser.stack.push(block.else.children[0]);
        }
        else if (parser.eat(':else')) {
            const block = parser.current();
            if (block.type !== 'IfBlock' && block.type !== 'EachBlock') {
                parser.error({
                    code: `invalid-else-placement`,
                    message: 'Cannot have an {{else}} block outside an {{#if ...}} or {{#each ...}} block'
                });
            }
            parser.allowWhitespace();
            parser.eat('}', true);
            block.else = {
                start: parser.index,
                end: null,
                type: 'ElseBlock',
                children: [],
            };
            parser.stack.push(block.else);
        }
        else if (parser.eat(':then')) {
            // TODO DRY out this and the next section
            const pendingBlock = parser.current();
            if (pendingBlock.type === 'PendingBlock') {
                pendingBlock.end = start;
                parser.stack.pop();
                const awaitBlock = parser.current();
                parser.requireWhitespace();
                awaitBlock.value = parser.readIdentifier();
                parser.allowWhitespace();
                parser.eat('}', true);
                const thenBlock = {
                    start,
                    end: null,
                    type: 'ThenBlock',
                    children: []
                };
                awaitBlock.then = thenBlock;
                parser.stack.push(thenBlock);
            }
        }
        else if (parser.eat(':catch')) {
            const thenBlock = parser.current();
            if (thenBlock.type === 'ThenBlock') {
                thenBlock.end = start;
                parser.stack.pop();
                const awaitBlock = parser.current();
                parser.requireWhitespace();
                awaitBlock.error = parser.readIdentifier();
                parser.allowWhitespace();
                parser.eat('}', true);
                const catchBlock = {
                    start,
                    end: null,
                    type: 'CatchBlock',
                    children: []
                };
                awaitBlock.catch = catchBlock;
                parser.stack.push(catchBlock);
            }
        }
        else if (parser.eat('#')) {
            // {{#if foo}} or {{#each foo}}
            let type;
            if (parser.eat('if')) {
                type = 'IfBlock';
            }
            else if (parser.eat('each')) {
                type = 'EachBlock';
            }
            else if (parser.eat('await')) {
                type = 'AwaitBlock';
            }
            else {
                parser.error({
                    code: `expected-block-type`,
                    message: `Expected if, each or await`
                });
            }
            parser.requireWhitespace();
            const expression = readExpression(parser);
            const block = type === 'AwaitBlock' ?
                {
                    start,
                    end: null,
                    type,
                    expression,
                    value: null,
                    error: null,
                    pending: {
                        start: null,
                        end: null,
                        type: 'PendingBlock',
                        children: []
                    },
                    then: {
                        start: null,
                        end: null,
                        type: 'ThenBlock',
                        children: []
                    },
                    catch: {
                        start: null,
                        end: null,
                        type: 'CatchBlock',
                        children: []
                    },
                } :
                {
                    start,
                    end: null,
                    type,
                    expression,
                    children: [],
                };
            parser.allowWhitespace();
            // {{#each}} blocks must declare a context – {{#each list as item}}
            if (type === 'EachBlock') {
                parser.eat('as', true);
                parser.requireWhitespace();
                block.context = readContext(parser);
                parser.allowWhitespace();
                if (parser.eat(',')) {
                    parser.allowWhitespace();
                    block.index = parser.readIdentifier();
                    if (!block.index)
                        parser.error({
                            code: `expected-name`,
                            message: `Expected name`
                        });
                    parser.allowWhitespace();
                }
                if (parser.eat('(')) {
                    parser.allowWhitespace();
                    block.key = readExpression(parser);
                    parser.allowWhitespace();
                    parser.eat(')', true);
                    parser.allowWhitespace();
                }
                else if (parser.eat('@')) {
                    block.key = parser.readIdentifier();
                    if (!block.key)
                        parser.error({
                            code: `expected-name`,
                            message: `Expected name`
                        });
                    parser.allowWhitespace();
                }
            }
            let awaitBlockShorthand = type === 'AwaitBlock' && parser.eat('then');
            if (awaitBlockShorthand) {
                parser.requireWhitespace();
                block.value = parser.readIdentifier();
                parser.allowWhitespace();
            }
            parser.eat('}', true);
            parser.current().children.push(block);
            parser.stack.push(block);
            if (type === 'AwaitBlock') {
                const childBlock = awaitBlockShorthand ? block.then : block.pending;
                childBlock.start = parser.index;
                parser.stack.push(childBlock);
            }
        }
        else if (parser.eat('@html')) {
            // {{{raw}}} mustache
            const expression = readExpression(parser);
            parser.allowWhitespace();
            parser.eat('}', true);
            parser.current().children.push({
                start,
                end: parser.index,
                type: 'RawMustacheTag',
                expression,
            });
        }
        else {
            const expression = readExpression(parser);
            parser.allowWhitespace();
            parser.eat('}', true);
            parser.current().children.push({
                start,
                end: parser.index,
                type: 'MustacheTag',
                expression,
            });
        }
    }

    function text(parser) {
        const start = parser.index;
        let data = '';
        while (parser.index < parser.template.length &&
            !parser.match('<') &&
            !parser.match('{')) {
            data += parser.template[parser.index++];
        }
        parser.current().children.push({
            start,
            end: parser.index,
            type: 'Text',
            data: decodeCharacterReferences(data),
        });
    }

    function fragment(parser) {
        if (parser.match('<')) {
            return tag;
        }
        if (parser.match('{')) {
            return mustache;
        }
        return text;
    }

    const reservedNames = new Set([
        'arguments',
        'await',
        'break',
        'case',
        'catch',
        'class',
        'const',
        'continue',
        'debugger',
        'default',
        'delete',
        'do',
        'else',
        'enum',
        'eval',
        'export',
        'extends',
        'false',
        'finally',
        'for',
        'function',
        'if',
        'implements',
        'import',
        'in',
        'instanceof',
        'interface',
        'let',
        'new',
        'null',
        'package',
        'private',
        'protected',
        'public',
        'return',
        'static',
        'super',
        'switch',
        'this',
        'throw',
        'true',
        'try',
        'typeof',
        'var',
        'void',
        'while',
        'with',
        'yield',
    ]);

    // Adapted from https://github.com/acornjs/acorn/blob/6584815dca7440e00de841d1dad152302fdd7ca5/src/tokenize.js
    // Reproduced under MIT License https://github.com/acornjs/acorn/blob/master/LICENSE
    function fullCharCodeAt(str, i) {
        let code = str.charCodeAt(i);
        if (code <= 0xd7ff || code >= 0xe000)
            return code;
        let next = str.charCodeAt(i + 1);
        return (code << 10) + next - 0x35fdc00;
    }

    function getLocator(source, options) {
        if (options === void 0) { options = {}; }
        var offsetLine = options.offsetLine || 0;
        var offsetColumn = options.offsetColumn || 0;
        var originalLines = source.split('\n');
        var start = 0;
        var lineRanges = originalLines.map(function (line, i) {
            var end = start + line.length + 1;
            var range = { start: start, end: end, line: i };
            start = end;
            return range;
        });
        var i = 0;
        function rangeContains(range, index) {
            return range.start <= index && index < range.end;
        }
        function getLocation(range, index) {
            return { line: offsetLine + range.line, column: offsetColumn + index - range.start, character: index };
        }
        function locate(search, startIndex) {
            if (typeof search === 'string') {
                search = source.indexOf(search, startIndex || 0);
            }
            var range = lineRanges[i];
            var d = search >= range.end ? 1 : -1;
            while (range) {
                if (rangeContains(range, search))
                    return getLocation(range, search);
                i += d;
                range = lineRanges[i];
            }
        }
        return locate;
    }
    function locate(source, search, options) {
        if (typeof options === 'number') {
            throw new Error('locate takes a { startIndex, offsetLine, offsetColumn } object as the third argument');
        }
        return getLocator(source, options)(search, options && options.startIndex);
    }

    function tabsToSpaces(str) {
        return str.replace(/^\t+/, match => match.split('\t').join('  '));
    }
    function getCodeFrame(source, line, column) {
        const lines = source.split('\n');
        const frameStart = Math.max(0, line - 2);
        const frameEnd = Math.min(line + 3, lines.length);
        const digits = String(frameEnd + 1).length;
        return lines
            .slice(frameStart, frameEnd)
            .map((str, i) => {
            const isErrorLine = frameStart + i === line;
            let lineNum = String(i + frameStart + 1);
            while (lineNum.length < digits)
                lineNum = ` ${lineNum}`;
            if (isErrorLine) {
                const indicator = repeat(' ', digits + 2 + tabsToSpaces(str.slice(0, column)).length) + '^';
                return `${lineNum}: ${tabsToSpaces(str)}\n${indicator}`;
            }
            return `${lineNum}: ${tabsToSpaces(str)}`;
        })
            .join('\n');
    }

    class CompileError extends Error {
        toString() {
            return `${this.message} (${this.start.line}:${this.start.column})\n${this.frame}`;
        }
    }
    function error$2(message, props) {
        const error = new CompileError(message);
        error.name = props.name;
        const start = locate(props.source, props.start, { offsetLine: 1 });
        const end = locate(props.source, props.end || props.start, { offsetLine: 1 });
        error.code = props.code;
        error.start = start;
        error.end = end;
        error.pos = props.start;
        error.filename = props.filename;
        error.frame = getCodeFrame(props.source, start.line - 1, start.column);
        throw error;
    }

    class Parser$1 {
        constructor(template, options) {
            if (typeof template !== 'string') {
                throw new TypeError('Template must be a string');
            }
            this.template = template.replace(/\s+$/, '');
            this.filename = options.filename;
            this.customElement = options.customElement;
            this.allowBindings = options.bind !== false;
            this.index = 0;
            this.stack = [];
            this.metaTags = {};
            this.html = {
                start: null,
                end: null,
                type: 'Fragment',
                children: [],
            };
            this.css = null;
            this.js = null;
            this.stack.push(this.html);
            let state = fragment;
            while (this.index < this.template.length) {
                state = state(this) || fragment;
            }
            if (this.stack.length > 1) {
                const current = this.current();
                const type = current.type === 'Element' ? `<${current.name}>` : 'Block';
                const slug = current.type === 'Element' ? 'element' : 'block';
                this.error({
                    code: `unclosed-${slug}`,
                    message: `${type} was left open`
                }, current.start);
            }
            if (state !== fragment) {
                this.error({
                    code: `unexpected-eof`,
                    message: 'Unexpected end of input'
                });
            }
            if (this.html.children.length) {
                let start = this.html.children[0] && this.html.children[0].start;
                while (/\s/.test(template[start]))
                    start += 1;
                let end = this.html.children[this.html.children.length - 1] && this.html.children[this.html.children.length - 1].end;
                while (/\s/.test(template[end - 1]))
                    end -= 1;
                this.html.start = start;
                this.html.end = end;
            }
            else {
                this.html.start = this.html.end = null;
            }
        }
        current() {
            return this.stack[this.stack.length - 1];
        }
        acornError(err) {
            this.error({
                code: `parse-error`,
                message: err.message.replace(/ \(\d+:\d+\)$/, '')
            }, err.pos);
        }
        error({ code, message }, index = this.index) {
            error$2(message, {
                name: 'ParseError',
                code,
                source: this.template,
                start: index,
                filename: this.filename
            });
        }
        eat(str, required, message) {
            if (this.match(str)) {
                this.index += str.length;
                return true;
            }
            if (required) {
                this.error({
                    code: `unexpected-${this.index === this.template.length ? 'eof' : 'token'}`,
                    message: message || `Expected ${str}`
                });
            }
            return false;
        }
        match(str) {
            return this.template.slice(this.index, this.index + str.length) === str;
        }
        allowWhitespace() {
            while (this.index < this.template.length &&
                whitespace.test(this.template[this.index])) {
                this.index++;
            }
        }
        read(pattern) {
            const match = pattern.exec(this.template.slice(this.index));
            if (!match || match.index !== 0)
                return null;
            this.index += match[0].length;
            return match[0];
        }
        readIdentifier() {
            const start = this.index;
            let i = this.index;
            const code = fullCharCodeAt(this.template, i);
            if (!isIdentifierStart(code, true))
                return null;
            i += code <= 0xffff ? 1 : 2;
            while (i < this.template.length) {
                const code = fullCharCodeAt(this.template, i);
                if (!isIdentifierChar(code, true))
                    break;
                i += code <= 0xffff ? 1 : 2;
            }
            const identifier = this.template.slice(this.index, this.index = i);
            if (reservedNames.has(identifier)) {
                this.error({
                    code: `unexpected-reserved-word`,
                    message: `'${identifier}' is a reserved word in JavaScript and cannot be used here`
                }, start);
            }
            return identifier;
        }
        readUntil(pattern) {
            if (this.index >= this.template.length)
                this.error({
                    code: `unexpected-eof`,
                    message: 'Unexpected end of input'
                });
            const start = this.index;
            const match = pattern.exec(this.template.slice(start));
            if (match) {
                this.index = start + match.index;
                return this.template.slice(start, this.index);
            }
            this.index = this.template.length;
            return this.template.slice(start);
        }
        remaining() {
            return this.template.slice(this.index);
        }
        requireWhitespace() {
            if (!whitespace.test(this.template[this.index])) {
                this.error({
                    code: `missing-whitespace`,
                    message: `Expected whitespace`
                });
            }
            this.allowWhitespace();
        }
    }
    function parse$1(template, options = {}) {
        const parser = new Parser$1(template, options);
        return {
            html: parser.html,
            css: parser.css,
            js: parser.js,
        };
    }

    const disallowed = new Set(['Literal', 'ObjectExpression', 'ArrayExpression']);
    function data$1(validator, prop) {
        while (prop.type === 'ParenthesizedExpression')
            prop = prop.expression;
        if (disallowed.has(prop.value.type)) {
            validator.error(prop.value, {
                code: `invalid-data-property`,
                message: `'data' must be a function`
            });
        }
    }

    function getMethodName(node) {
        if (node.type === 'Identifier')
            return node.name;
        if (node.type === 'Literal')
            return String(node.value);
    }

    function checkForDupes(validator, properties) {
        const seen = new Set();
        properties.forEach(prop => {
            const name = getMethodName(prop.key);
            if (seen.has(name)) {
                validator.error(prop, {
                    code: `duplicate-property`,
                    message: `Duplicate property '${name}'`
                });
            }
            seen.add(name);
        });
    }

    function checkForComputedKeys(validator, properties) {
        properties.forEach(prop => {
            if (prop.key.computed) {
                validator.error(prop, {
                    code: `computed-key`,
                    message: `Cannot use computed keys`
                });
            }
        });
    }

    function actions(validator, prop) {
        if (prop.value.type !== 'ObjectExpression') {
            validator.error(prop, {
                code: `invalid-actions`,
                message: `The 'actions' property must be an object literal`
            });
        }
        checkForDupes(validator, prop.value.properties);
        checkForComputedKeys(validator, prop.value.properties);
    }

    function transitions(validator, prop) {
        if (prop.value.type !== 'ObjectExpression') {
            validator.error(prop, {
                code: `invalid-transitions-property`,
                message: `The 'transitions' property must be an object literal`
            });
        }
        checkForDupes(validator, prop.value.properties);
        checkForComputedKeys(validator, prop.value.properties);
        prop.value.properties.forEach(() => {
            // TODO probably some validation that can happen here...
            // checking for use of `this` etc?
        });
    }

    function isValidIdentifier(str) {
        let i = 0;
        while (i < str.length) {
            const code = fullCharCodeAt(str, i);
            if (!(i === 0 ? isIdentifierStart : isIdentifierChar)(code, true))
                return false;
            i += code <= 0xffff ? 1 : 2;
        }
        return true;
    }

    function walkThroughTopFunctionScope(body, callback) {
        let lexicalDepth = 0;
        walk(body, {
            enter(node) {
                if (/^Function/.test(node.type)) {
                    lexicalDepth += 1;
                }
                else if (lexicalDepth === 0) {
                    callback(node);
                }
            },
            leave(node) {
                if (/^Function/.test(node.type)) {
                    lexicalDepth -= 1;
                }
            },
        });
    }

    function isThisGetCallExpression(node) {
        return node.type === 'CallExpression' &&
            node.callee.type === 'MemberExpression' &&
            node.callee.object.type === 'ThisExpression' &&
            node.callee.property.name === 'get';
    }

    const isFunctionExpression = new Set([
        'FunctionExpression',
        'ArrowFunctionExpression',
    ]);
    function computed(validator, prop) {
        if (prop.value.type !== 'ObjectExpression') {
            validator.error(prop, {
                code: `invalid-computed-property`,
                message: `The 'computed' property must be an object literal`
            });
        }
        checkForDupes(validator, prop.value.properties);
        checkForComputedKeys(validator, prop.value.properties);
        prop.value.properties.forEach((computation) => {
            const name = getMethodName(computation.key);
            if (!isValidIdentifier(name)) {
                const suggestion = name.replace(/[^_$a-z0-9]/ig, '_').replace(/^\d/, '_$&');
                validator.error(computation.key, {
                    code: `invalid-computed-name`,
                    message: `Computed property name '${name}' is invalid — must be a valid identifier such as ${suggestion}`
                });
            }
            if (reservedNames.has(name)) {
                validator.error(computation.key, {
                    code: `invalid-computed-name`,
                    message: `Computed property name '${name}' is invalid — cannot be a JavaScript reserved word`
                });
            }
            if (!isFunctionExpression.has(computation.value.type)) {
                validator.error(computation.value, {
                    code: `invalid-computed-value`,
                    message: `Computed properties can be function expressions or arrow function expressions`
                });
            }
            const { body, params } = computation.value;
            walkThroughTopFunctionScope(body, (node) => {
                if (isThisGetCallExpression(node) && !node.callee.property.computed) {
                    validator.error(node, {
                        code: `impure-computed`,
                        message: `Cannot use this.get(...) — values must be passed into the function as arguments`
                    });
                }
                if (node.type === 'ThisExpression') {
                    validator.error(node, {
                        code: `impure-computed`,
                        message: `Computed properties should be pure functions — they do not have access to the component instance and cannot use 'this'. Did you mean to put this in 'methods'?`
                    });
                }
            });
            if (params.length === 0) {
                validator.error(computation.value, {
                    code: `impure-computed`,
                    message: `A computed value must depend on at least one property`
                });
            }
            if (params.length > 1) {
                validator.error(computation.value, {
                    code: `invalid-computed-arguments`,
                    message: `Computed properties must take a single argument`
                });
            }
        });
    }

    function isReference(node, parent) {
        if (node.type === 'MemberExpression') {
            return !node.computed && isReference(node.object, node);
        }
        if (node.type === 'Identifier') {
            // the only time we could have an identifier node without a parent is
            // if it's the entire body of a function without a block statement –
            // i.e. an arrow function expression like `a => a`
            if (!parent)
                return true;
            // TODO is this right?
            if (parent.type === 'MemberExpression' || parent.type === 'MethodDefinition') {
                return parent.computed || node === parent.object;
            }
            // disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
            if (parent.type === 'Property')
                return parent.computed || node === parent.value;
            // disregard the `bar` in `export { foo as bar }`
            if (parent.type === 'ExportSpecifier' && node !== parent.local)
                return false;
            return true;
        }
        return false;
    }

    function usesThisOrArguments(node) {
        let result = false;
        walk(node, {
            enter(node, parent) {
                if (result ||
                    node.type === 'FunctionExpression' ||
                    node.type === 'FunctionDeclaration') {
                    return this.skip();
                }
                if (node.type === 'ThisExpression') {
                    result = true;
                }
                if (node.type === 'Identifier' &&
                    isReference(node, parent) &&
                    node.name === 'arguments') {
                    result = true;
                }
            },
        });
        return result;
    }

    function oncreate(validator, prop) {
        if (prop.value.type === 'ArrowFunctionExpression') {
            if (usesThisOrArguments(prop.value.body)) {
                validator.error(prop, {
                    code: `invalid-oncreate-property`,
                    message: `'oncreate' should be a function expression, not an arrow function expression`
                });
            }
        }
    }

    function ondestroy(validator, prop) {
        if (prop.value.type === 'ArrowFunctionExpression') {
            if (usesThisOrArguments(prop.value.body)) {
                validator.error(prop, {
                    code: `invalid-ondestroy-property`,
                    message: `'ondestroy' should be a function expression, not an arrow function expression`
                });
            }
        }
    }

    function onstate(validator, prop) {
        if (prop.value.type === 'ArrowFunctionExpression') {
            if (usesThisOrArguments(prop.value.body)) {
                validator.error(prop, {
                    code: `invalid-onstate-property`,
                    message: `'onstate' should be a function expression, not an arrow function expression`
                });
            }
        }
    }

    function onupdate(validator, prop) {
        if (prop.value.type === 'ArrowFunctionExpression') {
            if (usesThisOrArguments(prop.value.body)) {
                validator.error(prop, {
                    code: `invalid-onupdate-property`,
                    message: `'onupdate' should be a function expression, not an arrow function expression`
                });
            }
        }
    }

    function onrender(validator, prop) {
        validator.warn(prop, {
            code: `deprecated-onrender`,
            message: `'onrender' has been deprecated in favour of 'oncreate', and will cause an error in Svelte 2.x`
        });
        oncreate(validator, prop);
    }

    function onteardown(validator, prop) {
        validator.warn(prop, {
            code: `deprecated-onteardown`,
            message: `'onteardown' has been deprecated in favour of 'ondestroy', and will cause an error in Svelte 2.x`
        });
        ondestroy(validator, prop);
    }

    function helpers(validator, prop) {
        if (prop.value.type !== 'ObjectExpression') {
            validator.error(prop, {
                code: `invalid-helpers-property`,
                message: `The 'helpers' property must be an object literal`
            });
        }
        checkForDupes(validator, prop.value.properties);
        checkForComputedKeys(validator, prop.value.properties);
        prop.value.properties.forEach((prop) => {
            if (!/FunctionExpression/.test(prop.value.type))
                return;
            let usesArguments = false;
            walkThroughTopFunctionScope(prop.value.body, (node) => {
                if (isThisGetCallExpression(node) && !node.callee.property.computed) {
                    validator.error(node, {
                        code: `impure-helper`,
                        message: `Cannot use this.get(...) — values must be passed into the helper function as arguments`
                    });
                }
                if (node.type === 'ThisExpression') {
                    validator.error(node, {
                        code: `impure-helper`,
                        message: `Helpers should be pure functions — they do not have access to the component instance and cannot use 'this'. Did you mean to put this in 'methods'?`
                    });
                }
                else if (node.type === 'Identifier' && node.name === 'arguments') {
                    usesArguments = true;
                }
            });
            if (prop.value.params.length === 0 && !usesArguments) {
                validator.warn(prop, {
                    code: `impure-helper`,
                    message: `Helpers should be pure functions, with at least one argument`
                });
            }
        });
    }

    function checkForAccessors(validator, properties, label) {
        properties.forEach(prop => {
            if (prop.kind !== 'init') {
                validator.error(prop, {
                    code: `illegal-accessor`,
                    message: `${label} cannot use getters and setters`
                });
            }
        });
    }

    const builtin = new Set(['set', 'get', 'on', 'fire', 'destroy']);
    function methods(validator, prop) {
        if (prop.value.type !== 'ObjectExpression') {
            validator.error(prop, {
                code: `invalid-methods-property`,
                message: `The 'methods' property must be an object literal`
            });
        }
        checkForAccessors(validator, prop.value.properties, 'Methods');
        checkForDupes(validator, prop.value.properties);
        checkForComputedKeys(validator, prop.value.properties);
        prop.value.properties.forEach((prop) => {
            const name = getMethodName(prop.key);
            if (builtin.has(name)) {
                validator.error(prop, {
                    code: `invalid-method-name`,
                    message: `Cannot overwrite built-in method '${name}'`
                });
            }
            if (prop.value.type === 'ArrowFunctionExpression') {
                if (usesThisOrArguments(prop.value.body)) {
                    validator.error(prop, {
                        code: `invalid-method-value`,
                        message: `Method '${prop.key.name}' should be a function expression, not an arrow function expression`
                    });
                }
            }
        });
    }

    function components(validator, prop) {
        if (prop.value.type !== 'ObjectExpression') {
            validator.error(prop, {
                code: `invalid-components-property`,
                message: `The 'components' property must be an object literal`
            });
        }
        checkForDupes(validator, prop.value.properties);
        checkForComputedKeys(validator, prop.value.properties);
        prop.value.properties.forEach((component) => {
            const name = getMethodName(component.key);
            if (name === 'state') {
                // TODO is this still true?
                validator.error(component, {
                    code: `invalid-name`,
                    message: `Component constructors cannot be called 'state' due to technical limitations`
                });
            }
            if (!/^[A-Z]/.test(name)) {
                validator.error(component, {
                    code: `component-lowercase`,
                    message: `Component names must be capitalised`
                });
            }
        });
    }

    function events(validator, prop) {
        if (prop.value.type !== 'ObjectExpression') {
            validator.error(prop, {
                code: `invalid-events-property`,
                message: `The 'events' property must be an object literal`
            });
        }
        checkForDupes(validator, prop.value.properties);
        checkForComputedKeys(validator, prop.value.properties);
    }

    const html = 'http://www.w3.org/1999/xhtml';
    const mathml = 'http://www.w3.org/1998/Math/MathML';
    const svg = 'http://www.w3.org/2000/svg';
    const xlink = 'http://www.w3.org/1999/xlink';
    const xml = 'http://www.w3.org/XML/1998/namespace';
    const xmlns = 'http://www.w3.org/2000/xmlns';
    const validNamespaces = [
        'html',
        'mathml',
        'svg',
        'xlink',
        'xml',
        'xmlns',
        html,
        mathml,
        svg,
        xlink,
        xml,
        xmlns,
    ];
    const namespaces = { html, mathml, svg, xlink, xml, xmlns };

    function nodeToString(node) {
        if (node.type === 'Literal' && typeof node.value === 'string') {
            return node.value;
        }
        else if (node.type === 'TemplateLiteral'
            && node.quasis.length === 1
            && node.expressions.length === 0) {
            return node.quasis[0].value.raw;
        }
    }

    // adapted from https://github.com/Glench/fuzzyset.js/blob/master/lib/fuzzyset.js
    // BSD Licensed
    const GRAM_SIZE_LOWER = 2;
    const GRAM_SIZE_UPPER = 3;
    // return an edit distance from 0 to 1
    function _distance(str1, str2) {
        if (str1 === null && str2 === null)
            throw 'Trying to compare two null values';
        if (str1 === null || str2 === null)
            return 0;
        str1 = String(str1);
        str2 = String(str2);
        const distance = levenshtein(str1, str2);
        if (str1.length > str2.length) {
            return 1 - distance / str1.length;
        }
        else {
            return 1 - distance / str2.length;
        }
    }
    // helper functions
    function levenshtein(str1, str2) {
        const current = [];
        let prev;
        let value;
        for (let i = 0; i <= str2.length; i++) {
            for (let j = 0; j <= str1.length; j++) {
                if (i && j) {
                    if (str1.charAt(j - 1) === str2.charAt(i - 1)) {
                        value = prev;
                    }
                    else {
                        value = Math.min(current[j], current[j - 1], prev) + 1;
                    }
                }
                else {
                    value = i + j;
                }
                prev = current[j];
                current[j] = value;
            }
        }
        return current.pop();
    }
    const _nonWordRe = /[^\w, ]+/;
    function _iterateGrams(value, gramSize) {
        gramSize = gramSize || 2;
        const simplified = '-' + value.toLowerCase().replace(_nonWordRe, '') + '-';
        const lenDiff = gramSize - simplified.length;
        const results = [];
        if (lenDiff > 0) {
            for (let i = 0; i < lenDiff; ++i) {
                value += '-';
            }
        }
        for (let i = 0; i < simplified.length - gramSize + 1; ++i) {
            results.push(simplified.slice(i, i + gramSize));
        }
        return results;
    }
    function _gramCounter(value, gramSize) {
        // return an object where key=gram, value=number of occurrences
        gramSize = gramSize || 2;
        const result = {};
        const grams = _iterateGrams(value, gramSize);
        let i = 0;
        for (i; i < grams.length; ++i) {
            if (grams[i] in result) {
                result[grams[i]] += 1;
            }
            else {
                result[grams[i]] = 1;
            }
        }
        return result;
    }
    function sortDescending(a, b) {
        return b[0] - a[0];
    }
    class FuzzySet {
        constructor(arr) {
            // define all the object functions and attributes
            this.exactSet = {};
            this.matchDict = {};
            this.items = {};
            // initialization
            for (let i = GRAM_SIZE_LOWER; i < GRAM_SIZE_UPPER + 1; ++i) {
                this.items[i] = [];
            }
            // add all the items to the set
            for (let i = 0; i < arr.length; ++i) {
                this.add(arr[i]);
            }
        }
        add(value) {
            const normalizedValue = value.toLowerCase();
            if (normalizedValue in this.exactSet) {
                return false;
            }
            let i = GRAM_SIZE_LOWER;
            for (i; i < GRAM_SIZE_UPPER + 1; ++i) {
                this._add(value, i);
            }
        }
        _add(value, gramSize) {
            const normalizedValue = value.toLowerCase();
            const items = this.items[gramSize] || [];
            const index = items.length;
            items.push(0);
            const gramCounts = _gramCounter(normalizedValue, gramSize);
            let sumOfSquareGramCounts = 0;
            let gram;
            let gramCount;
            for (gram in gramCounts) {
                gramCount = gramCounts[gram];
                sumOfSquareGramCounts += Math.pow(gramCount, 2);
                if (gram in this.matchDict) {
                    this.matchDict[gram].push([index, gramCount]);
                }
                else {
                    this.matchDict[gram] = [[index, gramCount]];
                }
            }
            const vectorNormal = Math.sqrt(sumOfSquareGramCounts);
            items[index] = [vectorNormal, normalizedValue];
            this.items[gramSize] = items;
            this.exactSet[normalizedValue] = value;
        }
        ;
        get(value) {
            const normalizedValue = value.toLowerCase();
            const result = this.exactSet[normalizedValue];
            if (result) {
                return [[1, result]];
            }
            let results = [];
            // start with high gram size and if there are no results, go to lower gram sizes
            for (let gramSize = GRAM_SIZE_UPPER; gramSize >= GRAM_SIZE_LOWER; --gramSize) {
                results = this.__get(value, gramSize);
                if (results) {
                    return results;
                }
            }
            return null;
        }
        __get(value, gramSize) {
            const normalizedValue = value.toLowerCase();
            const matches = {};
            const gramCounts = _gramCounter(normalizedValue, gramSize);
            const items = this.items[gramSize];
            let sumOfSquareGramCounts = 0;
            let gram;
            let gramCount;
            let i;
            let index;
            let otherGramCount;
            for (gram in gramCounts) {
                gramCount = gramCounts[gram];
                sumOfSquareGramCounts += Math.pow(gramCount, 2);
                if (gram in this.matchDict) {
                    for (i = 0; i < this.matchDict[gram].length; ++i) {
                        index = this.matchDict[gram][i][0];
                        otherGramCount = this.matchDict[gram][i][1];
                        if (index in matches) {
                            matches[index] += gramCount * otherGramCount;
                        }
                        else {
                            matches[index] = gramCount * otherGramCount;
                        }
                    }
                }
            }
            const vectorNormal = Math.sqrt(sumOfSquareGramCounts);
            let results = [];
            let matchScore;
            // build a results list of [score, str]
            for (const matchIndex in matches) {
                matchScore = matches[matchIndex];
                results.push([
                    matchScore / (vectorNormal * items[matchIndex][0]),
                    items[matchIndex][1],
                ]);
            }
            results.sort(sortDescending);
            let newResults = [];
            const endIndex = Math.min(50, results.length);
            // truncate somewhat arbitrarily to 50
            for (let i = 0; i < endIndex; ++i) {
                newResults.push([
                    _distance(results[i][1], normalizedValue),
                    results[i][1],
                ]);
            }
            results = newResults;
            results.sort(sortDescending);
            newResults = [];
            for (let i = 0; i < results.length; ++i) {
                if (results[i][0] == results[0][0]) {
                    newResults.push([results[i][0], this.exactSet[results[i][1]]]);
                }
            }
            return newResults;
        }
        ;
    }

    function fuzzymatch(name, names) {
        const set = new FuzzySet(names);
        const matches = set.get(name);
        return matches && matches[0] && matches[0][0] > 0.7 ? matches[0][1] : null;
    }

    const valid = new Set(validNamespaces);
    function namespace(validator, prop) {
        const ns = nodeToString(prop.value);
        if (typeof ns !== 'string') {
            validator.error(prop, {
                code: `invalid-namespace-property`,
                message: `The 'namespace' property must be a string literal representing a valid namespace`
            });
        }
        if (!valid.has(ns)) {
            const match = fuzzymatch(ns, validNamespaces);
            if (match) {
                validator.error(prop, {
                    code: `invalid-namespace-property`,
                    message: `Invalid namespace '${ns}' (did you mean '${match}'?)`
                });
            }
            else {
                validator.error(prop, {
                    code: `invalid-namespace-property`,
                    message: `Invalid namespace '${ns}'`
                });
            }
        }
    }

    function preload(validator, prop) {
        // not sure there's anything we need to check here...
    }

    function props(validator, prop) {
        if (prop.value.type !== 'ArrayExpression') {
            validator.error(prop.value, {
                code: `invalid-props-property`,
                message: `'props' must be an array expression, if specified`
            });
        }
        prop.value.elements.forEach((element) => {
            if (typeof nodeToString(element) !== 'string') {
                validator.error(element, {
                    code: `invalid-props-property`,
                    message: `'props' must be an array of string literals`
                });
            }
        });
    }

    function tag$1(validator, prop) {
        const tag = nodeToString(prop.value);
        if (typeof tag !== 'string') {
            validator.error(prop.value, {
                code: `invalid-tag-property`,
                message: `'tag' must be a string literal`
            });
        }
        if (!/^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/.test(tag)) {
            validator.error(prop.value, {
                code: `invalid-tag-property`,
                message: `tag name must be two or more words joined by the '-' character`
            });
        }
    }

    function transitions$1(validator, prop) {
        if (prop.value.type !== 'ObjectExpression') {
            validator.error(prop, {
                code: `invalid-transitions-property`,
                message: `The 'transitions' property must be an object literal`
            });
        }
        checkForDupes(validator, prop.value.properties);
        checkForComputedKeys(validator, prop.value.properties);
        prop.value.properties.forEach(() => {
            // TODO probably some validation that can happen here...
            // checking for use of `this` etc?
        });
    }

    const disallowed$1 = new Set(['Literal', 'ObjectExpression', 'ArrayExpression']);
    function setup(validator, prop) {
        while (prop.type === 'ParenthesizedExpression')
            prop = prop.expression;
        if (disallowed$1.has(prop.value.type)) {
            validator.error(prop.value, {
                code: `invalid-setup-property`,
                message: `'setup' must be a function`
            });
        }
    }

    function store(validator, prop) {
        // not sure there's anything we need to check here...
    }

    function immutable(validator, prop) {
        if (prop.value.type !== 'Literal' || typeof prop.value.value !== 'boolean') {
            validator.error(prop.value, {
                code: `invalid-immutable-property`,
                message: `'immutable' must be a boolean literal`
            });
        }
    }

    var propValidators = {
        data: data$1,
        actions,
        animations: transitions,
        computed,
        oncreate,
        ondestroy,
        onstate,
        onupdate,
        onrender,
        onteardown,
        helpers,
        methods,
        components,
        events,
        namespace,
        preload,
        props,
        tag: tag$1,
        transitions: transitions$1,
        setup,
        store,
        immutable,
    };

    const validPropList = Object.keys(propValidators);
    function validateJs(validator, js) {
        js.content.body.forEach((node) => {
            // check there are no named exports
            if (node.type === 'ExportNamedDeclaration') {
                validator.error(node, {
                    code: `named-export`,
                    message: `A component can only have a default export`
                });
            }
            if (node.type === 'ExportDefaultDeclaration') {
                if (node.declaration.type !== 'ObjectExpression') {
                    validator.error(node.declaration, {
                        code: `invalid-default-export`,
                        message: `Default export must be an object literal`
                    });
                }
                checkForComputedKeys(validator, node.declaration.properties);
                checkForDupes(validator, node.declaration.properties);
                const props = validator.properties;
                node.declaration.properties.forEach((prop) => {
                    props.set(getMethodName(prop.key), prop);
                });
                // Remove these checks in version 2
                if (props.has('oncreate') && props.has('onrender')) {
                    validator.error(props.get('onrender'), {
                        code: `duplicate-oncreate`,
                        message: 'Cannot have both oncreate and onrender'
                    });
                }
                if (props.has('ondestroy') && props.has('onteardown')) {
                    validator.error(props.get('onteardown'), {
                        code: `duplicate-ondestroy`,
                        message: 'Cannot have both ondestroy and onteardown'
                    });
                }
                // ensure all exported props are valid
                node.declaration.properties.forEach((prop) => {
                    const name = getMethodName(prop.key);
                    const propValidator = propValidators[name];
                    if (propValidator) {
                        propValidator(validator, prop);
                    }
                    else {
                        const match = fuzzymatch(name, validPropList);
                        if (match) {
                            validator.error(prop, {
                                code: `unexpected-property`,
                                message: `Unexpected property '${name}' (did you mean '${match}'?)`
                            });
                        }
                        else if (/FunctionExpression/.test(prop.value.type)) {
                            validator.error(prop, {
                                code: `unexpected-property`,
                                message: `Unexpected property '${name}' (did you mean to include it in 'methods'?)`
                            });
                        }
                        else {
                            validator.error(prop, {
                                code: `unexpected-property`,
                                message: `Unexpected property '${name}'`
                            });
                        }
                    }
                });
                if (props.has('namespace')) {
                    const ns = nodeToString(props.get('namespace').value);
                    validator.namespace = namespaces[ns] || ns;
                }
                validator.defaultExport = node;
            }
        });
        ['components', 'methods', 'helpers', 'transitions', 'animations', 'actions'].forEach(key => {
            if (validator.properties.has(key)) {
                validator.properties.get(key).value.properties.forEach((prop) => {
                    validator[key].set(getMethodName(prop.key), prop.value);
                });
            }
        });
    }

    function flattenReference(node) {
        if (node.type === 'Expression')
            throw new Error('bad');
        const nodes = [];
        const parts = [];
        const propEnd = node.end;
        while (node.type === 'MemberExpression') {
            if (node.computed)
                return null;
            nodes.unshift(node.property);
            parts.unshift(node.property.name);
            node = node.object;
        }
        const propStart = node.end;
        const name = node.type === 'Identifier'
            ? node.name
            : node.type === 'ThisExpression' ? 'this' : null;
        if (!name)
            return null;
        parts.unshift(name);
        nodes.unshift(node);
        return { name, nodes, parts, keypath: `${name}[✂${propStart}-${propEnd}✂]` };
    }

    function list$2(items, conjunction = 'or') {
        if (items.length === 1)
            return items[0];
        return `${items.slice(0, -1).join(', ')} ${conjunction} ${items[items.length - 1]}`;
    }

    const validCalleeObjects = new Set(['this', 'event', 'console']);

    const validBuiltins = new Set(['set', 'fire', 'destroy']);
    function validateEventHandlerCallee(validator, attribute, refCallees) {
        if (!attribute.expression)
            return;
        const { callee, type } = attribute.expression;
        if (type !== 'CallExpression') {
            validator.error(attribute.expression, {
                code: `invalid-event-handler`,
                message: `Expected a call expression`
            });
        }
        const { name } = flattenReference(callee);
        if (validCalleeObjects.has(name) || name === 'options')
            return;
        if (name === 'refs') {
            refCallees.push(callee);
            return;
        }
        if ((callee.type === 'Identifier' && validBuiltins.has(callee.name)) ||
            validator.methods.has(callee.name)) {
            return;
        }
        if (name[0] === '$') {
            // assume it's a store method
            return;
        }
        const validCallees = ['this.*', 'event.*', 'options.*', 'console.*'].concat(Array.from(validBuiltins), Array.from(validator.methods.keys()));
        let message = `'${validator.source.slice(callee.start, callee.end)}' is an invalid callee `;
        if (name === 'store') {
            message += `(did you mean '$${validator.source.slice(callee.start + 6, callee.end)}(...)'?)`;
        }
        else {
            message += `(should be one of ${list$2(validCallees)})`;
            if (callee.type === 'Identifier' && validator.helpers.has(callee.name)) {
                message += `. '${callee.name}' exists on 'helpers', did you put it in the wrong place?`;
            }
        }
        validator.warn(attribute.expression, {
            code: `invalid-callee`,
            message
        });
    }

    function validateComponent(validator, node, refs, refCallees, stack, elementStack) {
        if (node.name !== 'svelte:self' && node.name !== 'svelte:component' && !validator.components.has(node.name)) {
            validator.error(node, {
                code: `missing-component`,
                message: `${node.name} component is not defined`
            });
        }
        validator.used.components.add(node.name);
        node.attributes.forEach((attribute) => {
            if (attribute.type === 'Ref') {
                if (!refs.has(attribute.name))
                    refs.set(attribute.name, []);
                refs.get(attribute.name).push(node);
            }
            if (attribute.type === 'EventHandler') {
                validator.used.events.add(attribute.name);
                validateEventHandlerCallee(validator, attribute, refCallees);
            }
            else if (attribute.type === 'Transition') {
                validator.error(attribute, {
                    code: `invalid-transition`,
                    message: `Transitions can only be applied to DOM elements, not components`
                });
            }
            else if (attribute.type === 'Action') {
                validator.error(attribute, {
                    code: `invalid-action`,
                    message: `Actions can only be applied to DOM elements, not components`
                });
            }
        });
    }

    const svg$1 = /^(?:altGlyph|altGlyphDef|altGlyphItem|animate|animateColor|animateMotion|animateTransform|circle|clipPath|color-profile|cursor|defs|desc|discard|ellipse|feBlend|feColorMatrix|feComponentTransfer|feComposite|feConvolveMatrix|feDiffuseLighting|feDisplacementMap|feDistantLight|feDropShadow|feFlood|feFuncA|feFuncB|feFuncG|feFuncR|feGaussianBlur|feImage|feMerge|feMergeNode|feMorphology|feOffset|fePointLight|feSpecularLighting|feSpotLight|feTile|feTurbulence|filter|font|font-face|font-face-format|font-face-name|font-face-src|font-face-uri|foreignObject|g|glyph|glyphRef|hatch|hatchpath|hkern|image|line|linearGradient|marker|mask|mesh|meshgradient|meshpatch|meshrow|metadata|missing-glyph|mpath|path|pattern|polygon|polyline|radialGradient|rect|set|solidcolor|stop|switch|symbol|text|textPath|tref|tspan|unknown|use|view|vkern)$/;
    function validateElement(validator, node, refs, refCallees, stack, elementStack) {
        if (elementStack.length === 0 && validator.namespace !== svg && svg$1.test(node.name)) {
            validator.warn(node, {
                code: `missing-namespace`,
                message: `<${node.name}> is an SVG element – did you forget to add { namespace: 'svg' } ?`
            });
        }
        if (node.name === 'slot') {
            const nameAttribute = node.attributes.find((attribute) => attribute.name === 'name');
            if (nameAttribute) {
                if (nameAttribute.value.length !== 1 || nameAttribute.value[0].type !== 'Text') {
                    validator.error(nameAttribute, {
                        code: `dynamic-slot-name`,
                        message: `<slot> name cannot be dynamic`
                    });
                }
                const slotName = nameAttribute.value[0].data;
                if (slotName === 'default') {
                    validator.error(nameAttribute, {
                        code: `invalid-slot-name`,
                        message: `default is a reserved word — it cannot be used as a slot name`
                    });
                }
                // TODO should duplicate slots be disallowed? Feels like it's more likely to be a
                // bug than anything. Perhaps it should be a warning
                // if (validator.slots.has(slotName)) {
                // 	validator.error(`duplicate '${slotName}' <slot> element`, nameAttribute.start);
                // }
                // validator.slots.add(slotName);
            }
            else {
                // if (validator.slots.has('default')) {
                // 	validator.error(`duplicate default <slot> element`, node.start);
                // }
                // validator.slots.add('default');
            }
        }
        if (node.name === 'title') {
            if (node.attributes.length > 0) {
                validator.error(node.attributes[0], {
                    code: `illegal-attribute`,
                    message: `<title> cannot have attributes`
                });
            }
            node.children.forEach(child => {
                if (child.type !== 'Text' && child.type !== 'MustacheTag') {
                    validator.error(child, {
                        code: 'illegal-structure',
                        message: `<title> can only contain text and {{tags}}`
                    });
                }
            });
        }
        let hasIntro;
        let hasOutro;
        let hasTransition;
        let hasAnimation;
        node.attributes.forEach((attribute) => {
            if (attribute.type === 'Ref') {
                if (!refs.has(attribute.name))
                    refs.set(attribute.name, []);
                refs.get(attribute.name).push(node);
            }
            if (attribute.type === 'Binding') {
                const { name } = attribute;
                if (name === 'value') {
                    if (node.name !== 'input' &&
                        node.name !== 'textarea' &&
                        node.name !== 'select') {
                        validator.error(attribute, {
                            code: `invalid-binding`,
                            message: `'value' is not a valid binding on <${node.name}> elements`
                        });
                    }
                    if (node.name === 'select') {
                        const attribute = node.attributes.find((attribute) => attribute.name === 'multiple');
                        if (attribute && isDynamic(attribute)) {
                            validator.error(attribute, {
                                code: `dynamic-multiple-attribute`,
                                message: `'multiple' attribute cannot be dynamic if select uses two-way binding`
                            });
                        }
                    }
                    else {
                        checkTypeAttribute(validator, node);
                    }
                }
                else if (name === 'checked' || name === 'indeterminate') {
                    if (node.name !== 'input') {
                        validator.error(attribute, {
                            code: `invalid-binding`,
                            message: `'${name}' is not a valid binding on <${node.name}> elements`
                        });
                    }
                    if (checkTypeAttribute(validator, node) !== 'checkbox') {
                        validator.error(attribute, {
                            code: `invalid-binding`,
                            message: `'${name}' binding can only be used with <input type="checkbox">`
                        });
                    }
                }
                else if (name === 'group') {
                    if (node.name !== 'input') {
                        validator.error(attribute, {
                            code: `invalid-binding`,
                            message: `'group' is not a valid binding on <${node.name}> elements`
                        });
                    }
                    const type = checkTypeAttribute(validator, node);
                    if (type !== 'checkbox' && type !== 'radio') {
                        validator.error(attribute, {
                            code: `invalid-binding`,
                            message: `'checked' binding can only be used with <input type="checkbox"> or <input type="radio">`
                        });
                    }
                }
                else if (name === 'currentTime' ||
                    name === 'duration' ||
                    name === 'paused' ||
                    name === 'buffered' ||
                    name === 'seekable' ||
                    name === 'played' ||
                    name === 'volume') {
                    if (node.name !== 'audio' && node.name !== 'video') {
                        validator.error(attribute, {
                            code: `invalid-binding`,
                            message: `'${name}' binding can only be used with <audio> or <video>`
                        });
                    }
                }
                else if (dimensions.test(name)) {
                    if (node.name === 'svg' && (name === 'offsetWidth' || name === 'offsetHeight')) {
                        validator.error(attribute, {
                            code: 'invalid-binding',
                            message: `'${attribute.name}' is not a valid binding on <svg>. Use '${name.replace('offset', 'client')}' instead`
                        });
                    }
                    else if (svg$1.test(node.name)) {
                        validator.error(attribute, {
                            code: 'invalid-binding',
                            message: `'${attribute.name}' is not a valid binding on SVG elements`
                        });
                    }
                    else if (isVoidElementName(node.name)) {
                        validator.error(attribute, {
                            code: 'invalid-binding',
                            message: `'${attribute.name}' is not a valid binding on void elements like <${node.name}>. Use a wrapper element instead`
                        });
                    }
                }
                else {
                    validator.error(attribute, {
                        code: `invalid-binding`,
                        message: `'${attribute.name}' is not a valid binding`
                    });
                }
            }
            else if (attribute.type === 'EventHandler') {
                validator.used.events.add(attribute.name);
                validateEventHandlerCallee(validator, attribute, refCallees);
            }
            else if (attribute.type === 'Transition') {
                validator.used.transitions.add(attribute.name);
                const bidi = attribute.intro && attribute.outro;
                if (hasTransition) {
                    if (bidi) {
                        validator.error(attribute, {
                            code: `duplicate-transition`,
                            message: `An element can only have one 'transition' directive`
                        });
                    }
                    validator.error(attribute, {
                        code: `duplicate-transition`,
                        message: `An element cannot have both a 'transition' directive and an '${attribute.intro ? 'in' : 'out'}' directive`
                    });
                }
                if ((hasIntro && attribute.intro) || (hasOutro && attribute.outro)) {
                    if (bidi) {
                        validator.error(attribute, {
                            code: `duplicate-transition`,
                            message: `An element cannot have both an '${hasIntro ? 'in' : 'out'}' directive and a 'transition' directive`
                        });
                    }
                    validator.error(attribute, {
                        code: `duplicate-transition`,
                        message: `An element can only have one '${hasIntro ? 'in' : 'out'}' directive`
                    });
                }
                if (attribute.intro)
                    hasIntro = true;
                if (attribute.outro)
                    hasOutro = true;
                if (bidi)
                    hasTransition = true;
                if (!validator.transitions.has(attribute.name)) {
                    validator.error(attribute, {
                        code: `missing-transition`,
                        message: `Missing transition '${attribute.name}'`
                    });
                }
            }
            else if (attribute.type === 'Animation') {
                validator.used.animations.add(attribute.name);
                if (hasAnimation) {
                    validator.error(attribute, {
                        code: `duplicate-animation`,
                        message: `An element can only have one 'animate' directive`
                    });
                }
                if (!validator.animations.has(attribute.name)) {
                    validator.error(attribute, {
                        code: `missing-animation`,
                        message: `Missing animation '${attribute.name}'`
                    });
                }
                const parent = stack[stack.length - 1];
                if (!parent || parent.type !== 'EachBlock' || !parent.key) {
                    // TODO can we relax the 'immediate child' rule?
                    validator.error(attribute, {
                        code: `invalid-animation`,
                        message: `An element that use the animate directive must be the immediate child of a keyed each block`
                    });
                }
                if (parent.children.length > 1) {
                    validator.error(attribute, {
                        code: `invalid-animation`,
                        message: `An element that use the animate directive must be the sole child of a keyed each block`
                    });
                }
                hasAnimation = true;
            }
            else if (attribute.type === 'Attribute') {
                if (attribute.name === 'value' && node.name === 'textarea') {
                    if (node.children.length) {
                        validator.error(attribute, {
                            code: `textarea-duplicate-value`,
                            message: `A <textarea> can have either a value attribute or (equivalently) child content, but not both`
                        });
                    }
                }
                if (attribute.name === 'slot') {
                    checkSlotAttribute(validator, node, attribute, stack);
                }
            }
            else if (attribute.type === 'Action') {
                validator.used.actions.add(attribute.name);
                if (!validator.actions.has(attribute.name)) {
                    validator.error(attribute, {
                        code: `missing-action`,
                        message: `Missing action '${attribute.name}'`
                    });
                }
            }
        });
    }
    function checkTypeAttribute(validator, node) {
        const attribute = node.attributes.find((attribute) => attribute.name === 'type');
        if (!attribute)
            return null;
        if (attribute.value === true) {
            validator.error(attribute, {
                code: `missing-type`,
                message: `'type' attribute must be specified`
            });
        }
        if (isDynamic(attribute)) {
            validator.error(attribute, {
                code: `invalid-type`,
                message: `'type' attribute cannot be dynamic if input uses two-way binding`
            });
        }
        return attribute.value[0].data;
    }
    function checkSlotAttribute(validator, node, attribute, stack) {
        if (isDynamic(attribute)) {
            validator.error(attribute, {
                code: `invalid-slot-attribute`,
                message: `slot attribute cannot have a dynamic value`
            });
        }
        let i = stack.length;
        while (i--) {
            const parent = stack[i];
            if (parent.type === 'Component') {
                // if we're inside a component or a custom element, gravy
                if (parent.name === 'svelte:self' || parent.name === 'svelte:component' || validator.components.has(parent.name))
                    return;
            }
            else if (parent.type === 'Element') {
                if (/-/.test(parent.name))
                    return;
            }
            if (parent.type === 'IfBlock' || parent.type === 'EachBlock') {
                const message = `Cannot place slotted elements inside an ${parent.type === 'IfBlock' ? 'if' : 'each'}-block`;
                validator.error(attribute, {
                    code: `invalid-slotted-content`,
                    message
                });
            }
        }
        validator.error(attribute, {
            code: `invalid-slotted-content`,
            message: `Element with a slot='...' attribute must be a descendant of a component or custom element`
        });
    }
    function isDynamic(attribute) {
        if (attribute.value === true)
            return false;
        return attribute.value.length > 1 || attribute.value[0].type !== 'Text';
    }

    const validBindings = [
        'innerWidth',
        'innerHeight',
        'outerWidth',
        'outerHeight',
        'scrollX',
        'scrollY',
        'online'
    ];
    function validateWindow(validator, node, refs, refCallees) {
        node.attributes.forEach((attribute) => {
            if (attribute.type === 'Binding') {
                if (attribute.value.type !== 'Identifier') {
                    const { parts } = flattenReference(attribute.value);
                    validator.error(attribute.value, {
                        code: `invalid-binding`,
                        message: `Bindings on <svelte:window> must be to top-level properties, e.g. '${parts[parts.length - 1]}' rather than '${parts.join('.')}'`
                    });
                }
                if (!~validBindings.indexOf(attribute.name)) {
                    const match = attribute.name === 'width'
                        ? 'innerWidth'
                        : attribute.name === 'height'
                            ? 'innerHeight'
                            : fuzzymatch(attribute.name, validBindings);
                    const message = `'${attribute.name}' is not a valid binding on <svelte:window>`;
                    if (match) {
                        validator.error(attribute, {
                            code: `invalid-binding`,
                            message: `${message} (did you mean '${match}'?)`
                        });
                    }
                    else {
                        validator.error(attribute, {
                            code: `invalid-binding`,
                            message: `${message} — valid bindings are ${list$2(validBindings)}`
                        });
                    }
                }
            }
            else if (attribute.type === 'EventHandler') {
                validator.used.events.add(attribute.name);
                validateEventHandlerCallee(validator, attribute, refCallees);
            }
        });
    }

    function validateHead(validator, node, refs, refCallees) {
        if (node.attributes.length) {
            validator.error(node.attributes[0], {
                code: `invalid-attribute`,
                message: `<svelte:head> should not have any attributes or directives`
            });
        }
        // TODO ensure only valid elements are included here
        node.children.forEach(node => {
            if (node.type !== 'Element' && node.type !== 'Title')
                return; // TODO handle {{#if}} and friends?
            validateElement(validator, node, refs, refCallees, [], []);
        });
    }

    function validateSlot(validator, node) {
        node.attributes.forEach(attr => {
            if (attr.type !== 'Attribute') {
                validator.error(attr, {
                    code: `invalid-slot-directive`,
                    message: `<slot> cannot have directives`
                });
            }
            if (attr.name !== 'name') {
                validator.error(attr, {
                    code: `invalid-slot-attribute`,
                    message: `"name" is the only attribute permitted on <slot> elements`
                });
            }
            if (attr.value.length !== 1 || attr.value[0].type !== 'Text') {
                validator.error(attr, {
                    code: `dynamic-slot-name`,
                    message: `<slot> name cannot be dynamic`
                });
            }
            const slotName = attr.value[0].data;
            if (slotName === 'default') {
                validator.error(attr, {
                    code: `invalid-slot-name`,
                    message: `default is a reserved word — it cannot be used as a slot name`
                });
            }
            // TODO should duplicate slots be disallowed? Feels like it's more likely to be a
            // bug than anything. Perhaps it should be a warning
            // if (validator.slots.has(slotName)) {
            // 	validator.error(`duplicate '${slotName}' <slot> element`, nameAttribute.start);
            // }
            // validator.slots.add(slotName);
        });
        // if (node.attributes.length === 0) && validator.slots.has('default')) {
        // 	validator.error(node, {
        // 		code: `duplicate-slot`,
        // 		message: `duplicate default <slot> element`
        // 	});
        // }
    }

    function getStaticAttributeValue(node, name) {
        const attribute = node.attributes.find((attr) => attr.type === 'Attribute' && attr.name.toLowerCase() === name);
        if (!attribute)
            return null;
        if (attribute.value === true)
            return true;
        if (attribute.value.length === 0)
            return '';
        if (attribute.value.length === 1 && attribute.value[0].type === 'Text') {
            return attribute.value[0].data;
        }
        return null;
    }

    const ariaAttributes = 'activedescendant atomic autocomplete busy checked controls current describedby details disabled dropeffect errormessage expanded flowto grabbed haspopup hidden invalid keyshortcuts label labelledby level live modal multiline multiselectable orientation owns placeholder posinset pressed readonly relevant required roledescription selected setsize sort valuemax valuemin valuenow valuetext'.split(' ');
    const ariaAttributeSet = new Set(ariaAttributes);
    const ariaRoles = 'alert alertdialog application article banner button cell checkbox columnheader combobox command complementary composite contentinfo definition dialog directory document feed figure form grid gridcell group heading img input landmark link list listbox listitem log main marquee math menu menubar menuitem menuitemcheckbox menuitemradio navigation none note option presentation progressbar radio radiogroup range region roletype row rowgroup rowheader scrollbar search searchbox section sectionhead select separator slider spinbutton status structure switch tab table tablist tabpanel term textbox timer toolbar tooltip tree treegrid treeitem widget window'.split(' ');
    const ariaRoleSet = new Set(ariaRoles);
    const invisibleElements = new Set(['meta', 'html', 'script', 'style']);
    function a11y(validator, node, elementStack) {
        if (node.type === 'Text') {
            // accessible-emoji
            return;
        }
        if (node.type !== 'Element')
            return;
        const attributeMap = new Map();
        node.attributes.forEach((attribute) => {
            if (attribute.type === 'Spread')
                return;
            const name = attribute.name.toLowerCase();
            // aria-props
            if (name.startsWith('aria-')) {
                if (invisibleElements.has(node.name)) {
                    // aria-unsupported-elements
                    validator.warn(attribute, {
                        code: `a11y-aria-attributes`,
                        message: `A11y: <${node.name}> should not have aria-* attributes`
                    });
                }
                const type = name.slice(5);
                if (!ariaAttributeSet.has(type)) {
                    const match = fuzzymatch(type, ariaAttributes);
                    let message = `A11y: Unknown aria attribute 'aria-${type}'`;
                    if (match)
                        message += ` (did you mean '${match}'?)`;
                    validator.warn(attribute, {
                        code: `a11y-unknown-aria-attribute`,
                        message
                    });
                }
            }
            // aria-role
            if (name === 'role') {
                if (invisibleElements.has(node.name)) {
                    // aria-unsupported-elements
                    validator.warn(attribute, {
                        code: `a11y-misplaced-role`,
                        message: `A11y: <${node.name}> should not have role attribute`
                    });
                }
                const value = getStaticAttributeValue(node, 'role');
                if (value && !ariaRoleSet.has(value)) {
                    const match = fuzzymatch(value, ariaRoles);
                    let message = `A11y: Unknown role '${value}'`;
                    if (match)
                        message += ` (did you mean '${match}'?)`;
                    validator.warn(attribute, {
                        code: `a11y-unknown-role`,
                        message
                    });
                }
            }
            // no-access-key
            if (name === 'accesskey') {
                validator.warn(attribute, {
                    code: `a11y-accesskey`,
                    message: `A11y: Avoid using accesskey`
                });
            }
            // no-autofocus
            if (name === 'autofocus') {
                validator.warn(attribute, {
                    code: `a11y-autofocus`,
                    message: `A11y: Avoid using autofocus`
                });
            }
            // scope
            if (name === 'scope' && node.name !== 'th') {
                validator.warn(attribute, {
                    code: `a11y-misplaced-scope`,
                    message: `A11y: The scope attribute should only be used with <th> elements`
                });
            }
            // tabindex-no-positive
            if (name === 'tabindex') {
                const value = getStaticAttributeValue(node, 'tabindex');
                if (!isNaN(value) && +value > 0) {
                    validator.warn(attribute, {
                        code: `a11y-positive-tabindex`,
                        message: `A11y: avoid tabindex values above zero`
                    });
                }
            }
            attributeMap.set(attribute.name, attribute);
        });
        function shouldHaveAttribute(attributes, name = node.name) {
            if (attributes.length === 0 || !attributes.some((name) => attributeMap.has(name))) {
                const article = /^[aeiou]/.test(attributes[0]) ? 'an' : 'a';
                const sequence = attributes.length > 1 ?
                    attributes.slice(0, -1).join(', ') + ` or ${attributes[attributes.length - 1]}` :
                    attributes[0];
                validator.warn(node, {
                    code: `a11y-missing-attribute`,
                    message: `A11y: <${name}> element should have ${article} ${sequence} attribute`
                });
            }
        }
        function shouldHaveContent() {
            if (node.children.length === 0) {
                validator.warn(node, {
                    code: `a11y-missing-content`,
                    message: `A11y: <${node.name}> element should have child content`
                });
            }
        }
        function shouldHaveValidHref(attribute) {
            const href = attributeMap.get(attribute);
            const value = getStaticAttributeValue(node, attribute);
            if (value === '' || value === '#') {
                validator.warn(href, {
                    code: `a11y-invalid-attribute`,
                    message: `A11y: '${value}' is not a valid ${attribute} attribute`
                });
            }
        }
        if (node.name === 'a') {
            if (attributeMap.has('href')) {
                // anchor-is-valid
                shouldHaveValidHref('href');
            }
            else if (attributeMap.has('xlink:href')) {
                // anchor-in-svg-is-valid
                shouldHaveValidHref('xlink:href');
            }
            else {
                validator.warn(node, {
                    code: `a11y-missing-attribute`,
                    message: `A11y: <a> element should have an href attribute`
                });
            }
            // anchor-has-content
            shouldHaveContent();
        }
        if (node.name === 'img')
            shouldHaveAttribute(['alt']);
        if (node.name === 'area')
            shouldHaveAttribute(['alt', 'aria-label', 'aria-labelledby']);
        if (node.name === 'object')
            shouldHaveAttribute(['title', 'aria-label', 'aria-labelledby']);
        if (node.name === 'input' && getStaticAttributeValue(node, 'type') === 'image') {
            shouldHaveAttribute(['alt', 'aria-label', 'aria-labelledby'], 'input type="image"');
        }
        // heading-has-content
        if (/^h[1-6]$/.test(node.name)) {
            shouldHaveContent();
            if (attributeMap.has('aria-hidden')) {
                validator.warn(attributeMap.get('aria-hidden'), {
                    code: `a11y-hidden`,
                    message: `A11y: <${node.name}> element should not be hidden`
                });
            }
        }
        // iframe-has-title
        if (node.name === 'iframe') {
            shouldHaveAttribute(['title']);
        }
        // html-has-lang
        if (node.name === 'html') {
            shouldHaveAttribute(['lang']);
        }
        // no-distracting-elements
        if (node.name === 'marquee' || node.name === 'blink') {
            validator.warn(node, {
                code: `a11y-distracting-elements`,
                message: `A11y: Avoid <${node.name}> elements`
            });
        }
        if (node.name === 'figcaption') {
            const parent = elementStack[elementStack.length - 1];
            if (parent) {
                if (parent.name !== 'figure') {
                    validator.warn(node, {
                        code: `a11y-structure`,
                        message: `A11y: <figcaption> must be an immediate child of <figure>`
                    });
                }
                else {
                    const children = parent.children.filter(node => {
                        if (node.type === 'Comment')
                            return false;
                        if (node.type === 'Text')
                            return /\S/.test(node.data);
                        return true;
                    });
                    const index = children.indexOf(node);
                    if (index !== 0 && index !== children.length - 1) {
                        validator.warn(node, {
                            code: `a11y-structure`,
                            message: `A11y: <figcaption> must be first or last child of <figure>`
                        });
                    }
                }
            }
        }
    }

    function unpackDestructuring(contexts, node, tail) {
        if (!node)
            return;
        if (node.type === 'Identifier') {
            contexts.push({
                key: node,
                tail
            });
        }
        else if (node.type === 'ArrayPattern') {
            node.elements.forEach((element, i) => {
                unpackDestructuring(contexts, element, `${tail}[${i}]`);
            });
        }
        else if (node.type === 'ObjectPattern') {
            node.properties.forEach((property) => {
                unpackDestructuring(contexts, property.value, `${tail}.${property.key.name}`);
            });
        }
    }

    function isEmptyBlock(node) {
        if (!/Block$/.test(node.type) || !node.children)
            return false;
        if (node.children.length > 1)
            return false;
        const child = node.children[0];
        return !child || (child.type === 'Text' && !/\S/.test(child.data));
    }
    function validateHtml(validator, html) {
        const refs = new Map();
        const refCallees = [];
        const stack = [];
        const elementStack = [];
        function visit(node) {
            if (node.type === 'Window') {
                validateWindow(validator, node, refs, refCallees);
            }
            else if (node.type === 'Head') {
                validateHead(validator, node, refs, refCallees);
            }
            else if (node.type === 'Slot') {
                validateSlot(validator, node);
            }
            else if (node.type === 'Component' || node.name === 'svelte:self' || node.name === 'svelte:component') {
                validateComponent(validator, node, refs, refCallees, stack, elementStack);
            }
            else if (node.type === 'Element') {
                validateElement(validator, node, refs, refCallees, stack, elementStack);
                a11y(validator, node, elementStack);
            }
            else if (node.type === 'EachBlock') {
                const contexts = [];
                unpackDestructuring(contexts, node.context, '');
                contexts.forEach(prop => {
                    if (validator.helpers.has(prop.key.name)) {
                        validator.warn(prop.key, {
                            code: `each-context-clash`,
                            message: `Context clashes with a helper. Rename one or the other to eliminate any ambiguity`
                        });
                    }
                });
            }
            if (validator.options.dev && isEmptyBlock(node)) {
                validator.warn(node, {
                    code: `empty-block`,
                    message: 'Empty block'
                });
            }
            if (node.children) {
                if (node.type === 'Element')
                    elementStack.push(node);
                stack.push(node);
                node.children.forEach(visit);
                stack.pop();
                if (node.type === 'Element')
                    elementStack.pop();
            }
            if (node.else) {
                visit(node.else);
            }
            if (node.type === 'AwaitBlock') {
                visit(node.pending);
                visit(node.then);
                visit(node.catch);
            }
        }
        html.children.forEach(visit);
        refCallees.forEach(callee => {
            const { parts } = flattenReference(callee);
            const ref = parts[1];
            if (refs.has(ref)) {
                // TODO check method is valid, e.g. `audio.stop()` should be `audio.pause()`
            }
            else {
                const match = fuzzymatch(ref, Array.from(refs.keys()));
                let message = `'refs.${ref}' does not exist`;
                if (match)
                    message += ` (did you mean 'refs.${match}'?)`;
                validator.error(callee, {
                    code: `missing-ref`,
                    message
                });
            }
        });
    }

    class Validator {
        constructor(ast, source, stats, options) {
            this.source = source;
            this.stats = stats;
            this.filename = options.filename;
            this.options = options;
            this.namespace = null;
            this.defaultExport = null;
            this.properties = new Map();
            this.components = new Map();
            this.methods = new Map();
            this.helpers = new Map();
            this.animations = new Map();
            this.transitions = new Map();
            this.actions = new Map();
            this.slots = new Set();
            this.used = {
                components: new Set(),
                helpers: new Set(),
                events: new Set(),
                animations: new Set(),
                transitions: new Set(),
                actions: new Set(),
            };
        }
        error(pos, { code, message }) {
            error$2(message, {
                name: 'ValidationError',
                code,
                source: this.source,
                start: pos.start,
                end: pos.end,
                filename: this.filename
            });
        }
        warn(pos, { code, message }) {
            if (!this.locator)
                this.locator = getLocator(this.source, { offsetLine: 1 });
            const start = this.locator(pos.start);
            const end = this.locator(pos.end);
            const frame = getCodeFrame(this.source, start.line - 1, start.column);
            this.stats.warn({
                code,
                message,
                frame,
                start,
                end,
                pos: pos.start,
                filename: this.filename,
                toString: () => `${message} (${start.line + 1}:${start.column})\n${frame}`,
            });
        }
    }
    function validate(ast, source, stylesheet, stats, options) {
        const { onerror, name, filename, dev, parser } = options;
        try {
            if (name && !/^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test(name)) {
                const error = new Error(`options.name must be a valid identifier (got '${name}')`);
                throw error;
            }
            if (name && /^[a-z]/.test(name)) {
                const message = `options.name should be capitalised`;
                stats.warn({
                    code: `options-lowercase-name`,
                    message,
                    filename,
                    toString: () => message,
                });
            }
            const validator = new Validator(ast, source, stats, {
                name,
                filename,
                dev,
                parser
            });
            if (ast.js) {
                validateJs(validator, ast.js);
            }
            if (ast.css) {
                stylesheet.validate(validator);
            }
            if (ast.html) {
                validateHtml(validator, ast.html);
            }
            // need to do a second pass of the JS, now that we've analysed the markup
            if (ast.js && validator.defaultExport) {
                const categories = {
                    components: 'component',
                    // TODO helpers require a bit more work — need to analyse all expressions
                    // helpers: 'helper',
                    events: 'event definition',
                    transitions: 'transition',
                    actions: 'actions',
                };
                Object.keys(categories).forEach(category => {
                    const definitions = validator.defaultExport.declaration.properties.find(prop => prop.key.name === category);
                    if (definitions) {
                        definitions.value.properties.forEach(prop => {
                            const { name } = prop.key;
                            if (!validator.used[category].has(name)) {
                                validator.warn(prop, {
                                    code: `unused-${category.slice(0, -1)}`,
                                    message: `The '${name}' ${categories[category]} is unused`
                                });
                            }
                        });
                    }
                });
            }
        }
        catch (err) {
            if (onerror) {
                onerror(err);
            }
            else {
                throw err;
            }
        }
    }

    const start = /\n(\t+)/;
    function deindent(strings, ...values) {
        const indentation = start.exec(strings[0])[1];
        const pattern = new RegExp(`^${indentation}`, 'gm');
        let result = strings[0].replace(start, '').replace(pattern, '');
        let trailingIndentation = getTrailingIndentation(result);
        for (let i = 1; i < strings.length; i += 1) {
            let expression = values[i - 1];
            const string = strings[i].replace(pattern, '');
            if (Array.isArray(expression)) {
                expression = expression.length ? expression.join('\n') : null;
            }
            if (expression || expression === '') {
                const value = String(expression).replace(/\n/g, `\n${trailingIndentation}`);
                result += value + string;
            }
            else {
                let c = result.length;
                while (/\s/.test(result[c - 1]))
                    c -= 1;
                result = result.slice(0, c) + string;
            }
            trailingIndentation = getTrailingIndentation(result);
        }
        return result.trim().replace(/\t+$/gm, '');
    }
    function getTrailingIndentation(str) {
        let i = str.length;
        while (str[i - 1] === ' ' || str[i - 1] === '\t')
            i -= 1;
        return str.slice(i, str.length);
    }

    function stringify(data, options = {}) {
        return JSON.stringify(escape(data, options));
    }
    function escape(data, { onlyEscapeAtSymbol = false } = {}) {
        return data.replace(onlyEscapeAtSymbol ? /(%+|@+)/g : /(%+|@+|#+)/g, (match) => {
            return match + match[0];
        });
    }
    const escaped = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
    };
    function escapeHTML(html) {
        return String(html).replace(/[&<>]/g, match => escaped[match]);
    }
    function escapeTemplate(str) {
        return str.replace(/(\${|`|\\)/g, '\\$1');
    }

    var ChunkType;
    (function (ChunkType) {
        ChunkType[ChunkType["Line"] = 0] = "Line";
        ChunkType[ChunkType["Block"] = 1] = "Block";
    })(ChunkType || (ChunkType = {}));
    class CodeBuilder {
        constructor(str = '') {
            this.result = str;
            const initial = str
                ? /\n/.test(str) ? ChunkType.Block : ChunkType.Line
                : null;
            this.first = initial;
            this.last = initial;
            this.lastCondition = null;
            this.conditionStack = [];
            this.indent = '';
        }
        addConditional(condition, body) {
            this.reifyConditions();
            body = body.replace(/^/gm, `${this.indent}\t`);
            if (condition === this.lastCondition) {
                this.result += `\n${body}`;
            }
            else {
                if (this.lastCondition) {
                    this.result += `\n${this.indent}}`;
                }
                this.result += `${this.last === ChunkType.Block ? '\n\n' : '\n'}${this.indent}if (${condition}) {\n${body}`;
                this.lastCondition = condition;
            }
            this.last = ChunkType.Block;
        }
        addLine(line) {
            this.reifyConditions();
            if (this.lastCondition) {
                this.result += `\n${this.indent}}`;
                this.lastCondition = null;
            }
            if (this.last === ChunkType.Block) {
                this.result += `\n\n${this.indent}${line}`;
            }
            else if (this.last === ChunkType.Line) {
                this.result += `\n${this.indent}${line}`;
            }
            else {
                this.result += line;
            }
            this.last = ChunkType.Line;
            if (!this.first)
                this.first = ChunkType.Line;
        }
        addLineAtStart(line) {
            this.reifyConditions();
            if (this.first === ChunkType.Block) {
                this.result = `${line}\n\n${this.indent}${this.result}`;
            }
            else if (this.first === ChunkType.Line) {
                this.result = `${line}\n${this.indent}${this.result}`;
            }
            else {
                this.result += line;
            }
            this.first = ChunkType.Line;
            if (!this.last)
                this.last = ChunkType.Line;
        }
        addBlock(block) {
            this.reifyConditions();
            if (this.indent)
                block = block.replace(/^/gm, `${this.indent}`);
            if (this.lastCondition) {
                this.result += `\n${this.indent}}`;
                this.lastCondition = null;
            }
            if (this.result) {
                this.result += `\n\n${this.indent}${block}`;
            }
            else {
                this.result += block;
            }
            this.last = ChunkType.Block;
            if (!this.first)
                this.first = ChunkType.Block;
        }
        addBlockAtStart(block) {
            this.reifyConditions();
            if (this.result) {
                this.result = `${block}\n\n${this.indent}${this.result}`;
            }
            else {
                this.result += block;
            }
            this.first = ChunkType.Block;
            if (!this.last)
                this.last = ChunkType.Block;
        }
        isEmpty() {
            return this.result === '';
        }
        pushCondition(condition) {
            this.conditionStack.push({ condition, used: false });
        }
        popCondition() {
            const { used } = this.conditionStack.pop();
            this.indent = repeat('\t', this.conditionStack.length);
            if (used)
                this.addLine('}');
        }
        reifyConditions() {
            for (let i = 0; i < this.conditionStack.length; i += 1) {
                const condition = this.conditionStack[i];
                if (!condition.used) {
                    const line = `if (${condition.condition}) {`;
                    if (this.last === ChunkType.Block) {
                        this.result += `\n\n${this.indent}${line}`;
                    }
                    else if (this.last === ChunkType.Line) {
                        this.result += `\n${this.indent}${line}`;
                    }
                    else {
                        this.result += line;
                    }
                    this.last = ChunkType.Line;
                    if (!this.first)
                        this.first = ChunkType.Line;
                    this.indent = repeat('\t', this.conditionStack.length);
                    condition.used = true;
                }
            }
        }
        toString() {
            return this.result.trim() + (this.lastCondition ? `\n}` : ``);
        }
    }

    var globalWhitelist = new Set([
        'Array',
        'Boolean',
        'console',
        'Date',
        'decodeURI',
        'decodeURIComponent',
        'encodeURI',
        'encodeURIComponent',
        'Infinity',
        'Intl',
        'isFinite',
        'isNaN',
        'JSON',
        'Map',
        'Math',
        'NaN',
        'Number',
        'Object',
        'parseFloat',
        'parseInt',
        'Promise',
        'RegExp',
        'Set',
        'String',
        'undefined',
    ]);

    var charToInteger = {};
    var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
    for (var i$1 = 0; i$1 < chars.length; i$1++) {
        charToInteger[chars.charCodeAt(i$1)] = i$1;
    }
    function encode(decoded) {
        var sourceFileIndex = 0; // second field
        var sourceCodeLine = 0; // third field
        var sourceCodeColumn = 0; // fourth field
        var nameIndex = 0; // fifth field
        var mappings = '';
        for (var i = 0; i < decoded.length; i++) {
            var line = decoded[i];
            if (i > 0)
                mappings += ';';
            if (line.length === 0)
                continue;
            var generatedCodeColumn = 0; // first field
            var lineMappings = [];
            for (var _i = 0, line_1 = line; _i < line_1.length; _i++) {
                var segment = line_1[_i];
                var segmentMappings = encodeInteger(segment[0] - generatedCodeColumn);
                generatedCodeColumn = segment[0];
                if (segment.length > 1) {
                    segmentMappings +=
                        encodeInteger(segment[1] - sourceFileIndex) +
                            encodeInteger(segment[2] - sourceCodeLine) +
                            encodeInteger(segment[3] - sourceCodeColumn);
                    sourceFileIndex = segment[1];
                    sourceCodeLine = segment[2];
                    sourceCodeColumn = segment[3];
                }
                if (segment.length === 5) {
                    segmentMappings += encodeInteger(segment[4] - nameIndex);
                    nameIndex = segment[4];
                }
                lineMappings.push(segmentMappings);
            }
            mappings += lineMappings.join(',');
        }
        return mappings;
    }
    function encodeInteger(num) {
        var result = '';
        num = num < 0 ? (-num << 1) | 1 : num << 1;
        do {
            var clamped = num & 31;
            num >>= 5;
            if (num > 0) {
                clamped |= 32;
            }
            result += chars[clamped];
        } while (num > 0);
        return result;
    }

    var Chunk = function Chunk(start, end, content) {
    	this.start = start;
    	this.end = end;
    	this.original = content;

    	this.intro = '';
    	this.outro = '';

    	this.content = content;
    	this.storeName = false;
    	this.edited = false;

    	// we make these non-enumerable, for sanity while debugging
    	Object.defineProperties(this, {
    		previous: { writable: true, value: null },
    		next:     { writable: true, value: null }
    	});
    };

    Chunk.prototype.appendLeft = function appendLeft (content) {
    	this.outro += content;
    };

    Chunk.prototype.appendRight = function appendRight (content) {
    	this.intro = this.intro + content;
    };

    Chunk.prototype.clone = function clone () {
    	var chunk = new Chunk(this.start, this.end, this.original);

    	chunk.intro = this.intro;
    	chunk.outro = this.outro;
    	chunk.content = this.content;
    	chunk.storeName = this.storeName;
    	chunk.edited = this.edited;

    	return chunk;
    };

    Chunk.prototype.contains = function contains (index) {
    	return this.start < index && index < this.end;
    };

    Chunk.prototype.eachNext = function eachNext (fn) {
    	var chunk = this;
    	while (chunk) {
    		fn(chunk);
    		chunk = chunk.next;
    	}
    };

    Chunk.prototype.eachPrevious = function eachPrevious (fn) {
    	var chunk = this;
    	while (chunk) {
    		fn(chunk);
    		chunk = chunk.previous;
    	}
    };

    Chunk.prototype.edit = function edit (content, storeName, contentOnly) {
    	this.content = content;
    	if (!contentOnly) {
    		this.intro = '';
    		this.outro = '';
    	}
    	this.storeName = storeName;

    	this.edited = true;

    	return this;
    };

    Chunk.prototype.prependLeft = function prependLeft (content) {
    	this.outro = content + this.outro;
    };

    Chunk.prototype.prependRight = function prependRight (content) {
    	this.intro = content + this.intro;
    };

    Chunk.prototype.split = function split (index) {
    	var sliceIndex = index - this.start;

    	var originalBefore = this.original.slice(0, sliceIndex);
    	var originalAfter = this.original.slice(sliceIndex);

    	this.original = originalBefore;

    	var newChunk = new Chunk(index, this.end, originalAfter);
    	newChunk.outro = this.outro;
    	this.outro = '';

    	this.end = index;

    	if (this.edited) {
    		// TODO is this block necessary?...
    		newChunk.edit('', false);
    		this.content = '';
    	} else {
    		this.content = originalBefore;
    	}

    	newChunk.next = this.next;
    	if (newChunk.next) { newChunk.next.previous = newChunk; }
    	newChunk.previous = this;
    	this.next = newChunk;

    	return newChunk;
    };

    Chunk.prototype.toString = function toString () {
    	return this.intro + this.content + this.outro;
    };

    Chunk.prototype.trimEnd = function trimEnd (rx) {
    	this.outro = this.outro.replace(rx, '');
    	if (this.outro.length) { return true; }

    	var trimmed = this.content.replace(rx, '');

    	if (trimmed.length) {
    		if (trimmed !== this.content) {
    			this.split(this.start + trimmed.length).edit('', false);
    		}
    		return true;

    	} else {
    		this.edit('', false);

    		this.intro = this.intro.replace(rx, '');
    		if (this.intro.length) { return true; }
    	}
    };

    Chunk.prototype.trimStart = function trimStart (rx) {
    	this.intro = this.intro.replace(rx, '');
    	if (this.intro.length) { return true; }

    	var trimmed = this.content.replace(rx, '');

    	if (trimmed.length) {
    		if (trimmed !== this.content) {
    			this.split(this.end - trimmed.length);
    			this.edit('', false);
    		}
    		return true;

    	} else {
    		this.edit('', false);

    		this.outro = this.outro.replace(rx, '');
    		if (this.outro.length) { return true; }
    	}
    };

    var btoa = function () {
    	throw new Error('Unsupported environment: `window.btoa` or `Buffer` should be supported.');
    };
    if (typeof window !== 'undefined' && typeof window.btoa === 'function') {
    	btoa = window.btoa;
    } else if (typeof Buffer === 'function') {
    	btoa = function (str) { return new Buffer(str).toString('base64'); };
    }

    var SourceMap = function SourceMap(properties) {
    	this.version = 3;
    	this.file = properties.file;
    	this.sources = properties.sources;
    	this.sourcesContent = properties.sourcesContent;
    	this.names = properties.names;
    	this.mappings = encode(properties.mappings);
    };

    SourceMap.prototype.toString = function toString () {
    	return JSON.stringify(this);
    };

    SourceMap.prototype.toUrl = function toUrl () {
    	return 'data:application/json;charset=utf-8;base64,' + btoa(this.toString());
    };

    function guessIndent(code) {
    	var lines = code.split('\n');

    	var tabbed = lines.filter(function (line) { return /^\t+/.test(line); });
    	var spaced = lines.filter(function (line) { return /^ {2,}/.test(line); });

    	if (tabbed.length === 0 && spaced.length === 0) {
    		return null;
    	}

    	// More lines tabbed than spaced? Assume tabs, and
    	// default to tabs in the case of a tie (or nothing
    	// to go on)
    	if (tabbed.length >= spaced.length) {
    		return '\t';
    	}

    	// Otherwise, we need to guess the multiple
    	var min = spaced.reduce(function (previous, current) {
    		var numSpaces = /^ +/.exec(current)[0].length;
    		return Math.min(numSpaces, previous);
    	}, Infinity);

    	return new Array(min + 1).join(' ');
    }

    function getRelativePath(from, to) {
    	var fromParts = from.split(/[/\\]/);
    	var toParts = to.split(/[/\\]/);

    	fromParts.pop(); // get dirname

    	while (fromParts[0] === toParts[0]) {
    		fromParts.shift();
    		toParts.shift();
    	}

    	if (fromParts.length) {
    		var i = fromParts.length;
    		while (i--) { fromParts[i] = '..'; }
    	}

    	return fromParts.concat(toParts).join('/');
    }

    var toString$2 = Object.prototype.toString;

    function isObject(thing) {
    	return toString$2.call(thing) === '[object Object]';
    }

    function getLocator$1(source) {
    	var originalLines = source.split('\n');
    	var lineOffsets = [];

    	for (var i = 0, pos = 0; i < originalLines.length; i++) {
    		lineOffsets.push(pos);
    		pos += originalLines[i].length + 1;
    	}

    	return function locate(index) {
    		var i = 0;
    		var j = lineOffsets.length;
    		while (i < j) {
    			var m = (i + j) >> 1;
    			if (index < lineOffsets[m]) {
    				j = m;
    			} else {
    				i = m + 1;
    			}
    		}
    		var line = i - 1;
    		var column = index - lineOffsets[line];
    		return { line: line, column: column };
    	};
    }

    var Mappings = function Mappings(hires) {
    	this.hires = hires;
    	this.generatedCodeLine = 0;
    	this.generatedCodeColumn = 0;
    	this.raw = [];
    	this.rawSegments = this.raw[this.generatedCodeLine] = [];
    	this.pending = null;
    };

    Mappings.prototype.addEdit = function addEdit (sourceIndex, content, loc, nameIndex) {
    	if (content.length) {
    		var segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
    		if (nameIndex >= 0) {
    			segment.push(nameIndex);
    		}
    		this.rawSegments.push(segment);
    	} else if (this.pending) {
    		this.rawSegments.push(this.pending);
    	}

    	this.advance(content);
    	this.pending = null;
    };

    Mappings.prototype.addUneditedChunk = function addUneditedChunk (sourceIndex, chunk, original, loc, sourcemapLocations) {
    		var this$1 = this;

    	var originalCharIndex = chunk.start;
    	var first = true;

    	while (originalCharIndex < chunk.end) {
    		if (this$1.hires || first || sourcemapLocations[originalCharIndex]) {
    			this$1.rawSegments.push([this$1.generatedCodeColumn, sourceIndex, loc.line, loc.column]);
    		}

    		if (original[originalCharIndex] === '\n') {
    			loc.line += 1;
    			loc.column = 0;
    			this$1.generatedCodeLine += 1;
    			this$1.raw[this$1.generatedCodeLine] = this$1.rawSegments = [];
    			this$1.generatedCodeColumn = 0;
    		} else {
    			loc.column += 1;
    			this$1.generatedCodeColumn += 1;
    		}

    		originalCharIndex += 1;
    		first = false;
    	}

    	this.pending = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
    };

    Mappings.prototype.advance = function advance (str) {
    		var this$1 = this;

    	if (!str) { return; }

    	var lines = str.split('\n');

    	if (lines.length > 1) {
    		for (var i = 0; i < lines.length - 1; i++) {
    			this$1.generatedCodeLine++;
    			this$1.raw[this$1.generatedCodeLine] = this$1.rawSegments = [];
    		}
    		this.generatedCodeColumn = 0;
    	}

    	this.generatedCodeColumn += lines[lines.length - 1].length;
    };

    var warned = {
    	insertLeft: false,
    	insertRight: false,
    	storeName: false
    };

    var MagicString = function MagicString(string, options) {
    	if ( options === void 0 ) options = {};

    	var chunk = new Chunk(0, string.length, string);

    	Object.defineProperties(this, {
    		original:              { writable: true, value: string },
    		outro:                 { writable: true, value: '' },
    		intro:                 { writable: true, value: '' },
    		firstChunk:            { writable: true, value: chunk },
    		lastChunk:             { writable: true, value: chunk },
    		lastSearchedChunk:     { writable: true, value: chunk },
    		byStart:               { writable: true, value: {} },
    		byEnd:                 { writable: true, value: {} },
    		filename:              { writable: true, value: options.filename },
    		indentExclusionRanges: { writable: true, value: options.indentExclusionRanges },
    		sourcemapLocations:    { writable: true, value: {} },
    		storedNames:           { writable: true, value: {} },
    		indentStr:             { writable: true, value: guessIndent(string) }
    	});

    	this.byStart[0] = chunk;
    	this.byEnd[string.length] = chunk;
    };

    MagicString.prototype.addSourcemapLocation = function addSourcemapLocation (char) {
    	this.sourcemapLocations[char] = true;
    };

    MagicString.prototype.append = function append (content) {
    	if (typeof content !== 'string') { throw new TypeError('outro content must be a string'); }

    	this.outro += content;
    	return this;
    };

    MagicString.prototype.appendLeft = function appendLeft (index, content) {
    	if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }

    	this._split(index);

    	var chunk = this.byEnd[index];

    	if (chunk) {
    		chunk.appendLeft(content);
    	} else {
    		this.intro += content;
    	}
    	return this;
    };

    MagicString.prototype.appendRight = function appendRight (index, content) {
    	if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }

    	this._split(index);

    	var chunk = this.byStart[index];

    	if (chunk) {
    		chunk.appendRight(content);
    	} else {
    		this.outro += content;
    	}
    	return this;
    };

    MagicString.prototype.clone = function clone () {
    	var cloned = new MagicString(this.original, { filename: this.filename });

    	var originalChunk = this.firstChunk;
    	var clonedChunk = (cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone());

    	while (originalChunk) {
    		cloned.byStart[clonedChunk.start] = clonedChunk;
    		cloned.byEnd[clonedChunk.end] = clonedChunk;

    		var nextOriginalChunk = originalChunk.next;
    		var nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone();

    		if (nextClonedChunk) {
    			clonedChunk.next = nextClonedChunk;
    			nextClonedChunk.previous = clonedChunk;

    			clonedChunk = nextClonedChunk;
    		}

    		originalChunk = nextOriginalChunk;
    	}

    	cloned.lastChunk = clonedChunk;

    	if (this.indentExclusionRanges) {
    		cloned.indentExclusionRanges = this.indentExclusionRanges.slice();
    	}

    	Object.keys(this.sourcemapLocations).forEach(function (loc) {
    		cloned.sourcemapLocations[loc] = true;
    	});

    	return cloned;
    };

    MagicString.prototype.generateDecodedMap = function generateDecodedMap (options) {
    		var this$1 = this;

    	options = options || {};

    	var sourceIndex = 0;
    	var names = Object.keys(this.storedNames);
    	var mappings = new Mappings(options.hires);

    	var locate = getLocator$1(this.original);

    	if (this.intro) {
    		mappings.advance(this.intro);
    	}

    	this.firstChunk.eachNext(function (chunk) {
    		var loc = locate(chunk.start);

    		if (chunk.intro.length) { mappings.advance(chunk.intro); }

    		if (chunk.edited) {
    			mappings.addEdit(
    				sourceIndex,
    				chunk.content,
    				loc,
    				chunk.storeName ? names.indexOf(chunk.original) : -1
    			);
    		} else {
    			mappings.addUneditedChunk(sourceIndex, chunk, this$1.original, loc, this$1.sourcemapLocations);
    		}

    		if (chunk.outro.length) { mappings.advance(chunk.outro); }
    	});

    	return {
    		file: options.file ? options.file.split(/[/\\]/).pop() : null,
    		sources: [options.source ? getRelativePath(options.file || '', options.source) : null],
    		sourcesContent: options.includeContent ? [this.original] : [null],
    		names: names,
    		mappings: mappings.raw
    	};
    };

    MagicString.prototype.generateMap = function generateMap (options) {
    	return new SourceMap(this.generateDecodedMap(options));
    };

    MagicString.prototype.getIndentString = function getIndentString () {
    	return this.indentStr === null ? '\t' : this.indentStr;
    };

    MagicString.prototype.indent = function indent (indentStr, options) {
    		var this$1 = this;

    	var pattern = /^[^\r\n]/gm;

    	if (isObject(indentStr)) {
    		options = indentStr;
    		indentStr = undefined;
    	}

    	indentStr = indentStr !== undefined ? indentStr : this.indentStr || '\t';

    	if (indentStr === '') { return this; } // noop

    	options = options || {};

    	// Process exclusion ranges
    	var isExcluded = {};

    	if (options.exclude) {
    		var exclusions =
    			typeof options.exclude[0] === 'number' ? [options.exclude] : options.exclude;
    		exclusions.forEach(function (exclusion) {
    			for (var i = exclusion[0]; i < exclusion[1]; i += 1) {
    				isExcluded[i] = true;
    			}
    		});
    	}

    	var shouldIndentNextCharacter = options.indentStart !== false;
    	var replacer = function (match) {
    		if (shouldIndentNextCharacter) { return ("" + indentStr + match); }
    		shouldIndentNextCharacter = true;
    		return match;
    	};

    	this.intro = this.intro.replace(pattern, replacer);

    	var charIndex = 0;
    	var chunk = this.firstChunk;

    	while (chunk) {
    		var end = chunk.end;

    		if (chunk.edited) {
    			if (!isExcluded[charIndex]) {
    				chunk.content = chunk.content.replace(pattern, replacer);

    				if (chunk.content.length) {
    					shouldIndentNextCharacter = chunk.content[chunk.content.length - 1] === '\n';
    				}
    			}
    		} else {
    			charIndex = chunk.start;

    			while (charIndex < end) {
    				if (!isExcluded[charIndex]) {
    					var char = this$1.original[charIndex];

    					if (char === '\n') {
    						shouldIndentNextCharacter = true;
    					} else if (char !== '\r' && shouldIndentNextCharacter) {
    						shouldIndentNextCharacter = false;

    						if (charIndex === chunk.start) {
    							chunk.prependRight(indentStr);
    						} else {
    							this$1._splitChunk(chunk, charIndex);
    							chunk = chunk.next;
    							chunk.prependRight(indentStr);
    						}
    					}
    				}

    				charIndex += 1;
    			}
    		}

    		charIndex = chunk.end;
    		chunk = chunk.next;
    	}

    	this.outro = this.outro.replace(pattern, replacer);

    	return this;
    };

    MagicString.prototype.insert = function insert () {
    	throw new Error('magicString.insert(...) is deprecated. Use prependRight(...) or appendLeft(...)');
    };

    MagicString.prototype.insertLeft = function insertLeft (index, content) {
    	if (!warned.insertLeft) {
    		console.warn('magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead'); // eslint-disable-line no-console
    		warned.insertLeft = true;
    	}

    	return this.appendLeft(index, content);
    };

    MagicString.prototype.insertRight = function insertRight (index, content) {
    	if (!warned.insertRight) {
    		console.warn('magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead'); // eslint-disable-line no-console
    		warned.insertRight = true;
    	}

    	return this.prependRight(index, content);
    };

    MagicString.prototype.move = function move (start, end, index) {
    	if (index >= start && index <= end) { throw new Error('Cannot move a selection inside itself'); }

    	this._split(start);
    	this._split(end);
    	this._split(index);

    	var first = this.byStart[start];
    	var last = this.byEnd[end];

    	var oldLeft = first.previous;
    	var oldRight = last.next;

    	var newRight = this.byStart[index];
    	if (!newRight && last === this.lastChunk) { return this; }
    	var newLeft = newRight ? newRight.previous : this.lastChunk;

    	if (oldLeft) { oldLeft.next = oldRight; }
    	if (oldRight) { oldRight.previous = oldLeft; }

    	if (newLeft) { newLeft.next = first; }
    	if (newRight) { newRight.previous = last; }

    	if (!first.previous) { this.firstChunk = last.next; }
    	if (!last.next) {
    		this.lastChunk = first.previous;
    		this.lastChunk.next = null;
    	}

    	first.previous = newLeft;
    	last.next = newRight || null;

    	if (!newLeft) { this.firstChunk = first; }
    	if (!newRight) { this.lastChunk = last; }
    	return this;
    };

    MagicString.prototype.overwrite = function overwrite (start, end, content, options) {
    		var this$1 = this;

    	if (typeof content !== 'string') { throw new TypeError('replacement content must be a string'); }

    	while (start < 0) { start += this$1.original.length; }
    	while (end < 0) { end += this$1.original.length; }

    	if (end > this.original.length) { throw new Error('end is out of bounds'); }
    	if (start === end)
    		{ throw new Error('Cannot overwrite a zero-length range – use appendLeft or prependRight instead'); }

    	this._split(start);
    	this._split(end);

    	if (options === true) {
    		if (!warned.storeName) {
    			console.warn('The final argument to magicString.overwrite(...) should be an options object. See https://github.com/rich-harris/magic-string'); // eslint-disable-line no-console
    			warned.storeName = true;
    		}

    		options = { storeName: true };
    	}
    	var storeName = options !== undefined ? options.storeName : false;
    	var contentOnly = options !== undefined ? options.contentOnly : false;

    	if (storeName) {
    		var original = this.original.slice(start, end);
    		this.storedNames[original] = true;
    	}

    	var first = this.byStart[start];
    	var last = this.byEnd[end];

    	if (first) {
    		if (end > first.end && first.next !== this.byStart[first.end]) {
    			throw new Error('Cannot overwrite across a split point');
    		}

    		first.edit(content, storeName, contentOnly);

    		if (first !== last) {
    			var chunk = first.next;
    			while (chunk !== last) {
    				chunk.edit('', false);
    				chunk = chunk.next;
    			}

    			chunk.edit('', false);
    		}
    	} else {
    		// must be inserting at the end
    		var newChunk = new Chunk(start, end, '').edit(content, storeName);

    		// TODO last chunk in the array may not be the last chunk, if it's moved...
    		last.next = newChunk;
    		newChunk.previous = last;
    	}
    	return this;
    };

    MagicString.prototype.prepend = function prepend (content) {
    	if (typeof content !== 'string') { throw new TypeError('outro content must be a string'); }

    	this.intro = content + this.intro;
    	return this;
    };

    MagicString.prototype.prependLeft = function prependLeft (index, content) {
    	if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }

    	this._split(index);

    	var chunk = this.byEnd[index];

    	if (chunk) {
    		chunk.prependLeft(content);
    	} else {
    		this.intro = content + this.intro;
    	}
    	return this;
    };

    MagicString.prototype.prependRight = function prependRight (index, content) {
    	if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }

    	this._split(index);

    	var chunk = this.byStart[index];

    	if (chunk) {
    		chunk.prependRight(content);
    	} else {
    		this.outro = content + this.outro;
    	}
    	return this;
    };

    MagicString.prototype.remove = function remove (start, end) {
    		var this$1 = this;

    	while (start < 0) { start += this$1.original.length; }
    	while (end < 0) { end += this$1.original.length; }

    	if (start === end) { return this; }

    	if (start < 0 || end > this.original.length) { throw new Error('Character is out of bounds'); }
    	if (start > end) { throw new Error('end must be greater than start'); }

    	this._split(start);
    	this._split(end);

    	var chunk = this.byStart[start];

    	while (chunk) {
    		chunk.intro = '';
    		chunk.outro = '';
    		chunk.edit('');

    		chunk = end > chunk.end ? this$1.byStart[chunk.end] : null;
    	}
    	return this;
    };

    MagicString.prototype.lastChar = function lastChar () {
    	var chunk = this.lastChunk;
    	do {
    		if (chunk.outro.length)
    			{ return chunk.outro[chunk.outro.length - 1]; }
    		if (chunk.content.length)
    			{ return chunk.content[chunk.content.length - 1]; }
    		if (chunk.intro.length)
    			{ return chunk.intro[chunk.intro.length - 1]; }
    	} while (chunk = chunk.previous);
    	return '';
    };

    MagicString.prototype.slice = function slice (start, end) {
    		var this$1 = this;
    		if ( start === void 0 ) start = 0;
    		if ( end === void 0 ) end = this.original.length;

    	while (start < 0) { start += this$1.original.length; }
    	while (end < 0) { end += this$1.original.length; }

    	var result = '';

    	// find start chunk
    	var chunk = this.firstChunk;
    	while (chunk && (chunk.start > start || chunk.end <= start)) {
    		// found end chunk before start
    		if (chunk.start < end && chunk.end >= end) {
    			return result;
    		}

    		chunk = chunk.next;
    	}

    	if (chunk && chunk.edited && chunk.start !== start)
    		{ throw new Error(("Cannot use replaced character " + start + " as slice start anchor.")); }

    	var startChunk = chunk;
    	while (chunk) {
    		if (chunk.intro && (startChunk !== chunk || chunk.start === start)) {
    			result += chunk.intro;
    		}

    		var containsEnd = chunk.start < end && chunk.end >= end;
    		if (containsEnd && chunk.edited && chunk.end !== end)
    			{ throw new Error(("Cannot use replaced character " + end + " as slice end anchor.")); }

    		var sliceStart = startChunk === chunk ? start - chunk.start : 0;
    		var sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length;

    		result += chunk.content.slice(sliceStart, sliceEnd);

    		if (chunk.outro && (!containsEnd || chunk.end === end)) {
    			result += chunk.outro;
    		}

    		if (containsEnd) {
    			break;
    		}

    		chunk = chunk.next;
    	}

    	return result;
    };

    // TODO deprecate this? not really very useful
    MagicString.prototype.snip = function snip (start, end) {
    	var clone = this.clone();
    	clone.remove(0, start);
    	clone.remove(end, clone.original.length);

    	return clone;
    };

    MagicString.prototype._split = function _split (index) {
    		var this$1 = this;

    	if (this.byStart[index] || this.byEnd[index]) { return; }

    	var chunk = this.lastSearchedChunk;
    	var searchForward = index > chunk.end;

    	while (chunk) {
    		if (chunk.contains(index)) { return this$1._splitChunk(chunk, index); }

    		chunk = searchForward ? this$1.byStart[chunk.end] : this$1.byEnd[chunk.start];
    	}
    };

    MagicString.prototype._splitChunk = function _splitChunk (chunk, index) {
    	if (chunk.edited && chunk.content.length) {
    		// zero-length edited chunks are a special case (overlapping replacements)
    		var loc = getLocator$1(this.original)(index);
    		throw new Error(
    			("Cannot split a chunk that has already been edited (" + (loc.line) + ":" + (loc.column) + " – \"" + (chunk.original) + "\")")
    		);
    	}

    	var newChunk = chunk.split(index);

    	this.byEnd[index] = chunk;
    	this.byStart[index] = newChunk;
    	this.byEnd[newChunk.end] = newChunk;

    	if (chunk === this.lastChunk) { this.lastChunk = newChunk; }

    	this.lastSearchedChunk = chunk;
    	return true;
    };

    MagicString.prototype.toString = function toString () {
    	var str = this.intro;

    	var chunk = this.firstChunk;
    	while (chunk) {
    		str += chunk.toString();
    		chunk = chunk.next;
    	}

    	return str + this.outro;
    };

    MagicString.prototype.isEmpty = function isEmpty () {
    	var chunk = this.firstChunk;
    	do {
    		if (chunk.intro.length && chunk.intro.trim() ||
    				chunk.content.length && chunk.content.trim() ||
    				chunk.outro.length && chunk.outro.trim())
    			{ return false; }
    	} while (chunk = chunk.next);
    	return true;
    };

    MagicString.prototype.trimLines = function trimLines () {
    	return this.trim('[\\r\\n]');
    };

    MagicString.prototype.trim = function trim (charType) {
    	return this.trimStart(charType).trimEnd(charType);
    };

    MagicString.prototype.trimEndAborted = function trimEndAborted (charType) {
    		var this$1 = this;

    	var rx = new RegExp((charType || '\\s') + '+$');

    	this.outro = this.outro.replace(rx, '');
    	if (this.outro.length) { return true; }

    	var chunk = this.lastChunk;

    	do {
    		var end = chunk.end;
    		var aborted = chunk.trimEnd(rx);

    		// if chunk was trimmed, we have a new lastChunk
    		if (chunk.end !== end) {
    			if (this$1.lastChunk === chunk) {
    				this$1.lastChunk = chunk.next;
    			}

    			this$1.byEnd[chunk.end] = chunk;
    			this$1.byStart[chunk.next.start] = chunk.next;
    			this$1.byEnd[chunk.next.end] = chunk.next;
    		}

    		if (aborted) { return true; }
    		chunk = chunk.previous;
    	} while (chunk);

    	return false;
    };

    MagicString.prototype.trimEnd = function trimEnd (charType) {
    	this.trimEndAborted(charType);
    	return this;
    };
    MagicString.prototype.trimStartAborted = function trimStartAborted (charType) {
    		var this$1 = this;

    	var rx = new RegExp('^' + (charType || '\\s') + '+');

    	this.intro = this.intro.replace(rx, '');
    	if (this.intro.length) { return true; }

    	var chunk = this.firstChunk;

    	do {
    		var end = chunk.end;
    		var aborted = chunk.trimStart(rx);

    		if (chunk.end !== end) {
    			// special case...
    			if (chunk === this$1.lastChunk) { this$1.lastChunk = chunk.next; }

    			this$1.byEnd[chunk.end] = chunk;
    			this$1.byStart[chunk.next.start] = chunk.next;
    			this$1.byEnd[chunk.next.end] = chunk.next;
    		}

    		if (aborted) { return true; }
    		chunk = chunk.next;
    	} while (chunk);

    	return false;
    };

    MagicString.prototype.trimStart = function trimStart (charType) {
    	this.trimStartAborted(charType);
    	return this;
    };

    var hasOwnProp = Object.prototype.hasOwnProperty;

    var Bundle = function Bundle(options) {
    	if ( options === void 0 ) options = {};

    	this.intro = options.intro || '';
    	this.separator = options.separator !== undefined ? options.separator : '\n';
    	this.sources = [];
    	this.uniqueSources = [];
    	this.uniqueSourceIndexByFilename = {};
    };

    Bundle.prototype.addSource = function addSource (source) {
    	if (source instanceof MagicString) {
    		return this.addSource({
    			content: source,
    			filename: source.filename,
    			separator: this.separator
    		});
    	}

    	if (!isObject(source) || !source.content) {
    		throw new Error('bundle.addSource() takes an object with a `content` property, which should be an instance of MagicString, and an optional `filename`');
    	}

    	['filename', 'indentExclusionRanges', 'separator'].forEach(function (option) {
    		if (!hasOwnProp.call(source, option)) { source[option] = source.content[option]; }
    	});

    	if (source.separator === undefined) {
    		// TODO there's a bunch of this sort of thing, needs cleaning up
    		source.separator = this.separator;
    	}

    	if (source.filename) {
    		if (!hasOwnProp.call(this.uniqueSourceIndexByFilename, source.filename)) {
    			this.uniqueSourceIndexByFilename[source.filename] = this.uniqueSources.length;
    			this.uniqueSources.push({ filename: source.filename, content: source.content.original });
    		} else {
    			var uniqueSource = this.uniqueSources[this.uniqueSourceIndexByFilename[source.filename]];
    			if (source.content.original !== uniqueSource.content) {
    				throw new Error(("Illegal source: same filename (" + (source.filename) + "), different contents"));
    			}
    		}
    	}

    	this.sources.push(source);
    	return this;
    };

    Bundle.prototype.append = function append (str, options) {
    	this.addSource({
    		content: new MagicString(str),
    		separator: (options && options.separator) || ''
    	});

    	return this;
    };

    Bundle.prototype.clone = function clone () {
    	var bundle = new Bundle({
    		intro: this.intro,
    		separator: this.separator
    	});

    	this.sources.forEach(function (source) {
    		bundle.addSource({
    			filename: source.filename,
    			content: source.content.clone(),
    			separator: source.separator
    		});
    	});

    	return bundle;
    };

    Bundle.prototype.generateDecodedMap = function generateDecodedMap (options) {
    		var this$1 = this;
    		if ( options === void 0 ) options = {};

    	var names = [];
    	this.sources.forEach(function (source) {
    		Object.keys(source.content.storedNames).forEach(function (name) {
    			if (!~names.indexOf(name)) { names.push(name); }
    		});
    	});

    	var mappings = new Mappings(options.hires);

    	if (this.intro) {
    		mappings.advance(this.intro);
    	}

    	this.sources.forEach(function (source, i) {
    		if (i > 0) {
    			mappings.advance(this$1.separator);
    		}

    		var sourceIndex = source.filename ? this$1.uniqueSourceIndexByFilename[source.filename] : -1;
    		var magicString = source.content;
    		var locate = getLocator$1(magicString.original);

    		if (magicString.intro) {
    			mappings.advance(magicString.intro);
    		}

    		magicString.firstChunk.eachNext(function (chunk) {
    			var loc = locate(chunk.start);

    			if (chunk.intro.length) { mappings.advance(chunk.intro); }

    			if (source.filename) {
    				if (chunk.edited) {
    					mappings.addEdit(
    						sourceIndex,
    						chunk.content,
    						loc,
    						chunk.storeName ? names.indexOf(chunk.original) : -1
    					);
    				} else {
    					mappings.addUneditedChunk(
    						sourceIndex,
    						chunk,
    						magicString.original,
    						loc,
    						magicString.sourcemapLocations
    					);
    				}
    			} else {
    				mappings.advance(chunk.content);
    			}

    			if (chunk.outro.length) { mappings.advance(chunk.outro); }
    		});

    		if (magicString.outro) {
    			mappings.advance(magicString.outro);
    		}
    	});

    	return {
    		file: options.file ? options.file.split(/[/\\]/).pop() : null,
    		sources: this.uniqueSources.map(function (source) {
    			return options.file ? getRelativePath(options.file, source.filename) : source.filename;
    		}),
    		sourcesContent: this.uniqueSources.map(function (source) {
    			return options.includeContent ? source.content : null;
    		}),
    		names: names,
    		mappings: mappings.raw
    	};
    };

    Bundle.prototype.generateMap = function generateMap (options) {
    	return new SourceMap(this.generateDecodedMap(options));
    };

    Bundle.prototype.getIndentString = function getIndentString () {
    	var indentStringCounts = {};

    	this.sources.forEach(function (source) {
    		var indentStr = source.content.indentStr;

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

    		if (!indentStringCounts[indentStr]) { indentStringCounts[indentStr] = 0; }
    		indentStringCounts[indentStr] += 1;
    	});

    	return (
    		Object.keys(indentStringCounts).sort(function (a, b) {
    			return indentStringCounts[a] - indentStringCounts[b];
    		})[0] || '\t'
    	);
    };

    Bundle.prototype.indent = function indent (indentStr) {
    		var this$1 = this;

    	if (!arguments.length) {
    		indentStr = this.getIndentString();
    	}

    	if (indentStr === '') { return this; } // noop

    	var trailingNewline = !this.intro || this.intro.slice(-1) === '\n';

    	this.sources.forEach(function (source, i) {
    		var separator = source.separator !== undefined ? source.separator : this$1.separator;
    		var indentStart = trailingNewline || (i > 0 && /\r?\n$/.test(separator));

    		source.content.indent(indentStr, {
    			exclude: source.indentExclusionRanges,
    			indentStart: indentStart //: trailingNewline || /\r?\n$/.test( separator )  //true///\r?\n/.test( separator )
    		});

    		trailingNewline = source.content.lastChar() === '\n';
    	});

    	if (this.intro) {
    		this.intro =
    			indentStr +
    			this.intro.replace(/^[^\n]/gm, function (match, index) {
    				return index > 0 ? indentStr + match : match;
    			});
    	}

    	return this;
    };

    Bundle.prototype.prepend = function prepend (str) {
    	this.intro = str + this.intro;
    	return this;
    };

    Bundle.prototype.toString = function toString () {
    		var this$1 = this;

    	var body = this.sources
    		.map(function (source, i) {
    			var separator = source.separator !== undefined ? source.separator : this$1.separator;
    			var str = (i > 0 ? separator : '') + source.content.toString();

    			return str;
    		})
    		.join('');

    	return this.intro + body;
    };

    Bundle.prototype.isEmpty = function isEmpty () {
    	if (this.intro.length && this.intro.trim())
    		{ return false; }
    	if (this.sources.some(function (source) { return !source.content.isEmpty(); }))
    		{ return false; }
    	return true;
    };

    Bundle.prototype.trimLines = function trimLines () {
    	return this.trim('[\\r\\n]');
    };

    Bundle.prototype.trim = function trim (charType) {
    	return this.trimStart(charType).trimEnd(charType);
    };

    Bundle.prototype.trimStart = function trimStart (charType) {
    		var this$1 = this;

    	var rx = new RegExp('^' + (charType || '\\s') + '+');
    	this.intro = this.intro.replace(rx, '');

    	if (!this.intro) {
    		var source;
    		var i = 0;

    		do {
    			source = this$1.sources[i++];
    			if (!source) {
    				break;
    			}
    		} while (!source.content.trimStartAborted(charType));
    	}

    	return this;
    };

    Bundle.prototype.trimEnd = function trimEnd (charType) {
    		var this$1 = this;

    	var rx = new RegExp((charType || '\\s') + '+$');

    	var source;
    	var i = this.sources.length - 1;

    	do {
    		source = this$1.sources[i--];
    		if (!source) {
    			this$1.intro = this$1.intro.replace(rx, '');
    			break;
    		}
    	} while (!source.content.trimEndAborted(charType));

    	return this;
    };

    const keys = {
        ObjectExpression: 'properties',
        Program: 'body',
    };
    const offsets = {
        ObjectExpression: [1, -1],
        Program: [0, 0],
    };
    function removeNode(code, parent, node) {
        const key = keys[parent.type];
        const offset = offsets[parent.type];
        if (!key || !offset)
            throw new Error(`not implemented: ${parent.type}`);
        const list = parent[key];
        const i = list.indexOf(node);
        if (i === -1)
            throw new Error('node not in list');
        let a;
        let b;
        if (list.length === 1) {
            // remove everything, leave {}
            a = parent.start + offset[0];
            b = parent.end + offset[1];
        }
        else if (i === 0) {
            // remove everything before second node, including comments
            a = parent.start + offset[0];
            while (/\s/.test(code.original[a]))
                a += 1;
            b = list[i].end;
            while (/[\s,]/.test(code.original[b]))
                b += 1;
        }
        else {
            // remove the end of the previous node to the end of this one
            a = list[i - 1].end;
            b = node.end;
        }
        code.remove(a, b);
        list.splice(i, 1);
        return;
    }

    const wrappers = { es, amd, cjs, iife, umd, eval: expr };
    function wrapModule(code, format, name, options, banner, sharedPath, helpers, imports, shorthandImports, source) {
        if (format === 'es')
            return es(code, name, options, banner, sharedPath, helpers, imports, shorthandImports, source);
        const dependencies = imports.map((declaration, i) => {
            const defaultImport = declaration.specifiers.find((x) => x.type === 'ImportDefaultSpecifier' ||
                (x.type === 'ImportSpecifier' && x.imported.name === 'default'));
            const namespaceImport = declaration.specifiers.find((x) => x.type === 'ImportNamespaceSpecifier');
            const namedImports = declaration.specifiers.filter((x) => x.type === 'ImportSpecifier' && x.imported.name !== 'default');
            const name = defaultImport || namespaceImport
                ? (defaultImport || namespaceImport).local.name
                : `__import${i}`;
            const statements = [];
            namedImports.forEach((specifier) => {
                statements.push(`var ${specifier.local.name} = ${name}.${specifier.imported.name};`);
            });
            if (defaultImport) {
                statements.push(`${name} = (${name} && ${name}.__esModule) ? ${name}["default"] : ${name};`);
            }
            return { name, statements, source: declaration.source.value };
        })
            .concat(shorthandImports.map(({ name, source }) => ({
            name,
            statements: [
                `${name} = (${name} && ${name}.__esModule) ? ${name}["default"] : ${name};`,
            ],
            source,
        })));
        if (format === 'amd')
            return amd(code, name, options, banner, dependencies);
        if (format === 'cjs')
            return cjs(code, name, options, banner, sharedPath, helpers, dependencies);
        if (format === 'iife')
            return iife(code, name, options, banner, dependencies);
        if (format === 'umd')
            return umd(code, name, options, banner, dependencies);
        if (format === 'eval')
            return expr(code, name, options, banner, dependencies);
        throw new Error(`options.format is invalid (must be ${list$2(Object.keys(wrappers))})`);
    }
    function es(code, name, options, banner, sharedPath, helpers, imports, shorthandImports, source) {
        const importHelpers = helpers.length > 0 && (`import { ${helpers.map(h => h.name === h.alias ? h.name : `${h.name} as ${h.alias}`).join(', ')} } from ${JSON.stringify(sharedPath)};`);
        const importBlock = imports.length > 0 && (imports
            .map((declaration) => source.slice(declaration.start, declaration.end))
            .join('\n'));
        const shorthandImportBlock = shorthandImports.length > 0 && (shorthandImports.map(({ name, source }) => `import ${name} from ${JSON.stringify(source)};`).join('\n'));
        return deindent `
		${banner}
		${importHelpers}
		${importBlock}
		${shorthandImportBlock}

		${code}
		export default ${name};`;
    }
    function amd(code, name, options, banner, dependencies) {
        const sourceString = dependencies.length
            ? `[${dependencies.map(d => `"${removeExtension(d.source)}"`).join(', ')}], `
            : '';
        const id = options.amd && options.amd.id;
        return deindent `
		define(${id ? `"${id}", ` : ''}${sourceString}function(${paramString(dependencies)}) { "use strict";
			${getCompatibilityStatements(dependencies)}

			${code}
			return ${name};
		});`;
    }
    function cjs(code, name, options, banner, sharedPath, helpers, dependencies) {
        const helperDeclarations = helpers.map(h => `${h.alias === h.name ? h.name : `${h.name}: ${h.alias}`}`).join(', ');
        const helperBlock = helpers.length > 0 && (`var { ${helperDeclarations} } = require(${JSON.stringify(sharedPath)});\n`);
        const requireBlock = dependencies.length > 0 && (dependencies
            .map(d => `var ${d.name} = require("${d.source}");`)
            .join('\n\n'));
        return deindent `
		${banner}
		"use strict";

		${helperBlock}
		${requireBlock}
		${getCompatibilityStatements(dependencies)}

		${code}

		module.exports = ${name};`;
    }
    function iife(code, name, options, banner, dependencies) {
        if (!options.name) {
            throw new Error(`Missing required 'name' option for IIFE export`);
        }
        const globals = getGlobals(dependencies, options);
        return deindent `
		${banner}
		var ${options.name} = (function(${paramString(dependencies)}) { "use strict";
			${getCompatibilityStatements(dependencies)}

			${code}
			return ${name};
		}(${globals.join(', ')}));`;
    }
    function umd(code, name, options, banner, dependencies) {
        if (!options.name) {
            throw new Error(`Missing required 'name' option for UMD export`);
        }
        const amdId = options.amd && options.amd.id ? `'${options.amd.id}', ` : '';
        const amdDeps = dependencies.length
            ? `[${dependencies.map(d => `"${removeExtension(d.source)}"`).join(', ')}], `
            : '';
        const cjsDeps = dependencies
            .map(d => `require("${d.source}")`)
            .join(', ');
        const globals = getGlobals(dependencies, options);
        return deindent `
		${banner}
		(function(global, factory) {
			typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory(${cjsDeps}) :
			typeof define === "function" && define.amd ? define(${amdId}${amdDeps}factory) :
			(global.${options.name} = factory(${globals.join(', ')}));
		}(this, (function (${paramString(dependencies)}) { "use strict";

			${getCompatibilityStatements(dependencies)}

			${code}

			return ${name};

		})));`;
    }
    function expr(code, name, options, banner, dependencies) {
        const globals = getGlobals(dependencies, options);
        return deindent `
		(function (${paramString(dependencies)}) { "use strict";
			${banner}

			${getCompatibilityStatements(dependencies)}

			${code}

			return ${name};
		}(${globals.join(', ')}))`;
    }
    function paramString(dependencies) {
        return dependencies.map(dep => dep.name).join(', ');
    }
    function removeExtension(file) {
        const index = file.lastIndexOf('.');
        return ~index ? file.slice(0, index) : file;
    }
    function getCompatibilityStatements(dependencies) {
        if (!dependencies.length)
            return null;
        const statements = [];
        dependencies.forEach(dependency => {
            statements.push(...dependency.statements);
        });
        return statements.join('\n');
    }
    function getGlobals(dependencies, options) {
        const { globals, onerror, onwarn } = options;
        const globalFn = getGlobalFn(globals);
        return dependencies.map(d => {
            let name = globalFn(d.source);
            if (!name) {
                if (d.name.startsWith('__import')) {
                    const error = new Error(`Could not determine name for imported module '${d.source}' – use options.globals`);
                    onerror(error);
                }
                else {
                    const warning = {
                        code: `options-missing-globals`,
                        message: `No name was supplied for imported module '${d.source}'. Guessing '${d.name}', but you should use options.globals`,
                    };
                    onwarn(warning);
                }
                name = d.name;
            }
            return name;
        });
    }
    function getGlobalFn(globals) {
        if (typeof globals === 'function')
            return globals;
        if (typeof globals === 'object') {
            return id => globals[id];
        }
        return () => undefined;
    }

    function createScopes(expression) {
        const map = new WeakMap();
        const globals = new Set();
        let scope = new Scope(null, false);
        walk(expression, {
            enter(node, parent) {
                if (/Function/.test(node.type)) {
                    if (node.type === 'FunctionDeclaration') {
                        scope.declarations.add(node.id.name);
                    }
                    else {
                        scope = new Scope(scope, false);
                        map.set(node, scope);
                        if (node.id)
                            scope.declarations.add(node.id.name);
                    }
                    node.params.forEach((param) => {
                        extractNames(param).forEach(name => {
                            scope.declarations.add(name);
                        });
                    });
                }
                else if (/For(?:In|Of)Statement/.test(node.type)) {
                    scope = new Scope(scope, true);
                    map.set(node, scope);
                }
                else if (node.type === 'BlockStatement') {
                    scope = new Scope(scope, true);
                    map.set(node, scope);
                }
                else if (/(Function|Class|Variable)Declaration/.test(node.type)) {
                    scope.addDeclaration(node);
                }
                else if (isReference(node, parent)) {
                    if (!scope.has(node.name)) {
                        globals.add(node.name);
                    }
                }
            },
            leave(node) {
                if (map.has(node)) {
                    scope = scope.parent;
                }
            },
        });
        return { map, scope, globals };
    }
    // TODO remove this in favour of weakmap version
    function annotateWithScopes(expression) {
        const globals = new Set();
        let scope = new Scope(null, false);
        walk(expression, {
            enter(node, parent) {
                if (/Function/.test(node.type)) {
                    if (node.type === 'FunctionDeclaration') {
                        scope.declarations.add(node.id.name);
                    }
                    else {
                        node._scope = scope = new Scope(scope, false);
                        if (node.id)
                            scope.declarations.add(node.id.name);
                    }
                    node.params.forEach((param) => {
                        extractNames(param).forEach(name => {
                            scope.declarations.add(name);
                        });
                    });
                }
                else if (/For(?:In|Of)Statement/.test(node.type)) {
                    node._scope = scope = new Scope(scope, true);
                }
                else if (node.type === 'BlockStatement') {
                    node._scope = scope = new Scope(scope, true);
                }
                else if (/(Function|Class|Variable)Declaration/.test(node.type)) {
                    scope.addDeclaration(node);
                }
                else if (isReference(node, parent)) {
                    if (!scope.has(node.name)) {
                        globals.add(node.name);
                    }
                }
            },
            leave(node) {
                if (node._scope) {
                    scope = scope.parent;
                }
            },
        });
        return { scope, globals };
    }
    class Scope {
        constructor(parent, block) {
            this.parent = parent;
            this.block = block;
            this.declarations = new Set();
        }
        addDeclaration(node) {
            if (node.kind === 'var' && !this.block && this.parent) {
                this.parent.addDeclaration(node);
            }
            else if (node.type === 'VariableDeclaration') {
                node.declarations.forEach((declarator) => {
                    extractNames(declarator.id).forEach(name => {
                        this.declarations.add(name);
                    });
                });
            }
            else {
                this.declarations.add(node.id.name);
            }
        }
        has(name) {
            return (this.declarations.has(name) || (this.parent && this.parent.has(name)));
        }
    }
    function extractNames(param) {
        const names = [];
        extractors[param.type](names, param);
        return names;
    }
    const extractors = {
        Identifier(names, param) {
            names.push(param.name);
        },
        ObjectPattern(names, param) {
            param.properties.forEach((prop) => {
                extractors[prop.value.type](names, prop.value);
            });
        },
        ArrayPattern(names, param) {
            param.elements.forEach((element) => {
                if (element)
                    extractors[element.type](names, element);
            });
        },
        RestElement(names, param) {
            extractors[param.argument.type](names, param.argument);
        },
        AssignmentPattern(names, param) {
            extractors[param.left.type](names, param.left);
        },
    };

    const test = typeof process !== 'undefined' && process.env.TEST;

    class Node$1 {
        constructor(compiler, parent, scope, info) {
            this.start = info.start;
            this.end = info.end;
            this.type = info.type;
            // this makes properties non-enumerable, which makes logging
            // bearable. might have a performance cost. TODO remove in prod?
            Object.defineProperties(this, {
                compiler: {
                    value: compiler
                },
                parent: {
                    value: parent
                }
            });
        }
        cannotUseInnerHTML() {
            if (this.canUseInnerHTML !== false) {
                this.canUseInnerHTML = false;
                if (this.parent)
                    this.parent.cannotUseInnerHTML();
            }
        }
        init(block, stripWhitespace, nextSibling) {
            // implemented by subclasses
        }
        initChildren(block, stripWhitespace, nextSibling) {
            // glue text nodes together
            const cleaned = [];
            let lastChild;
            let windowComponent;
            this.children.forEach((child) => {
                if (child.type === 'Comment')
                    return;
                // special case — this is an easy way to remove whitespace surrounding
                // <svelte:window/>. lil hacky but it works
                if (child.type === 'Window') {
                    windowComponent = child;
                    return;
                }
                if (child.type === 'Text' && lastChild && lastChild.type === 'Text') {
                    lastChild.data += child.data;
                    lastChild.end = child.end;
                }
                else {
                    if (child.type === 'Text' && stripWhitespace && cleaned.length === 0) {
                        child.data = trimStart(child.data);
                        if (child.data)
                            cleaned.push(child);
                    }
                    else {
                        cleaned.push(child);
                    }
                }
                lastChild = child;
            });
            lastChild = null;
            cleaned.forEach((child, i) => {
                child.canUseInnerHTML = !this.compiler.options.hydratable;
                child.init(block, stripWhitespace, cleaned[i + 1] || nextSibling);
                if (child.shouldSkip)
                    return;
                if (lastChild)
                    lastChild.next = child;
                child.prev = lastChild;
                lastChild = child;
            });
            // We want to remove trailing whitespace inside an element/component/block,
            // *unless* there is no whitespace between this node and its next sibling
            if (stripWhitespace && lastChild && lastChild.type === 'Text') {
                const shouldTrim = (nextSibling ? (nextSibling.type === 'Text' && /^\s/.test(nextSibling.data)) : !this.hasAncestor('EachBlock'));
                if (shouldTrim) {
                    lastChild.data = trimEnd(lastChild.data);
                    if (!lastChild.data) {
                        cleaned.pop();
                        lastChild = cleaned[cleaned.length - 1];
                        lastChild.next = null;
                    }
                }
            }
            this.children = cleaned;
            if (windowComponent)
                cleaned.unshift(windowComponent);
        }
        build(block, parentNode, parentNodes) {
            // implemented by subclasses
        }
        isDomNode() {
            return this.type === 'Element' || this.type === 'Text' || this.type === 'MustacheTag';
        }
        hasAncestor(type) {
            return this.parent ?
                this.parent.type === type || this.parent.hasAncestor(type) :
                false;
        }
        findNearest(selector) {
            if (selector.test(this.type))
                return this;
            if (this.parent)
                return this.parent.findNearest(selector);
        }
        getOrCreateAnchor(block, parentNode, parentNodes) {
            // TODO use this in EachBlock and IfBlock — tricky because
            // children need to be created first
            const needsAnchor = this.next ? !this.next.isDomNode() : !parentNode || !this.parent.isDomNode();
            const anchor = needsAnchor
                ? block.getUniqueName(`${this.var}_anchor`)
                : (this.next && this.next.var) || 'null';
            if (needsAnchor) {
                block.addElement(anchor, `@createComment()`, parentNodes && `@createComment()`, parentNode);
            }
            return anchor;
        }
        getUpdateMountNode(anchor) {
            return this.parent.isDomNode() ? this.parent.var : `${anchor}.parentNode`;
        }
        remount(name) {
            return `${this.var}.m(${name}._slotted.default, null);`;
        }
    }

    class PendingBlock extends Node$1 {
        constructor(compiler, parent, scope, info) {
            super(compiler, parent, scope, info);
            this.children = mapChildren(compiler, parent, scope, info.children);
        }
    }

    class ThenBlock extends Node$1 {
        constructor(compiler, parent, scope, info) {
            super(compiler, parent, scope, info);
            this.children = mapChildren(compiler, parent, scope, info.children);
        }
    }

    class CatchBlock extends Node$1 {
        constructor(compiler, parent, scope, info) {
            super(compiler, parent, scope, info);
            this.children = mapChildren(compiler, parent, scope, info.children);
        }
    }

    function createDebuggingComment(node, compiler) {
        const { locate, source } = compiler;
        let c = node.start;
        if (node.type === 'ElseBlock') {
            while (source[c - 1] !== '{')
                c -= 1;
            while (source[c - 1] === '{')
                c -= 1;
        }
        let d = node.expression ? node.expression.node.end : c;
        while (source[d] !== '}')
            d += 1;
        while (source[d] === '}')
            d += 1;
        const start = locate(c);
        const loc = `(${start.line + 1}:${start.column})`;
        return `${loc} ${source.slice(c, d)}`.replace(/\s/g, ' ');
    }

    const binaryOperators = {
        '**': 15,
        '*': 14,
        '/': 14,
        '%': 14,
        '+': 13,
        '-': 13,
        '<<': 12,
        '>>': 12,
        '>>>': 12,
        '<': 11,
        '<=': 11,
        '>': 11,
        '>=': 11,
        'in': 11,
        'instanceof': 11,
        '==': 10,
        '!=': 10,
        '===': 10,
        '!==': 10,
        '&': 9,
        '^': 8,
        '|': 7
    };
    const logicalOperators = {
        '&&': 6,
        '||': 5
    };
    const precedence = {
        Literal: () => 21,
        Identifier: () => 21,
        ParenthesizedExpression: () => 20,
        MemberExpression: () => 19,
        NewExpression: () => 19,
        CallExpression: () => 19,
        UpdateExpression: () => 17,
        UnaryExpression: () => 16,
        BinaryExpression: (node) => binaryOperators[node.operator],
        LogicalExpression: (node) => logicalOperators[node.operator],
        ConditionalExpression: () => 4,
        AssignmentExpression: () => 3,
        YieldExpression: () => 2,
        SpreadElement: () => 1,
        SequenceExpression: () => 0
    };
    class Expression {
        constructor(compiler, parent, scope, info) {
            // TODO revert to direct property access in prod?
            Object.defineProperties(this, {
                compiler: {
                    value: compiler
                }
            });
            this.node = info;
            this.thisReferences = [];
            this.snippet = `[✂${info.start}-${info.end}✂]`;
            this.usesContext = false;
            const dependencies = new Set();
            const { code, helpers } = compiler;
            let { map, scope: currentScope } = createScopes(info);
            const isEventHandler = parent.type === 'EventHandler';
            const expression = this;
            const isSynthetic = parent.isSynthetic;
            walk(info, {
                enter(node, parent, key) {
                    // don't manipulate shorthand props twice
                    if (key === 'value' && parent.shorthand)
                        return;
                    code.addSourcemapLocation(node.start);
                    code.addSourcemapLocation(node.end);
                    if (map.has(node)) {
                        currentScope = map.get(node);
                        return;
                    }
                    if (node.type === 'ThisExpression') {
                        expression.thisReferences.push(node);
                    }
                    if (isReference(node, parent)) {
                        const { name, nodes } = flattenReference(node);
                        if (currentScope.has(name) || (name === 'event' && isEventHandler))
                            return;
                        if (compiler.helpers.has(name)) {
                            let object = node;
                            while (object.type === 'MemberExpression')
                                object = object.object;
                            const alias = compiler.templateVars.get(`helpers-${name}`);
                            if (alias !== name)
                                code.overwrite(object.start, object.end, alias);
                            return;
                        }
                        expression.usesContext = true;
                        if (!isSynthetic) {
                            // <option> value attribute could be synthetic — avoid double editing
                            code.prependRight(node.start, key === 'key' && parent.shorthand
                                ? `${name}: ctx.`
                                : 'ctx.');
                        }
                        if (scope.names.has(name)) {
                            scope.dependenciesForName.get(name).forEach(dependency => {
                                dependencies.add(dependency);
                            });
                        }
                        else {
                            dependencies.add(name);
                            compiler.expectedProperties.add(name);
                        }
                        if (node.type === 'MemberExpression') {
                            nodes.forEach(node => {
                                code.addSourcemapLocation(node.start);
                                code.addSourcemapLocation(node.end);
                            });
                        }
                        this.skip();
                    }
                },
                leave(node, parent) {
                    if (map.has(node))
                        currentScope = currentScope.parent;
                }
            });
            this.dependencies = dependencies;
        }
        getPrecedence() {
            return this.node.type in precedence ? precedence[this.node.type](this.node) : 0;
        }
        overwriteThis(name) {
            this.thisReferences.forEach(ref => {
                this.compiler.code.overwrite(ref.start, ref.end, name, {
                    storeName: true
                });
            });
        }
    }

    class AwaitBlock extends Node$1 {
        constructor(compiler, parent, scope, info) {
            super(compiler, parent, scope, info);
            this.expression = new Expression(compiler, this, scope, info.expression);
            const deps = this.expression.dependencies;
            this.value = info.value;
            this.error = info.error;
            this.pending = new PendingBlock(compiler, this, scope, info.pending);
            this.then = new ThenBlock(compiler, this, scope.add(this.value, deps), info.then);
            this.catch = new CatchBlock(compiler, this, scope.add(this.error, deps), info.catch);
        }
        init(block, stripWhitespace, nextSibling) {
            this.cannotUseInnerHTML();
            this.var = block.getUniqueName('await_block');
            block.addDependencies(this.expression.dependencies);
            let isDynamic = false;
            let hasIntros = false;
            let hasOutros = false;
            ['pending', 'then', 'catch'].forEach(status => {
                const child = this[status];
                child.block = block.child({
                    comment: createDebuggingComment(child, this.compiler),
                    name: this.compiler.getUniqueName(`create_${status}_block`)
                });
                child.initChildren(child.block, stripWhitespace, nextSibling);
                this.compiler.target.blocks.push(child.block);
                if (child.block.dependencies.size > 0) {
                    isDynamic = true;
                    block.addDependencies(child.block.dependencies);
                }
                if (child.block.hasIntros)
                    hasIntros = true;
                if (child.block.hasOutros)
                    hasOutros = true;
            });
            this.pending.block.hasUpdateMethod = isDynamic;
            this.then.block.hasUpdateMethod = isDynamic;
            this.catch.block.hasUpdateMethod = isDynamic;
            this.pending.block.hasIntroMethod = hasIntros;
            this.then.block.hasIntroMethod = hasIntros;
            this.catch.block.hasIntroMethod = hasIntros;
            this.pending.block.hasOutroMethod = hasOutros;
            this.then.block.hasOutroMethod = hasOutros;
            this.catch.block.hasOutroMethod = hasOutros;
            if (hasOutros && this.compiler.options.nestedTransitions)
                block.addOutro();
        }
        build(block, parentNode, parentNodes) {
            const name = this.var;
            const anchor = this.getOrCreateAnchor(block, parentNode, parentNodes);
            const updateMountNode = this.getUpdateMountNode(anchor);
            const { snippet } = this.expression;
            const info = block.getUniqueName(`info`);
            const promise = block.getUniqueName(`promise`);
            block.addVariable(promise);
            block.maintainContext = true;
            const infoProps = [
                block.alias('component') === 'component' ? 'component' : `component: #component`,
                'ctx',
                'current: null',
                this.pending.block.name && `pending: ${this.pending.block.name}`,
                this.then.block.name && `then: ${this.then.block.name}`,
                this.catch.block.name && `catch: ${this.catch.block.name}`,
                this.then.block.name && `value: '${this.value}'`,
                this.catch.block.name && `error: '${this.error}'`,
                this.pending.block.hasOutroMethod && `blocks: Array(3)`
            ].filter(Boolean);
            block.builders.init.addBlock(deindent `
			let ${info} = {
				${infoProps.join(',\n')}
			};
		`);
            block.builders.init.addBlock(deindent `
			@handlePromise(${promise} = ${snippet}, ${info});
		`);
            block.builders.create.addBlock(deindent `
			${info}.block.c();
		`);
            if (parentNodes) {
                block.builders.claim.addBlock(deindent `
				${info}.block.l(${parentNodes});
			`);
            }
            const initialMountNode = parentNode || '#target';
            const anchorNode = parentNode ? 'null' : 'anchor';
            const hasTransitions = this.pending.block.hasIntroMethod || this.pending.block.hasOutroMethod;
            block.builders.mount.addBlock(deindent `
			${info}.block.${hasTransitions ? 'i' : 'm'}(${initialMountNode}, ${info}.anchor = ${anchorNode});
			${info}.mount = () => ${updateMountNode};
		`);
            const conditions = [];
            if (this.expression.dependencies.size > 0) {
                conditions.push(`(${[...this.expression.dependencies].map(dep => `'${dep}' in changed`).join(' || ')})`);
            }
            conditions.push(`${promise} !== (${promise} = ${snippet})`, `@handlePromise(${promise}, ${info})`);
            block.builders.update.addLine(`${info}.ctx = ctx;`);
            if (this.pending.block.hasUpdateMethod) {
                block.builders.update.addBlock(deindent `
				if (${conditions.join(' && ')}) {
					// nothing
				} else {
					${info}.block.p(changed, @assign(@assign({}, ctx), ${info}.resolved));
				}
			`);
            }
            else {
                block.builders.update.addBlock(deindent `
				${conditions.join(' && ')}
			`);
            }
            if (this.pending.block.hasOutroMethod && this.compiler.options.nestedTransitions) {
                block.builders.outro.addBlock(deindent `
				#outrocallback = @callAfter(#outrocallback, 3);
				for (let #i = 0; #i < 3; #i += 1) {
					const block = ${info}.blocks[#i];
					if (block) block.o(#outrocallback);
					else #outrocallback();
				}
			`);
            }
            block.builders.destroy.addBlock(deindent `
			${info}.block.d(${parentNode ? '' : 'detach'});
			${info} = null;
		`);
            [this.pending, this.then, this.catch].forEach(status => {
                status.children.forEach(child => {
                    child.build(status.block, null, 'nodes');
                });
            });
        }
        ssr() {
            const target = this.compiler.target;
            const { snippet } = this.expression;
            target.append('${(function(__value) { if(@isPromise(__value)) return `');
            this.pending.children.forEach((child) => {
                child.ssr();
            });
            target.append('`; return function(ctx) { return `');
            this.then.children.forEach((child) => {
                child.ssr();
            });
            target.append(`\`;}(Object.assign({}, ctx, { ${this.value}: __value }));}(${snippet})) }`);
        }
    }

    class Comment$2 extends Node$1 {
        constructor(compiler, parent, scope, info) {
            super(compiler, parent, scope, info);
            this.data = info.data;
        }
        ssr() {
            // Allow option to preserve comments, otherwise ignore
            if (this.compiler.options.preserveComments) {
                this.compiler.target.append(`<!--${this.data}-->`);
            }
        }
    }

    function stringifyProps(props) {
        if (!props.length)
            return '{}';
        const joined = props.join(', ');
        if (joined.length > 40) {
            // make larger data objects readable
            return `{\n\t${props.join(',\n\t')}\n}`;
        }
        return `{ ${joined} }`;
    }

    function getTailSnippet(node) {
        const end = node.end;
        while (node.type === 'MemberExpression')
            node = node.object;
        const start = node.end;
        return `[✂${start}-${end}✂]`;
    }

    function getObject(node) {
        while (node.type === 'MemberExpression')
            node = node.object;
        return node;
    }

    function quoteNameIfNecessary(name) {
        if (!isValidIdentifier(name))
            return `"${name}"`;
        return name;
    }
    function quotePropIfNecessary(name) {
        if (!isValidIdentifier(name))
            return `["${name}"]`;
        return `.${name}`;
    }

    const svgAttributes = 'accent-height accumulate additive alignment-baseline allowReorder alphabetic amplitude arabic-form ascent attributeName attributeType autoReverse azimuth baseFrequency baseline-shift baseProfile bbox begin bias by calcMode cap-height class clip clipPathUnits clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering contentScriptType contentStyleType cursor cx cy d decelerate descent diffuseConstant direction display divisor dominant-baseline dur dx dy edgeMode elevation enable-background end exponent externalResourcesRequired fill fill-opacity fill-rule filter filterRes filterUnits flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight format from fr fx fy g1 g2 glyph-name glyph-orientation-horizontal glyph-orientation-vertical glyphRef gradientTransform gradientUnits hanging height href horiz-adv-x horiz-origin-x id ideographic image-rendering in in2 intercept k k1 k2 k3 k4 kernelMatrix kernelUnitLength kerning keyPoints keySplines keyTimes lang lengthAdjust letter-spacing lighting-color limitingConeAngle local marker-end marker-mid marker-start markerHeight markerUnits markerWidth mask maskContentUnits maskUnits mathematical max media method min mode name numOctaves offset onabort onactivate onbegin onclick onend onerror onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup onrepeat onresize onscroll onunload opacity operator order orient orientation origin overflow overline-position overline-thickness panose-1 paint-order pathLength patternContentUnits patternTransform patternUnits pointer-events points pointsAtX pointsAtY pointsAtZ preserveAlpha preserveAspectRatio primitiveUnits r radius refX refY rendering-intent repeatCount repeatDur requiredExtensions requiredFeatures restart result rotate rx ry scale seed shape-rendering slope spacing specularConstant specularExponent speed spreadMethod startOffset stdDeviation stemh stemv stitchTiles stop-color stop-opacity strikethrough-position strikethrough-thickness string stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style surfaceScale systemLanguage tabindex tableValues target targetX targetY text-anchor text-decoration text-rendering textLength to transform type u1 u2 underline-position underline-thickness unicode unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical values version vert-adv-y vert-origin-x vert-origin-y viewBox viewTarget visibility width widths word-spacing writing-mode x x-height x1 x2 xChannelSelector xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y y1 y2 yChannelSelector z zoomAndPan'.split(' ');
    const svgAttributeLookup = new Map();
    svgAttributes.forEach(name => {
        svgAttributeLookup.set(name.toLowerCase(), name);
    });
    function fixAttributeCasing(name) {
        name = name.toLowerCase();
        return svgAttributeLookup.get(name) || name;
    }

    function addToSet(a, b) {
        b.forEach(item => {
            a.add(item);
        });
    }

    class Attribute extends Node$1 {
        constructor(compiler, parent, scope, info) {
            super(compiler, parent, scope, info);
            if (info.type === 'Spread') {
                this.name = null;
                this.isSpread = true;
                this.isTrue = false;
                this.isSynthetic = false;
                this.expression = new Expression(compiler, this, scope, info.expression);
                this.dependencies = this.expression.dependencies;
                this.chunks = null;
                this.isDynamic = true; // TODO not necessarily
                this.shouldCache = false; // TODO does this mean anything here?
            }
            else {
                this.name = info.name;
                this.isTrue = info.value === true;
                this.isSynthetic = info.synthetic;
                this.dependencies = new Set();
                this.chunks = this.isTrue
                    ? []
                    : info.value.map(node => {
                        if (node.type === 'Text')
                            return node;
                        const expression = new Expression(compiler, this, scope, node.expression);
                        addToSet(this.dependencies, expression.dependencies);
                        return expression;
                    });
                this.isDynamic = this.dependencies.size > 0;
                this.shouldCache = this.isDynamic
                    ? this.chunks.length === 1
                        ? this.chunks[0].node.type !== 'Identifier' || scope.names.has(this.chunks[0].node.name)
                        : true
                    : false;
            }
        }
        getValue() {
            if (this.isTrue)
                return true;
            if (this.chunks.length === 0)
                return `""`;
            if (this.chunks.length === 1) {
                return this.chunks[0].type === 'Text'
                    ? stringify(this.chunks[0].data)
                    : this.chunks[0].snippet;
            }
            return (this.chunks[0].type === 'Text' ? '' : `"" + `) +
                this.chunks
                    .map(chunk => {
                    if (chunk.type === 'Text') {
                        return stringify(chunk.data);
                    }
                    else {
                        return chunk.getPrecedence() <= 13 ? `(${chunk.snippet})` : chunk.snippet;
                    }
                })
                    .join(' + ');
        }
        render(block) {
            const node = this.parent;
            const name = fixAttributeCasing(this.name);
            if (name === 'style') {
                const styleProps = optimizeStyle(this.chunks);
                if (styleProps) {
                    this.renderStyle(block, styleProps);
                    return;
                }
            }
            let metadata = node.namespace ? null : attributeLookup[name];
            if (metadata && metadata.appliesTo && !~metadata.appliesTo.indexOf(node.name))
                metadata = null;
            const isIndirectlyBoundValue = name === 'value' &&
                (node.name === 'option' || // TODO check it's actually bound
                    (node.name === 'input' &&
                        node.bindings.find((binding) => /checked|group/.test(binding.name))));
            const propertyName = isIndirectlyBoundValue
                ? '__value'
                : metadata && metadata.propertyName;
            // xlink is a special case... we could maybe extend this to generic
            // namespaced attributes but I'm not sure that's applicable in
            // HTML5?
            const method = name.slice(0, 6) === 'xlink:'
                ? '@setXlinkAttribute'
                : '@setAttribute';
            const isLegacyInputType = this.compiler.options.legacy && name === 'type' && this.parent.name === 'input';
            const isDataSet = /^data-/.test(name) && !this.compiler.options.legacy && !node.namespace;
            const camelCaseName = isDataSet ? name.replace('data-', '').replace(/(-\w)/g, function (m) {
                return m[1].toUpperCase();
            }) : name;
            if (this.isDynamic) {
                let value;
                // TODO some of this code is repeated in Tag.ts — would be good to
                // DRY it out if that's possible without introducing crazy indirection
                if (this.chunks.length === 1) {
                    // single {tag} — may be a non-string
                    value = this.chunks[0].snippet;
                }
                else {
                    // '{foo} {bar}' — treat as string concatenation
                    value =
                        (this.chunks[0].type === 'Text' ? '' : `"" + `) +
                            this.chunks
                                .map((chunk) => {
                                if (chunk.type === 'Text') {
                                    return stringify(chunk.data);
                                }
                                else {
                                    return chunk.getPrecedence() <= 13
                                        ? `(${chunk.snippet})`
                                        : chunk.snippet;
                                }
                            })
                                .join(' + ');
                }
                const isSelectValueAttribute = name === 'value' && node.name === 'select';
                const shouldCache = this.shouldCache || isSelectValueAttribute;
                const last = shouldCache && block.getUniqueName(`${node.var}_${name.replace(/[^a-zA-Z_$]/g, '_')}_value`);
                if (shouldCache)
                    block.addVariable(last);
                let updater;
                const init = shouldCache ? `${last} = ${value}` : value;
                if (isLegacyInputType) {
                    block.builders.hydrate.addLine(`@setInputType(${node.var}, ${init});`);
                    updater = `@setInputType(${node.var}, ${shouldCache ? last : value});`;
                }
                else if (isSelectValueAttribute) {
                    // annoying special case
                    const isMultipleSelect = node.getStaticAttributeValue('multiple');
                    const i = block.getUniqueName('i');
                    const option = block.getUniqueName('option');
                    const ifStatement = isMultipleSelect
                        ? deindent `
						${option}.selected = ~${last}.indexOf(${option}.__value);`
                        : deindent `
						if (${option}.__value === ${last}) {
							${option}.selected = true;
							break;
						}`;
                    updater = deindent `
					for (var ${i} = 0; ${i} < ${node.var}.options.length; ${i} += 1) {
						var ${option} = ${node.var}.options[${i}];

						${ifStatement}
					}
				`;
                    block.builders.hydrate.addBlock(deindent `
					${last} = ${value};
					${updater}
				`);
                }
                else if (propertyName) {
                    block.builders.hydrate.addLine(`${node.var}.${propertyName} = ${init};`);
                    updater = `${node.var}.${propertyName} = ${shouldCache ? last : value};`;
                }
                else if (isDataSet) {
                    block.builders.hydrate.addLine(`${node.var}.dataset.${camelCaseName} = ${init};`);
                    updater = `${node.var}.dataset.${camelCaseName} = ${shouldCache ? last : value};`;
                }
                else {
                    block.builders.hydrate.addLine(`${method}(${node.var}, "${name}", ${init});`);
                    updater = `${method}(${node.var}, "${name}", ${shouldCache ? last : value});`;
                }
                if (this.dependencies.size || isSelectValueAttribute) {
                    const dependencies = Array.from(this.dependencies);
                    const changedCheck = ((block.hasOutros ? `#outroing || ` : '') +
                        dependencies.map(dependency => `changed.${dependency}`).join(' || '));
                    const updateCachedValue = `${last} !== (${last} = ${value})`;
                    const condition = shouldCache ?
                        (dependencies.length ? `(${changedCheck}) && ${updateCachedValue}` : updateCachedValue) :
                        changedCheck;
                    block.builders.update.addConditional(condition, updater);
                }
            }
            else {
                const value = this.getValue();
                const statement = (isLegacyInputType
                    ? `@setInputType(${node.var}, ${value});`
                    : propertyName
                        ? `${node.var}.${propertyName} = ${value};`
                        : isDataSet
                            ? `${node.var}.dataset.${camelCaseName} = ${value};`
                            : `${method}(${node.var}, "${name}", ${value});`);
                block.builders.hydrate.addLine(statement);
                // special case – autofocus. has to be handled in a bit of a weird way
                if (this.isTrue && name === 'autofocus') {
                    block.autofocus = node.var;
                }
            }
            if (isIndirectlyBoundValue) {
                const updateValue = `${node.var}.value = ${node.var}.__value;`;
                block.builders.hydrate.addLine(updateValue);
                if (this.isDynamic)
                    block.builders.update.addLine(updateValue);
            }
        }
        renderStyle(block, styleProps) {
            styleProps.forEach((prop) => {
                let value;
                if (isDynamic$1(prop.value)) {
                    const propDependencies = new Set();
                    value =
                        ((prop.value.length === 1 || prop.value[0].type === 'Text') ? '' : `"" + `) +
                            prop.value
                                .map((chunk) => {
                                if (chunk.type === 'Text') {
                                    return stringify(chunk.data);
                                }
                                else {
                                    const { dependencies, snippet } = chunk;
                                    dependencies.forEach(d => {
                                        propDependencies.add(d);
                                    });
                                    return chunk.getPrecedence() <= 13 ? `(${snippet})` : snippet;
                                }
                            })
                                .join(' + ');
                    if (propDependencies.size) {
                        const dependencies = Array.from(propDependencies);
                        const condition = ((block.hasOutros ? `#outroing || ` : '') +
                            dependencies.map(dependency => `changed.${dependency}`).join(' || '));
                        block.builders.update.addConditional(condition, `@setStyle(${this.parent.var}, "${prop.key}", ${value});`);
                    }
                }
                else {
                    value = stringify(prop.value[0].data);
                }
                block.builders.hydrate.addLine(`@setStyle(${this.parent.var}, "${prop.key}", ${value});`);
            });
        }
        stringifyForSsr() {
            return this.chunks
                .map((chunk) => {
                if (chunk.type === 'Text') {
                    return escapeTemplate(escape(chunk.data).replace(/"/g, '&quot;'));
                }
                return '${@escape(' + chunk.snippet + ')}';
            })
                .join('');
        }
    }
    // source: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes
    const attributeLookup = {
        accept: { appliesTo: ['form', 'input'] },
        'accept-charset': { propertyName: 'acceptCharset', appliesTo: ['form'] },
        accesskey: { propertyName: 'accessKey' },
        action: { appliesTo: ['form'] },
        align: {
            appliesTo: [
                'applet',
                'caption',
                'col',
                'colgroup',
                'hr',
                'iframe',
                'img',
                'table',
                'tbody',
                'td',
                'tfoot',
                'th',
                'thead',
                'tr',
            ],
        },
        allowfullscreen: { propertyName: 'allowFullscreen', appliesTo: ['iframe'] },
        alt: { appliesTo: ['applet', 'area', 'img', 'input'] },
        async: { appliesTo: ['script'] },
        autocomplete: { appliesTo: ['form', 'input'] },
        autofocus: { appliesTo: ['button', 'input', 'keygen', 'select', 'textarea'] },
        autoplay: { appliesTo: ['audio', 'video'] },
        autosave: { appliesTo: ['input'] },
        bgcolor: {
            propertyName: 'bgColor',
            appliesTo: [
                'body',
                'col',
                'colgroup',
                'marquee',
                'table',
                'tbody',
                'tfoot',
                'td',
                'th',
                'tr',
            ],
        },
        border: { appliesTo: ['img', 'object', 'table'] },
        buffered: { appliesTo: ['audio', 'video'] },
        challenge: { appliesTo: ['keygen'] },
        charset: { appliesTo: ['meta', 'script'] },
        checked: { appliesTo: ['command', 'input'] },
        cite: { appliesTo: ['blockquote', 'del', 'ins', 'q'] },
        class: { propertyName: 'className' },
        code: { appliesTo: ['applet'] },
        codebase: { propertyName: 'codeBase', appliesTo: ['applet'] },
        color: { appliesTo: ['basefont', 'font', 'hr'] },
        cols: { appliesTo: ['textarea'] },
        colspan: { propertyName: 'colSpan', appliesTo: ['td', 'th'] },
        content: { appliesTo: ['meta'] },
        contenteditable: { propertyName: 'contentEditable' },
        contextmenu: {},
        controls: { appliesTo: ['audio', 'video'] },
        coords: { appliesTo: ['area'] },
        data: { appliesTo: ['object'] },
        datetime: { propertyName: 'dateTime', appliesTo: ['del', 'ins', 'time'] },
        default: { appliesTo: ['track'] },
        defer: { appliesTo: ['script'] },
        dir: {},
        dirname: { propertyName: 'dirName', appliesTo: ['input', 'textarea'] },
        disabled: {
            appliesTo: [
                'button',
                'command',
                'fieldset',
                'input',
                'keygen',
                'optgroup',
                'option',
                'select',
                'textarea',
            ],
        },
        download: { appliesTo: ['a', 'area'] },
        draggable: {},
        dropzone: {},
        enctype: { appliesTo: ['form'] },
        for: { propertyName: 'htmlFor', appliesTo: ['label', 'output'] },
        form: {
            appliesTo: [
                'button',
                'fieldset',
                'input',
                'keygen',
                'label',
                'meter',
                'object',
                'output',
                'progress',
                'select',
                'textarea',
            ],
        },
        formaction: { appliesTo: ['input', 'button'] },
        headers: { appliesTo: ['td', 'th'] },
        height: {
            appliesTo: ['canvas', 'embed', 'iframe', 'img', 'input', 'object', 'video'],
        },
        hidden: {},
        high: { appliesTo: ['meter'] },
        href: { appliesTo: ['a', 'area', 'base', 'link'] },
        hreflang: { appliesTo: ['a', 'area', 'link'] },
        'http-equiv': { propertyName: 'httpEquiv', appliesTo: ['meta'] },
        icon: { appliesTo: ['command'] },
        id: {},
        indeterminate: { appliesTo: ['input'] },
        ismap: { propertyName: 'isMap', appliesTo: ['img'] },
        itemprop: {},
        keytype: { appliesTo: ['keygen'] },
        kind: { appliesTo: ['track'] },
        label: { appliesTo: ['track'] },
        lang: {},
        language: { appliesTo: ['script'] },
        loop: { appliesTo: ['audio', 'bgsound', 'marquee', 'video'] },
        low: { appliesTo: ['meter'] },
        manifest: { appliesTo: ['html'] },
        max: { appliesTo: ['input', 'meter', 'progress'] },
        maxlength: { propertyName: 'maxLength', appliesTo: ['input', 'textarea'] },
        media: { appliesTo: ['a', 'area', 'link', 'source', 'style'] },
        method: { appliesTo: ['form'] },
        min: { appliesTo: ['input', 'meter'] },
        multiple: { appliesTo: ['input', 'select'] },
        muted: { appliesTo: ['audio', 'video'] },
        name: {
            appliesTo: [
                'button',
                'form',
                'fieldset',
                'iframe',
                'input',
                'keygen',
                'object',
                'output',
                'select',
                'textarea',
                'map',
                'meta',
                'param',
            ],
        },
        novalidate: { propertyName: 'noValidate', appliesTo: ['form'] },
        open: { appliesTo: ['details'] },
        optimum: { appliesTo: ['meter'] },
        pattern: { appliesTo: ['input'] },
        ping: { appliesTo: ['a', 'area'] },
        placeholder: { appliesTo: ['input', 'textarea'] },
        poster: { appliesTo: ['video'] },
        preload: { appliesTo: ['audio', 'video'] },
        radiogroup: { appliesTo: ['command'] },
        readonly: { propertyName: 'readOnly', appliesTo: ['input', 'textarea'] },
        rel: { appliesTo: ['a', 'area', 'link'] },
        required: { appliesTo: ['input', 'select', 'textarea'] },
        reversed: { appliesTo: ['ol'] },
        rows: { appliesTo: ['textarea'] },
        rowspan: { propertyName: 'rowSpan', appliesTo: ['td', 'th'] },
        sandbox: { appliesTo: ['iframe'] },
        scope: { appliesTo: ['th'] },
        scoped: { appliesTo: ['style'] },
        seamless: { appliesTo: ['iframe'] },
        selected: { appliesTo: ['option'] },
        shape: { appliesTo: ['a', 'area'] },
        size: { appliesTo: ['input', 'select'] },
        sizes: { appliesTo: ['link', 'img', 'source'] },
        span: { appliesTo: ['col', 'colgroup'] },
        spellcheck: {},
        src: {
            appliesTo: [
                'audio',
                'embed',
                'iframe',
                'img',
                'input',
                'script',
                'source',
                'track',
                'video',
            ],
        },
        srcdoc: { appliesTo: ['iframe'] },
        srclang: { appliesTo: ['track'] },
        srcset: { appliesTo: ['img'] },
        start: { appliesTo: ['ol'] },
        step: { appliesTo: ['input'] },
        style: { propertyName: 'style.cssText' },
        summary: { appliesTo: ['table'] },
        tabindex: { propertyName: 'tabIndex' },
        target: { appliesTo: ['a', 'area', 'base', 'form'] },
        title: {},
        type: {
            appliesTo: [
                'button',
                'command',
                'embed',
                'object',
                'script',
                'source',
                'style',
                'menu',
            ],
        },
        usemap: { propertyName: 'useMap', appliesTo: ['img', 'input', 'object'] },
        value: {
            appliesTo: [
                'button',
                'option',
                'input',
                'li',
                'meter',
                'progress',
                'param',
                'select',
                'textarea',
            ],
        },
        volume: { appliesTo: ['audio', 'video'] },
        width: {
            appliesTo: ['canvas', 'embed', 'iframe', 'img', 'input', 'object', 'video'],
        },
        wrap: { appliesTo: ['textarea'] },
    };
    Object.keys(attributeLookup).forEach(name => {
        const metadata = attributeLookup[name];
        if (!metadata.propertyName)
            metadata.propertyName = name;
    });
    function optimizeStyle(value) {
        const props = [];
        let chunks = value.slice();
        while (chunks.length) {
            const chunk = chunks[0];
            if (chunk.type !== 'Text')
                return null;
            const keyMatch = /^\s*([\w-]+):\s*/.exec(chunk.data);
            if (!keyMatch)
                return null;
            const key = keyMatch[1];
            const offset = keyMatch.index + keyMatch[0].length;
            const remainingData = chunk.data.slice(offset);
            if (remainingData) {
                chunks[0] = {
                    start: chunk.start + offset,
                    end: chunk.end,
                    type: 'Text',
                    data: remainingData
                };
            }
            else {
                chunks.shift();
            }
            const result = getStyleValue(chunks);
            if (!result)
                return null;
            props.push({ key, value: result.value });
            chunks = result.chunks;
        }
        return props;
    }
    function getStyleValue(chunks) {
        const value = [];
        let inUrl = false;
        let quoteMark = null;
        let escaped = false;
        while (chunks.length) {
            const chunk = chunks.shift();
            if (chunk.type === 'Text') {
                let c = 0;
                while (c < chunk.data.length) {
                    const char = chunk.data[c];
                    if (escaped) {
                        escaped = false;
                    }
                    else if (char === '\\') {
                        escaped = true;
                    }
                    else if (char === quoteMark) {
                    }
                    else if (char === '"' || char === "'") {
                        quoteMark = char;
                    }
                    else if (char === ')' && inUrl) {
                        inUrl = false;
                    }
                    else if (char === 'u' && chunk.data.slice(c, c + 4) === 'url(') {
                        inUrl = true;
                    }
                    else if (char === ';' && !inUrl && !quoteMark) {
                        break;
                    }
                    c += 1;
                }
                if (c > 0) {
                    value.push({
                        type: 'Text',
                        start: chunk.start,
                        end: chunk.start + c,
                        data: chunk.data.slice(0, c)
                    });
                }
                while (/[;\s]/.test(chunk.data[c]))
                    c += 1;
                const remainingData = chunk.data.slice(c);
                if (remainingData) {
                    chunks.unshift({
                        start: chunk.start + c,
                        end: chunk.end,
                        type: 'Text',
                        data: remainingData
                    });
                    break;
                }
            }
            else {
                value.push(chunk);
            }
        }
        return {
            chunks,
            value
        };
    }
    function isDynamic$1(value) {
        return value.length > 1 || value[0].type !== 'Text';
    }

    const readOnlyMediaAttributes = new Set([
        'duration',
        'buffered',
        'seekable',
        'played'
    ]);
    // TODO a lot of this element-specific stuff should live in Element —
    // Binding should ideally be agnostic between Element and Component
    class Binding extends Node$1 {
        constructor(compiler, parent, scope, info) {
            super(compiler, parent, scope, info);
            this.name = info.name;
            this.value = new Expression(compiler, this, scope, info.value);
            let obj;
            let prop;
            const { name } = getObject(this.value.node);
            this.isContextual = scope.names.has(name);
            if (this.value.node.type === 'MemberExpression') {
                prop = `[✂${this.value.node.property.start}-${this.value.node.property.end}✂]`;
                if (!this.value.node.computed)
                    prop = `'${prop}'`;
                obj = `[✂${this.value.node.object.start}-${this.value.node.object.end}✂]`;
                this.usesContext = true;
            }
            else {
                obj = 'ctx';
                prop = `'${name}'`;
                this.usesContext = scope.names.has(name);
            }
            this.obj = obj;
            this.prop = prop;
        }
        munge(block) {
            const node = this.parent;
            const needsLock = node.name !== 'input' || !/radio|checkbox|range|color/.test(node.getStaticAttributeValue('type'));
            const isReadOnly = ((node.isMediaNode() && readOnlyMediaAttributes.has(this.name)) ||
                dimensions.test(this.name));
            let updateCondition;
            const { name } = getObject(this.value.node);
            const { snippet } = this.value;
            // special case: if you have e.g. `<input type=checkbox bind:checked=selected.done>`
            // and `selected` is an object chosen with a <select>, then when `checked` changes,
            // we need to tell the component to update all the values `selected` might be
            // pointing to
            // TODO should this happen in preprocess?
            const dependencies = new Set(this.value.dependencies);
            this.value.dependencies.forEach((prop) => {
                const indirectDependencies = this.compiler.indirectDependencies.get(prop);
                if (indirectDependencies) {
                    indirectDependencies.forEach(indirectDependency => {
                        dependencies.add(indirectDependency);
                    });
                }
            });
            // view to model
            const valueFromDom = getValueFromDom(this.compiler, node, this);
            const handler = getEventHandler(this, this.compiler, block, name, snippet, dependencies, valueFromDom);
            // model to view
            let updateDom = getDomUpdater(node, this, snippet);
            let initialUpdate = updateDom;
            // special cases
            if (this.name === 'group') {
                const bindingGroup = getBindingGroup(this.compiler, this.value.node);
                block.builders.hydrate.addLine(`#component._bindingGroups[${bindingGroup}].push(${node.var});`);
                block.builders.destroy.addLine(`#component._bindingGroups[${bindingGroup}].splice(#component._bindingGroups[${bindingGroup}].indexOf(${node.var}), 1);`);
            }
            if (this.name === 'currentTime' || this.name === 'volume') {
                updateCondition = `!isNaN(${snippet})`;
                if (this.name === 'currentTime')
                    initialUpdate = null;
            }
            if (this.name === 'paused') {
                // this is necessary to prevent audio restarting by itself
                const last = block.getUniqueName(`${node.var}_is_paused`);
                block.addVariable(last, 'true');
                updateCondition = `${last} !== (${last} = ${snippet})`;
                updateDom = `${node.var}[${last} ? "pause" : "play"]();`;
                initialUpdate = null;
            }
            // bind:offsetWidth and bind:offsetHeight
            if (dimensions.test(this.name)) {
                initialUpdate = null;
                updateDom = null;
            }
            return {
                name: this.name,
                object: name,
                handler,
                updateDom,
                initialUpdate,
                needsLock: !isReadOnly && needsLock,
                updateCondition,
                isReadOnlyMediaAttribute: this.isReadOnlyMediaAttribute()
            };
        }
        isReadOnlyMediaAttribute() {
            return readOnlyMediaAttributes.has(this.name);
        }
    }
    function getDomUpdater(node, binding, snippet) {
        if (binding.isReadOnlyMediaAttribute()) {
            return null;
        }
        if (node.name === 'select') {
            return node.getStaticAttributeValue('multiple') === true ?
                `@selectOptions(${node.var}, ${snippet})` :
                `@selectOption(${node.var}, ${snippet})`;
        }
        if (binding.name === 'group') {
            const type = node.getStaticAttributeValue('type');
            const condition = type === 'checkbox'
                ? `~${snippet}.indexOf(${node.var}.__value)`
                : `${node.var}.__value === ${snippet}`;
            return `${node.var}.checked = ${condition};`;
        }
        return `${node.var}.${binding.name} = ${snippet};`;
    }
    function getBindingGroup(compiler, value) {
        const { parts } = flattenReference(value); // TODO handle cases involving computed member expressions
        const keypath = parts.join('.');
        // TODO handle contextual bindings — `keypath` should include unique ID of
        // each block that provides context
        let index = compiler.bindingGroups.indexOf(keypath);
        if (index === -1) {
            index = compiler.bindingGroups.length;
            compiler.bindingGroups.push(keypath);
        }
        return index;
    }
    function getEventHandler(binding, compiler, block, name, snippet, dependencies, value, isContextual) {
        const storeDependencies = [...dependencies].filter(prop => prop[0] === '$').map(prop => prop.slice(1));
        dependencies = [...dependencies].filter(prop => prop[0] !== '$');
        if (binding.isContextual) {
            const tail = binding.value.node.type === 'MemberExpression'
                ? getTailSnippet(binding.value.node)
                : '';
            const head = block.bindings.get(name);
            return {
                usesContext: true,
                usesState: true,
                usesStore: storeDependencies.length > 0,
                mutation: `${head}${tail} = ${value};`,
                props: dependencies.map(prop => `${prop}: ctx.${prop}`),
                storeProps: storeDependencies.map(prop => `${prop}: $.${prop}`)
            };
        }
        if (binding.value.node.type === 'MemberExpression') {
            // This is a little confusing, and should probably be tidied up
            // at some point. It addresses a tricky bug (#893), wherein
            // Svelte tries to `set()` a computed property, which throws an
            // error in dev mode. a) it's possible that we should be
            // replacing computations with *their* dependencies, and b)
            // we should probably populate `compiler.target.readonly` sooner so
            // that we don't have to do the `.some()` here
            dependencies = dependencies.filter(prop => !compiler.computations.some(computation => computation.key === prop));
            return {
                usesContext: false,
                usesState: true,
                usesStore: storeDependencies.length > 0,
                mutation: `${snippet} = ${value}`,
                props: dependencies.map((prop) => `${prop}: ctx.${prop}`),
                storeProps: storeDependencies.map(prop => `${prop}: $.${prop}`)
            };
        }
        let props;
        let storeProps;
        if (name[0] === '$') {
            props = [];
            storeProps = [`${name.slice(1)}: ${value}`];
        }
        else {
            props = [`${name}: ${value}`];
            storeProps = [];
        }
        return {
            usesContext: false,
            usesState: false,
            usesStore: false,
            mutation: null,
            props,
            storeProps
        };
    }
    function getValueFromDom(compiler, node, binding) {
        // <select bind:value='selected>
        if (node.name === 'select') {
            return node.getStaticAttributeValue('multiple') === true ?
                `@selectMultipleValue(${node.var})` :
                `@selectValue(${node.var})`;
        }
        const type = node.getStaticAttributeValue('type');
        // <input type='checkbox' bind:group='foo'>
        if (binding.name === 'group') {
            const bindingGroup = getBindingGroup(compiler, binding.value.node);
            if (type === 'checkbox') {
                return `@getBindingGroupValue(#component._bindingGroups[${bindingGroup}])`;
            }
            return `${node.var}.__value`;
        }
        // <input type='range|number' bind:value>
        if (type === 'range' || type === 'number') {
            return `@toNumber(${node.var}.${binding.name})`;
        }
        if ((binding.name === 'buffered' || binding.name === 'seekable' || binding.name === 'played')) {
            return `@timeRangesToArray(${node.var}.${binding.name})`;
        }
        // everything else
        return `${node.var}.${binding.name}`;
    }

    class EventHandler extends Node$1 {
        constructor(compiler, parent, scope, info) {
            super(compiler, parent, scope, info);
            this.name = info.name;
            this.dependencies = new Set();
            if (info.expression) {
                this.callee = flattenReference(info.expression.callee);
                this.insertionPoint = info.expression.start;
                this.usesComponent = !validCalleeObjects.has(this.callee.name);
                this.usesContext = false;
                this.args = info.expression.arguments.map(param => {
                    const expression = new Expression(compiler, this, scope, param);
                    addToSet(this.dependencies, expression.dependencies);
                    if (expression.usesContext)
                        this.usesContext = true;
                    return expression;
                });
                this.snippet = `[✂${info.expression.start}-${info.expression.end}✂];`;
            }
            else {
                this.callee = null;
                this.insertionPoint = null;
                this.args = null;
                this.usesComponent = true;
                this.usesContext = false;
                this.snippet = null; // TODO handle shorthand events here?
            }
            this.isCustomEvent = compiler.events.has(this.name);
            this.shouldHoist = !this.isCustomEvent && parent.hasAncestor('EachBlock');
        }
        render(compiler, block, hoisted) {
            if (this.insertionPoint === null)
                return; // TODO handle shorthand events here?
            if (!validCalleeObjects.has(this.callee.name)) {
                const component = hoisted ? `component` : block.alias(`component`);
                // allow event.stopPropagation(), this.select() etc
                // TODO verify that it's a valid callee (i.e. built-in or declared method)
                if (this.callee.name[0] === '$' && !compiler.methods.has(this.callee.name)) {
                    compiler.code.overwrite(this.insertionPoint, this.insertionPoint + 1, `${component}.store.`);
                }
                else {
                    compiler.code.prependRight(this.insertionPoint, `${component}.`);
                }
            }
            if (this.isCustomEvent) {
                this.args.forEach(arg => {
                    arg.overwriteThis(this.parent.var);
                });
                if (this.callee && this.callee.name === 'this') {
                    const node = this.callee.nodes[0];
                    compiler.code.overwrite(node.start, node.end, this.parent.var, {
                        storeName: true,
                        contentOnly: true
                    });
                }
            }
        }
    }

    class Component extends Node$1 {
        constructor(compiler, parent, scope, info) {
            super(compiler, parent, scope, info);
            compiler.hasComponents = true;
            this.name = info.name;
            this.expression = this.name === 'svelte:component'
                ? new Expression(compiler, this, scope, info.expression)
                : null;
            this.attributes = [];
            this.bindings = [];
            this.handlers = [];
            info.attributes.forEach(node => {
                switch (node.type) {
                    case 'Attribute':
                    case 'Spread':
                        this.attributes.push(new Attribute(compiler, this, scope, node));
                        break;
                    case 'Binding':
                        this.bindings.push(new Binding(compiler, this, scope, node));
                        break;
                    case 'EventHandler':
                        this.handlers.push(new EventHandler(compiler, this, scope, node));
                        break;
                    case 'Ref':
                        // TODO catch this in validation
                        if (this.ref)
                            throw new Error(`Duplicate refs`);
                        compiler.usesRefs = true;
                        this.ref = node.name;
                        break;
                    default:
                        throw new Error(`Not implemented: ${node.type}`);
                }
            });
            this.children = mapChildren(compiler, this, scope, info.children);
        }
        init(block, stripWhitespace, nextSibling) {
            this.cannotUseInnerHTML();
            this.attributes.forEach(attr => {
                block.addDependencies(attr.dependencies);
            });
            this.bindings.forEach(binding => {
                block.addDependencies(binding.value.dependencies);
            });
            this.handlers.forEach(handler => {
                block.addDependencies(handler.dependencies);
            });
            this.var = block.getUniqueName((this.name === 'svelte:self' ? this.compiler.name :
                this.name === 'svelte:component' ? 'switch_instance' :
                    this.name).toLowerCase());
            if (this.children.length) {
                this._slots = new Set(['default']);
                this.children.forEach(child => {
                    child.init(block, stripWhitespace, nextSibling);
                });
            }
            if (this.compiler.options.nestedTransitions) {
                block.addOutro();
            }
        }
        build(block, parentNode, parentNodes) {
            const { compiler } = this;
            const name = this.var;
            const componentInitProperties = [`root: #component.root`];
            if (this.children.length > 0) {
                const slots = Array.from(this._slots).map(name => `${quoteNameIfNecessary(name)}: @createFragment()`);
                componentInitProperties.push(`slots: { ${slots.join(', ')} }`);
                this.children.forEach((child) => {
                    child.build(block, `${this.var}._slotted.default`, 'nodes');
                });
            }
            const statements = [];
            const name_initial_data = block.getUniqueName(`${name}_initial_data`);
            const name_changes = block.getUniqueName(`${name}_changes`);
            let name_updating;
            let beforecreate = null;
            const updates = [];
            const usesSpread = !!this.attributes.find(a => a.isSpread);
            const attributeObject = usesSpread
                ? '{}'
                : stringifyProps(this.attributes.map(attr => `${attr.name}: ${attr.getValue()}`));
            if (this.attributes.length || this.bindings.length) {
                componentInitProperties.push(`data: ${name_initial_data}`);
            }
            if (!usesSpread && (this.attributes.filter(a => a.isDynamic).length || this.bindings.length)) {
                updates.push(`var ${name_changes} = {};`);
            }
            if (this.attributes.length) {
                if (usesSpread) {
                    const levels = block.getUniqueName(`${this.var}_spread_levels`);
                    const initialProps = [];
                    const changes = [];
                    const allDependencies = new Set();
                    this.attributes.forEach(attr => {
                        addToSet(allDependencies, attr.dependencies);
                    });
                    this.attributes.forEach(attr => {
                        const { name, dependencies } = attr;
                        const condition = dependencies.size > 0 && (dependencies.size !== allDependencies.size)
                            ? [...dependencies].map(d => `changed.${d}`).join(' || ')
                            : null;
                        if (attr.isSpread) {
                            const value = attr.expression.snippet;
                            initialProps.push(value);
                            changes.push(condition ? `${condition} && ${value}` : value);
                        }
                        else {
                            const obj = `{ ${quoteNameIfNecessary(name)}: ${attr.getValue()} }`;
                            initialProps.push(obj);
                            changes.push(condition ? `${condition} && ${obj}` : obj);
                        }
                    });
                    block.builders.init.addBlock(deindent `
					var ${levels} = [
						${initialProps.join(',\n')}
					];
				`);
                    statements.push(deindent `
					for (var #i = 0; #i < ${levels}.length; #i += 1) {
						${name_initial_data} = @assign(${name_initial_data}, ${levels}[#i]);
					}
				`);
                    const conditions = [...allDependencies].map(dep => `changed.${dep}`).join(' || ');
                    updates.push(deindent `
					var ${name_changes} = ${allDependencies.size === 1 ? `${conditions}` : `(${conditions})`} ? @getSpreadUpdate(${levels}, [
						${changes.join(',\n')}
					]) : {};
				`);
                }
                else {
                    this.attributes
                        .filter((attribute) => attribute.isDynamic)
                        .forEach((attribute) => {
                        if (attribute.dependencies.size > 0) {
                            updates.push(deindent `
								if (${[...attribute.dependencies]
                            .map(dependency => `changed.${dependency}`)
                            .join(' || ')}) ${name_changes}.${attribute.name} = ${attribute.getValue()};
							`);
                        }
                    });
                }
            }
            if (this.bindings.length) {
                compiler.target.hasComplexBindings = true;
                name_updating = block.alias(`${name}_updating`);
                block.addVariable(name_updating, '{}');
                let hasLocalBindings = false;
                let hasStoreBindings = false;
                const builder = new CodeBuilder();
                this.bindings.forEach((binding) => {
                    let { name: key } = getObject(binding.value.node);
                    let setFromChild;
                    if (binding.isContextual) {
                        const computed = isComputed$1(binding.value.node);
                        const tail = binding.value.node.type === 'MemberExpression' ? getTailSnippet(binding.value.node) : '';
                        const head = block.bindings.get(key);
                        const lhs = binding.value.node.type === 'MemberExpression'
                            ? binding.value.snippet
                            : `${head}${tail} = childState.${binding.name}`;
                        setFromChild = deindent `
						${lhs} = childState.${binding.name};

						${[...binding.value.dependencies]
                        .map((name) => {
                        const isStoreProp = name[0] === '$';
                        const prop = isStoreProp ? name.slice(1) : name;
                        const newState = isStoreProp ? 'newStoreState' : 'newState';
                        if (isStoreProp)
                            hasStoreBindings = true;
                        else
                            hasLocalBindings = true;
                        return `${newState}.${prop} = ctx.${name};`;
                    })}
					`;
                    }
                    else {
                        const isStoreProp = key[0] === '$';
                        const prop = isStoreProp ? key.slice(1) : key;
                        const newState = isStoreProp ? 'newStoreState' : 'newState';
                        if (isStoreProp)
                            hasStoreBindings = true;
                        else
                            hasLocalBindings = true;
                        if (binding.value.node.type === 'MemberExpression') {
                            setFromChild = deindent `
							${binding.value.snippet} = childState.${binding.name};
							${newState}.${prop} = ctx.${key};
						`;
                        }
                        else {
                            setFromChild = `${newState}.${prop} = childState.${binding.name};`;
                        }
                    }
                    statements.push(deindent `
					if (${binding.value.snippet} !== void 0) {
						${name_initial_data}.${binding.name} = ${binding.value.snippet};
						${name_updating}.${binding.name} = true;
					}`);
                    builder.addConditional(`!${name_updating}.${binding.name} && changed.${binding.name}`, setFromChild);
                    updates.push(deindent `
					if (!${name_updating}.${binding.name} && ${[...binding.value.dependencies].map((dependency) => `changed.${dependency}`).join(' || ')}) {
						${name_changes}.${binding.name} = ${binding.value.snippet};
						${name_updating}.${binding.name} = ${binding.value.snippet} !== void 0;
					}
				`);
                });
                block.maintainContext = true; // TODO put this somewhere more logical
                const initialisers = [
                    hasLocalBindings && 'newState = {}',
                    hasStoreBindings && 'newStoreState = {}',
                ].filter(Boolean).join(', ');
                // TODO use component.on('state', ...) instead of _bind
                componentInitProperties.push(deindent `
				_bind(changed, childState) {
					var ${initialisers};
					${builder}
					${hasStoreBindings && `#component.store.set(newStoreState);`}
					${hasLocalBindings && `#component._set(newState);`}
					${name_updating} = {};
				}
			`);
                beforecreate = deindent `
				#component.root._beforecreate.push(() => {
					${name}._bind({ ${this.bindings.map(b => `${b.name}: 1`).join(', ')} }, ${name}.get());
				});
			`;
            }
            this.handlers.forEach(handler => {
                handler.var = block.getUniqueName(`${this.var}_${handler.name}`); // TODO this is hacky
                handler.render(compiler, block, false); // TODO hoist when possible
                if (handler.usesContext)
                    block.maintainContext = true; // TODO is there a better place to put this?
            });
            if (this.name === 'svelte:component') {
                const switch_value = block.getUniqueName('switch_value');
                const switch_props = block.getUniqueName('switch_props');
                const { dependencies, snippet } = this.expression;
                const anchor = this.getOrCreateAnchor(block, parentNode, parentNodes);
                block.builders.init.addBlock(deindent `
				var ${switch_value} = ${snippet};

				function ${switch_props}(ctx) {
					${(this.attributes.length || this.bindings.length) && deindent `
					var ${name_initial_data} = ${attributeObject};`}
					${statements}
					return {
						${componentInitProperties.join(',\n')}
					};
				}

				if (${switch_value}) {
					var ${name} = new ${switch_value}(${switch_props}(ctx));

					${beforecreate}
				}

				${this.handlers.map(handler => deindent `
					function ${handler.var}(event) {
						${handler.snippet || `#component.fire("${handler.name}", event);`}
					}

					if (${name}) ${name}.on("${handler.name}", ${handler.var});
				`)}
			`);
                block.builders.create.addLine(`if (${name}) ${name}._fragment.c();`);
                if (parentNodes) {
                    block.builders.claim.addLine(`if (${name}) ${name}._fragment.l(${parentNodes});`);
                }
                block.builders.mount.addBlock(deindent `
				if (${name}) {
					${name}._mount(${parentNode || '#target'}, ${parentNode ? 'null' : 'anchor'});
					${this.ref && `#component.refs.${this.ref} = ${name};`}
				}
			`);
                const updateMountNode = this.getUpdateMountNode(anchor);
                if (updates.length) {
                    block.builders.update.addBlock(deindent `
					${updates}
				`);
                }
                block.builders.update.addBlock(deindent `
				if (${switch_value} !== (${switch_value} = ${snippet})) {
					if (${name}) ${name}.destroy();

					if (${switch_value}) {
						${name} = new ${switch_value}(${switch_props}(ctx));

						${this.bindings.length > 0 && deindent `
						#component.root._beforecreate.push(() => {
							const changed = {};
							${this.bindings.map(binding => deindent `
							if (${binding.value.snippet} === void 0) changed.${binding.name} = 1;`)}
							${name}._bind(changed, ${name}.get());
						});`}
						${name}._fragment.c();

						${this.children.map(child => child.remount(name))}
						${name}._mount(${updateMountNode}, ${anchor});

						${this.handlers.map(handler => deindent `
							${name}.on("${handler.name}", ${handler.var});
						`)}

						${this.ref && `#component.refs.${this.ref} = ${name};`}
					}

					${this.ref && deindent `
						else if (#component.refs.${this.ref} === ${name}) {
							#component.refs.${this.ref} = null;
						}`}
				}
			`);
                if (updates.length) {
                    block.builders.update.addBlock(deindent `
					else if (${switch_value}) {
						${name}._set(${name_changes});
						${this.bindings.length && `${name_updating} = {};`}
					}
				`);
                }
                block.builders.destroy.addLine(`if (${name}) ${name}.destroy(${parentNode ? '' : 'detach'});`);
            }
            else {
                const expression = this.name === 'svelte:self'
                    ? compiler.name
                    : `%components-${this.name}`;
                block.builders.init.addBlock(deindent `
				${(this.attributes.length || this.bindings.length) && deindent `
				var ${name_initial_data} = ${attributeObject};`}
				${statements}
				var ${name} = new ${expression}({
					${componentInitProperties.join(',\n')}
				});

				${beforecreate}

				${this.handlers.map(handler => deindent `
					${name}.on("${handler.name}", function(event) {
						${handler.snippet || `#component.fire("${handler.name}", event);`}
					});
				`)}

				${this.ref && `#component.refs.${this.ref} = ${name};`}
			`);
                block.builders.create.addLine(`${name}._fragment.c();`);
                if (parentNodes) {
                    block.builders.claim.addLine(`${name}._fragment.l(${parentNodes});`);
                }
                block.builders.mount.addLine(`${name}._mount(${parentNode || '#target'}, ${parentNode ? 'null' : 'anchor'});`);
                if (updates.length) {
                    block.builders.update.addBlock(deindent `
					${updates}
					${name}._set(${name_changes});
					${this.bindings.length && `${name_updating} = {};`}
				`);
                }
                block.builders.destroy.addLine(deindent `
				${name}.destroy(${parentNode ? '' : 'detach'});
				${this.ref && `if (#component.refs.${this.ref} === ${name}) #component.refs.${this.ref} = null;`}
			`);
            }
            if (this.compiler.options.nestedTransitions) {
                block.builders.outro.addLine(`${name}._fragment.o(#outrocallback);`);
            }
        }
        remount(name) {
            return `${this.var}._mount(${name}._slotted.default, null);`;
        }
        ssr() {
            function stringifyAttribute(chunk) {
                if (chunk.type === 'Text') {
                    return escapeTemplate(escape(chunk.data));
                }
                return '${@escape( ' + chunk.snippet + ')}';
            }
            const bindingProps = this.bindings.map(binding => {
                const { name } = getObject(binding.value.node);
                const tail = binding.value.node.type === 'MemberExpression'
                    ? getTailSnippet(binding.value.node)
                    : '';
                return `${binding.name}: ctx.${name}${tail}`;
            });
            function getAttributeValue(attribute) {
                if (attribute.isTrue)
                    return `true`;
                if (attribute.chunks.length === 0)
                    return `''`;
                if (attribute.chunks.length === 1) {
                    const chunk = attribute.chunks[0];
                    if (chunk.type === 'Text') {
                        return stringify(chunk.data);
                    }
                    return chunk.snippet;
                }
                return '`' + attribute.chunks.map(stringifyAttribute).join('') + '`';
            }
            const usesSpread = this.attributes.find(attr => attr.isSpread);
            const props = usesSpread
                ? `Object.assign(${this.attributes
                .map(attribute => {
                if (attribute.isSpread) {
                    return attribute.expression.snippet;
                }
                else {
                    return `{ ${attribute.name}: ${getAttributeValue(attribute)} }`;
                }
            })
                .concat(bindingProps.map(p => `{ ${p} }`))
                .join(', ')})`
                : `{ ${this.attributes
                .map(attribute => `${attribute.name}: ${getAttributeValue(attribute)}`)
                .concat(bindingProps)
                .join(', ')} }`;
            const isDynamicComponent = this.name === 'svelte:component';
            const expression = (this.name === 'svelte:self' ? this.compiler.name :
                (isDynamicComponent ? `((${this.expression.snippet}) || @missingComponent)` :
                    `%components-${this.name}`));
            this.bindings.forEach(binding => {
                const conditions = [];
                let node = this;
                while (node = node.parent) {
                    if (node.type === 'IfBlock') {
                        // TODO handle contextual bindings...
                        conditions.push(`(${node.expression.snippet})`);
                    }
                }
                conditions.push(`!('${binding.name}' in ctx)`);
                const { name } = getObject(binding.value.node);
                this.compiler.target.bindings.push(deindent `
				if (${conditions.reverse().join('&&')}) {
					tmp = ${expression}.data();
					if ('${name}' in tmp) {
						ctx.${binding.name} = tmp.${name};
						settled = false;
					}
				}
			`);
            });
            let open = `\${${expression}._render(__result, ${props}`;
            const options = [];
            options.push(`store: options.store`);
            if (this.children.length) {
                const appendTarget = {
                    slots: { default: '' },
                    slotStack: ['default']
                };
                this.compiler.target.appendTargets.push(appendTarget);
                this.children.forEach((child) => {
                    child.ssr();
                });
                const slotted = Object.keys(appendTarget.slots)
                    .map(name => `${quoteNameIfNecessary(name)}: () => \`${appendTarget.slots[name]}\``)
                    .join(', ');
                options.push(`slotted: { ${slotted} }`);
                this.compiler.target.appendTargets.pop();
            }
            if (options.length) {
                open += `, { ${options.join(', ')} }`;
            }
            this.compiler.target.append(open);
            this.compiler.target.append(')}');
        }
    }
    function isComputed$1(node) {
        while (node.type === 'MemberExpression') {
            if (node.computed)
                return true;
            node = node.object;
        }
        return false;
    }

    class ElseBlock extends Node$1 {
        constructor(compiler, parent, scope, info) {
            super(compiler, parent, scope, info);
            this.children = mapChildren(compiler, this, scope, info.children);
        }
    }

    class EachBlock extends Node$1 {
        constructor(compiler, parent, scope, info) {
            super(compiler, parent, scope, info);
            this.expression = new Expression(compiler, this, scope, info.expression);
            this.context = info.context.name || 'each'; // TODO this is used to facilitate binding; currently fails with destructuring
            this.index = info.index;
            this.scope = scope.child();
            this.contexts = [];
            unpackDestructuring(this.contexts, info.context, '');
            this.contexts.forEach(context => {
                this.scope.add(context.key.name, this.expression.dependencies);
            });
            this.key = info.key
                ? new Expression(compiler, this, this.scope, info.key)
                : null;
            if (this.index) {
                // index can only change if this is a keyed each block
                const dependencies = this.key ? this.expression.dependencies : [];
                this.scope.add(this.index, dependencies);
            }
            this.children = mapChildren(compiler, this, this.scope, info.children);
            this.else = info.else
                ? new ElseBlock(compiler, this, this.scope, info.else)
                : null;
        }
        init(block, stripWhitespace, nextSibling) {
            this.cannotUseInnerHTML();
            this.var = block.getUniqueName(`each`);
            this.iterations = block.getUniqueName(`${this.var}_blocks`);
            this.get_each_context = this.compiler.getUniqueName(`get_${this.var}_context`);
            const { dependencies } = this.expression;
            block.addDependencies(dependencies);
            this.block = block.child({
                comment: createDebuggingComment(this, this.compiler),
                name: this.compiler.getUniqueName('create_each_block'),
                key: this.key,
                bindings: new Map(block.bindings)
            });
            this.each_block_value = this.compiler.getUniqueName('each_value');
            const indexName = this.index || this.compiler.getUniqueName(`${this.context}_index`);
            this.contexts.forEach(prop => {
                this.block.bindings.set(prop.key.name, `ctx.${this.each_block_value}[ctx.${indexName}]${prop.tail}`);
            });
            if (this.index) {
                this.block.getUniqueName(this.index); // this prevents name collisions (#1254)
            }
            this.contextProps = this.contexts.map(prop => `child_ctx.${prop.key.name} = list[i]${prop.tail};`);
            // TODO only add these if necessary
            this.contextProps.push(`child_ctx.${this.each_block_value} = list;`, `child_ctx.${indexName} = i;`);
            this.compiler.target.blocks.push(this.block);
            this.initChildren(this.block, stripWhitespace, nextSibling);
            block.addDependencies(this.block.dependencies);
            this.block.hasUpdateMethod = this.block.dependencies.size > 0;
            if (this.else) {
                this.else.block = block.child({
                    comment: createDebuggingComment(this.else, this.compiler),
                    name: this.compiler.getUniqueName(`${this.block.name}_else`),
                });
                this.compiler.target.blocks.push(this.else.block);
                this.else.initChildren(this.else.block, stripWhitespace, nextSibling);
                this.else.block.hasUpdateMethod = this.else.block.dependencies.size > 0;
            }
            if (this.block.hasOutros || (this.else && this.else.block.hasOutros)) {
                block.addOutro();
            }
        }
        build(block, parentNode, parentNodes) {
            if (this.children.length === 0)
                return;
            const { compiler } = this;
            const each = this.var;
            const create_each_block = this.block.name;
            const iterations = this.iterations;
            const needsAnchor = this.next ? !this.next.isDomNode() : !parentNode || !this.parent.isDomNode();
            const anchor = needsAnchor
                ? block.getUniqueName(`${each}_anchor`)
                : (this.next && this.next.var) || 'null';
            // hack the sourcemap, so that if data is missing the bug
            // is easy to find
            let c = this.start + 2;
            while (compiler.source[c] !== 'e')
                c += 1;
            compiler.code.overwrite(c, c + 4, 'length');
            const length = `[✂${c}-${c + 4}✂]`;
            const mountOrIntro = (this.block.hasIntroMethod || this.block.hasOutroMethod) ? 'i' : 'm';
            const vars = {
                each,
                create_each_block,
                length,
                iterations,
                anchor,
                mountOrIntro,
            };
            const { snippet } = this.expression;
            block.builders.init.addLine(`var ${this.each_block_value} = ${snippet};`);
            this.compiler.target.blocks.push(deindent `
			function ${this.get_each_context}(ctx, list, i) {
				const child_ctx = Object.create(ctx);
				${this.contextProps}
				return child_ctx;
			}
		`);
            if (this.key) {
                this.buildKeyed(block, parentNode, parentNodes, snippet, vars);
            }
            else {
                this.buildUnkeyed(block, parentNode, parentNodes, snippet, vars);
            }
            if (needsAnchor) {
                block.addElement(anchor, `@createComment()`, parentNodes && `@createComment()`, parentNode);
            }
            if (this.else) {
                const each_block_else = compiler.getUniqueName(`${each}_else`);
                block.builders.init.addLine(`var ${each_block_else} = null;`);
                // TODO neaten this up... will end up with an empty line in the block
                block.builders.init.addBlock(deindent `
				if (!${this.each_block_value}.${length}) {
					${each_block_else} = ${this.else.block.name}(#component, ctx);
					${each_block_else}.c();
				}
			`);
                block.builders.mount.addBlock(deindent `
				if (${each_block_else}) {
					${each_block_else}.${mountOrIntro}(${parentNode || '#target'}, null);
				}
			`);
                const initialMountNode = parentNode || `${anchor}.parentNode`;
                if (this.else.block.hasUpdateMethod) {
                    block.builders.update.addBlock(deindent `
					if (!${this.each_block_value}.${length} && ${each_block_else}) {
						${each_block_else}.p(changed, ctx);
					} else if (!${this.each_block_value}.${length}) {
						${each_block_else} = ${this.else.block.name}(#component, ctx);
						${each_block_else}.c();
						${each_block_else}.${mountOrIntro}(${initialMountNode}, ${anchor});
					} else if (${each_block_else}) {
						${each_block_else}.d(1);
						${each_block_else} = null;
					}
				`);
                }
                else {
                    block.builders.update.addBlock(deindent `
					if (${this.each_block_value}.${length}) {
						if (${each_block_else}) {
							${each_block_else}.d(1);
							${each_block_else} = null;
						}
					} else if (!${each_block_else}) {
						${each_block_else} = ${this.else.block.name}(#component, ctx);
						${each_block_else}.c();
						${each_block_else}.${mountOrIntro}(${initialMountNode}, ${anchor});
					}
				`);
                }
                block.builders.destroy.addBlock(deindent `
				if (${each_block_else}) ${each_block_else}.d(${parentNode ? '' : 'detach'});
			`);
            }
            this.children.forEach((child) => {
                child.build(this.block, null, 'nodes');
            });
            if (this.else) {
                this.else.children.forEach((child) => {
                    child.build(this.else.block, null, 'nodes');
                });
            }
        }
        buildKeyed(block, parentNode, parentNodes, snippet, { each, create_each_block, length, anchor, mountOrIntro, }) {
            const get_key = block.getUniqueName('get_key');
            const blocks = block.getUniqueName(`${each}_blocks`);
            const lookup = block.getUniqueName(`${each}_lookup`);
            block.addVariable(blocks, '[]');
            block.addVariable(lookup, `@blankObject()`);
            if (this.children[0].isDomNode()) {
                this.block.first = this.children[0].var;
            }
            else {
                this.block.first = this.block.getUniqueName('first');
                this.block.addElement(this.block.first, `@createComment()`, parentNodes && `@createComment()`, null);
            }
            block.builders.init.addBlock(deindent `
			const ${get_key} = ctx => ${this.key.snippet};

			for (var #i = 0; #i < ${this.each_block_value}.${length}; #i += 1) {
				let child_ctx = ${this.get_each_context}(ctx, ${this.each_block_value}, #i);
				let key = ${get_key}(child_ctx);
				${blocks}[#i] = ${lookup}[key] = ${create_each_block}(#component, key, child_ctx);
			}
		`);
            const initialMountNode = parentNode || '#target';
            const updateMountNode = this.getUpdateMountNode(anchor);
            const anchorNode = parentNode ? 'null' : 'anchor';
            block.builders.create.addBlock(deindent `
			for (#i = 0; #i < ${blocks}.length; #i += 1) ${blocks}[#i].c();
		`);
            if (parentNodes) {
                block.builders.claim.addBlock(deindent `
				for (#i = 0; #i < ${blocks}.length; #i += 1) ${blocks}[#i].l(${parentNodes});
			`);
            }
            block.builders.mount.addBlock(deindent `
			for (#i = 0; #i < ${blocks}.length; #i += 1) ${blocks}[#i].${mountOrIntro}(${initialMountNode}, ${anchorNode});
		`);
            const dynamic = this.block.hasUpdateMethod;
            const rects = block.getUniqueName('rects');
            const destroy = this.block.hasAnimation
                ? `@fixAndOutroAndDestroyBlock`
                : this.block.hasOutros
                    ? `@outroAndDestroyBlock`
                    : `@destroyBlock`;
            block.builders.update.addBlock(deindent `
			const ${this.each_block_value} = ${snippet};

			${this.block.hasOutros && `@transitionManager.groupOutros();`}
			${this.block.hasAnimation && `for (let #i = 0; #i < ${blocks}.length; #i += 1) ${blocks}[#i].r();`}
			${blocks} = @updateKeyedEach(${blocks}, #component, changed, ${get_key}, ${dynamic ? '1' : '0'}, ctx, ${this.each_block_value}, ${lookup}, ${updateMountNode}, ${destroy}, ${create_each_block}, "${mountOrIntro}", ${anchor}, ${this.get_each_context});
			${this.block.hasAnimation && `for (let #i = 0; #i < ${blocks}.length; #i += 1) ${blocks}[#i].a();`}
		`);
            if (this.compiler.options.nestedTransitions) {
                block.builders.outro.addBlock(deindent `
				#outrocallback = @callAfter(#outrocallback, ${blocks}.length);
				for (#i = 0; #i < ${blocks}.length; #i += 1) ${blocks}[#i].o(#outrocallback);
			`);
            }
            block.builders.destroy.addBlock(deindent `
			for (#i = 0; #i < ${blocks}.length; #i += 1) ${blocks}[#i].d(${parentNode ? '' : 'detach'});
		`);
        }
        buildUnkeyed(block, parentNode, parentNodes, snippet, { create_each_block, length, iterations, anchor, mountOrIntro, }) {
            block.builders.init.addBlock(deindent `
			var ${iterations} = [];

			for (var #i = 0; #i < ${this.each_block_value}.${length}; #i += 1) {
				${iterations}[#i] = ${create_each_block}(#component, ${this.get_each_context}(ctx, ${this.each_block_value}, #i));
			}
		`);
            const initialMountNode = parentNode || '#target';
            const updateMountNode = this.getUpdateMountNode(anchor);
            const anchorNode = parentNode ? 'null' : 'anchor';
            block.builders.create.addBlock(deindent `
			for (var #i = 0; #i < ${iterations}.length; #i += 1) {
				${iterations}[#i].c();
			}
		`);
            if (parentNodes) {
                block.builders.claim.addBlock(deindent `
				for (var #i = 0; #i < ${iterations}.length; #i += 1) {
					${iterations}[#i].l(${parentNodes});
				}
			`);
            }
            block.builders.mount.addBlock(deindent `
			for (var #i = 0; #i < ${iterations}.length; #i += 1) {
				${iterations}[#i].${mountOrIntro}(${initialMountNode}, ${anchorNode});
			}
		`);
            const allDependencies = new Set(this.block.dependencies);
            const { dependencies } = this.expression;
            dependencies.forEach((dependency) => {
                allDependencies.add(dependency);
            });
            const outro = this.block.hasOutros && block.getUniqueName('outro');
            if (outro) {
                block.builders.init.addBlock(deindent `
				function ${outro}(i, detach, fn) {
					if (${iterations}[i]) {
						${iterations}[i].o(() => {
							${iterations}[i].d(detach);
							if (detach) ${iterations}[i] = null;
							if (fn) fn();
						});
					}
				}
			`);
            }
            // TODO do this for keyed blocks as well
            const condition = Array.from(allDependencies)
                .map(dependency => `changed.${dependency}`)
                .join(' || ');
            if (condition !== '') {
                const forLoopBody = this.block.hasUpdateMethod
                    ? (this.block.hasIntros || this.block.hasOutros)
                        ? deindent `
						if (${iterations}[#i]) {
							${iterations}[#i].p(changed, child_ctx);
						} else {
							${iterations}[#i] = ${create_each_block}(#component, child_ctx);
							${iterations}[#i].c();
						}
						${iterations}[#i].i(${updateMountNode}, ${anchor});
					`
                        : deindent `
						if (${iterations}[#i]) {
							${iterations}[#i].p(changed, child_ctx);
						} else {
							${iterations}[#i] = ${create_each_block}(#component, child_ctx);
							${iterations}[#i].c();
							${iterations}[#i].m(${updateMountNode}, ${anchor});
						}
					`
                    : deindent `
					${iterations}[#i] = ${create_each_block}(#component, child_ctx);
					${iterations}[#i].c();
					${iterations}[#i].${mountOrIntro}(${updateMountNode}, ${anchor});
				`;
                const start = this.block.hasUpdateMethod ? '0' : `${iterations}.length`;
                let destroy;
                if (this.block.hasOutros) {
                    destroy = deindent `
					@transitionManager.groupOutros();
					for (; #i < ${iterations}.length; #i += 1) ${outro}(#i, 1);
				`;
                }
                else {
                    destroy = deindent `
					for (; #i < ${iterations}.length; #i += 1) {
						${iterations}[#i].d(1);
					}
					${iterations}.length = ${this.each_block_value}.${length};
				`;
                }
                block.builders.update.addBlock(deindent `
				if (${condition}) {
					${this.each_block_value} = ${snippet};

					for (var #i = ${start}; #i < ${this.each_block_value}.${length}; #i += 1) {
						const child_ctx = ${this.get_each_context}(ctx, ${this.each_block_value}, #i);

						${forLoopBody}
					}

					${destroy}
				}
			`);
            }
            if (outro && this.compiler.options.nestedTransitions) {
                block.builders.outro.addBlock(deindent `
				#outrocallback = @callAfter(#outrocallback, #i);
				for (let #i = 0; #i < ${iterations}.length; #i += 1) ${outro}(#i, 0, #outrocallback);`);
            }
            block.builders.destroy.addBlock(`@destroyEach(${iterations}, detach);`);
        }
        remount(name) {
            // TODO consider keyed blocks
            return `for (var #i = 0; #i < ${this.iterations}.length; #i += 1) ${this.iterations}[#i].m(${name}._slotted.default, null);`;
        }
        ssr() {
            const { compiler } = this;
            const { snippet } = this.expression;
            const props = this.contexts.map(prop => `${prop.key.name}: item${prop.tail}`);
            const getContext = this.index
                ? `(item, i) => Object.assign({}, ctx, { ${props.join(', ')}, ${this.index}: i })`
                : `item => Object.assign({}, ctx, { ${props.join(', ')} })`;
            const open = `\${ ${this.else ? `${snippet}.length ? ` : ''}@each(${snippet}, ${getContext}, ctx => \``;
            compiler.target.append(open);
            this.children.forEach((child) => {
                child.ssr();
            });
            const close = `\`)`;
            compiler.target.append(close);
            if (this.else) {
                compiler.target.append(` : \``);
                this.else.children.forEach((child) => {
                    child.ssr();
                });
                compiler.target.append(`\``);
            }
            compiler.target.append('}');
        }
    }

    class Transition extends Node$1 {
        constructor(compiler, parent, scope, info) {
            super(compiler, parent, scope, info);
            this.name = info.name;
            this.expression = info.expression
                ? new Expression(compiler, this, scope, info.expression)
                : null;
        }
    }

    class Animation extends Node$1 {
        constructor(compiler, parent, scope, info) {
            super(compiler, parent, scope, info);
            this.name = info.name;
            this.expression = info.expression
                ? new Expression(compiler, this, scope, info.expression)
                : null;
        }
        build(block, parentNode, parentNodes) {
        }
    }

    class Action extends Node$1 {
        constructor(compiler, parent, scope, info) {
            super(compiler, parent, scope, info);
            this.name = info.name;
            this.expression = info.expression
                ? new Expression(compiler, this, scope, info.expression)
                : null;
        }
    }

    // Whitespace inside one of these elements will not result in
    // a whitespace node being created in any circumstances. (This
    // list is almost certainly very incomplete)
    const elementsWithoutText = new Set([
        'audio',
        'datalist',
        'dl',
        'ol',
        'optgroup',
        'select',
        'ul',
        'video',
    ]);
    function shouldSkip$1(node) {
        if (/\S/.test(node.data))
            return false;
        const parentElement = node.findNearest(/(?:Element|Component|Head)/);
        if (!parentElement)
            return false;
        if (parentElement.type === 'Head')
            return true;
        if (parentElement.type === 'Component')
            return parentElement.children.length === 1 && node === parentElement.children[0];
        return parentElement.namespace || elementsWithoutText.has(parentElement.name);
    }
    class Text extends Node$1 {
        constructor(compiler, parent, scope, info) {
            super(compiler, parent, scope, info);
            this.data = info.data;
        }
        init(block) {
            const parentElement = this.findNearest(/(?:Element|Component)/);
            if (shouldSkip$1(this)) {
                this.shouldSkip = true;
                return;
            }
            this.var = block.getUniqueName(`text`);
        }
        build(block, parentNode, parentNodes) {
            if (this.shouldSkip)
                return;
            block.addElement(this.var, `@createText(${stringify(this.data)})`, parentNodes && `@claimText(${parentNodes}, ${stringify(this.data)})`, parentNode);
        }
        remount(name) {
            return `@appendNode(${this.var}, ${name}._slotted.default);`;
        }
        ssr() {
            let text = this.data;
            if (!this.parent ||
                this.parent.type !== 'Element' ||
                (this.parent.name !== 'script' && this.parent.name !== 'style')) {
                // unless this Text node is inside a <script> or <style> element, escape &,<,>
                text = escapeHTML(text);
            }
            this.compiler.target.append(escape(escapeTemplate(text)));
        }
    }

    // source: https://gist.github.com/ArjanSchouten/0b8574a6ad7f5065a5e7
    const booleanAttributes = new Set('async autocomplete autofocus autoplay border challenge checked compact contenteditable controls default defer disabled formnovalidate frameborder hidden indeterminate ismap loop multiple muted nohref noresize noshade novalidate nowrap open readonly required reversed scoped scrolling seamless selected sortable spellcheck translate'.split(' '));
    class Element extends Node$1 {
        constructor(compiler, parent, scope, info) {
            super(compiler, parent, scope, info);
            this.name = info.name;
            this.scope = scope;
            const parentElement = parent.findNearest(/^Element/);
            this.namespace = this.name === 'svg' ?
                svg :
                parentElement ? parentElement.namespace : this.compiler.namespace;
            this.attributes = [];
            this.actions = [];
            this.bindings = [];
            this.handlers = [];
            this.intro = null;
            this.outro = null;
            this.animation = null;
            if (this.name === 'textarea') {
                // this is an egregious hack, but it's the easiest way to get <textarea>
                // children treated the same way as a value attribute
                if (info.children.length > 0) {
                    info.attributes.push({
                        type: 'Attribute',
                        name: 'value',
                        value: info.children
                    });
                    info.children = [];
                }
            }
            if (this.name === 'option') {
                // Special case — treat these the same way:
                //   <option>{foo}</option>
                //   <option value={foo}>{foo}</option>
                const valueAttribute = info.attributes.find((attribute) => attribute.name === 'value');
                if (!valueAttribute) {
                    info.attributes.push({
                        type: 'Attribute',
                        name: 'value',
                        value: info.children,
                        synthetic: true
                    });
                }
            }
            info.attributes.forEach(node => {
                switch (node.type) {
                    case 'Action':
                        this.actions.push(new Action(compiler, this, scope, node));
                        break;
                    case 'Attribute':
                    case 'Spread':
                        // special case
                        if (node.name === 'xmlns')
                            this.namespace = node.value[0].data;
                        this.attributes.push(new Attribute(compiler, this, scope, node));
                        break;
                    case 'Binding':
                        this.bindings.push(new Binding(compiler, this, scope, node));
                        break;
                    case 'EventHandler':
                        this.handlers.push(new EventHandler(compiler, this, scope, node));
                        break;
                    case 'Transition':
                        const transition = new Transition(compiler, this, scope, node);
                        if (node.intro)
                            this.intro = transition;
                        if (node.outro)
                            this.outro = transition;
                        break;
                    case 'Animation':
                        this.animation = new Animation(compiler, this, scope, node);
                        break;
                    case 'Ref':
                        // TODO catch this in validation
                        if (this.ref)
                            throw new Error(`Duplicate refs`);
                        compiler.usesRefs = true;
                        this.ref = node.name;
                        break;
                    default:
                        throw new Error(`Not implemented: ${node.type}`);
                }
            });
            this.children = mapChildren(compiler, this, scope, info.children);
            compiler.stylesheet.apply(this);
        }
        init(block, stripWhitespace, nextSibling) {
            if (this.name === 'slot' || this.name === 'option') {
                this.cannotUseInnerHTML();
            }
            this.var = block.getUniqueName(this.name.replace(/[^a-zA-Z0-9_$]/g, '_'));
            this.attributes.forEach(attr => {
                if (attr.dependencies.size) {
                    this.parent.cannotUseInnerHTML();
                    block.addDependencies(attr.dependencies);
                    // special case — <option value={foo}> — see below
                    if (this.name === 'option' && attr.name === 'value') {
                        let select = this.parent;
                        while (select && (select.type !== 'Element' || select.name !== 'select'))
                            select = select.parent;
                        if (select && select.selectBindingDependencies) {
                            select.selectBindingDependencies.forEach(prop => {
                                attr.dependencies.forEach((dependency) => {
                                    this.compiler.indirectDependencies.get(prop).add(dependency);
                                });
                            });
                        }
                    }
                }
            });
            this.actions.forEach(action => {
                this.parent.cannotUseInnerHTML();
                if (action.expression) {
                    block.addDependencies(action.expression.dependencies);
                }
            });
            this.bindings.forEach(binding => {
                this.parent.cannotUseInnerHTML();
                block.addDependencies(binding.value.dependencies);
            });
            this.handlers.forEach(handler => {
                this.parent.cannotUseInnerHTML();
                block.addDependencies(handler.dependencies);
            });
            if (this.intro || this.outro || this.animation || this.ref) {
                this.parent.cannotUseInnerHTML();
            }
            if (this.intro)
                block.addIntro();
            if (this.outro)
                block.addOutro();
            if (this.animation)
                block.addAnimation();
            const valueAttribute = this.attributes.find((attribute) => attribute.name === 'value');
            // special case — in a case like this...
            //
            //   <select bind:value='foo'>
            //     <option value='{bar}'>bar</option>
            //     <option value='{baz}'>baz</option>
            //   </option>
            //
            // ...we need to know that `foo` depends on `bar` and `baz`,
            // so that if `foo.qux` changes, we know that we need to
            // mark `bar` and `baz` as dirty too
            if (this.name === 'select') {
                const binding = this.bindings.find(node => node.name === 'value');
                if (binding) {
                    // TODO does this also apply to e.g. `<input type='checkbox' bind:group='foo'>`?
                    const dependencies = binding.value.dependencies;
                    this.selectBindingDependencies = dependencies;
                    dependencies.forEach((prop) => {
                        this.compiler.indirectDependencies.set(prop, new Set());
                    });
                }
                else {
                    this.selectBindingDependencies = null;
                }
            }
            const slot = this.getStaticAttributeValue('slot');
            if (slot && this.hasAncestor('Component')) {
                this.cannotUseInnerHTML();
                this.slotted = true;
                // TODO validate slots — no nesting, no dynamic names...
                const component = this.findNearest(/^Component/);
                component._slots.add(slot);
            }
            if (this.children.length) {
                if (this.name === 'pre' || this.name === 'textarea')
                    stripWhitespace = false;
                this.initChildren(block, stripWhitespace, nextSibling);
            }
        }
        build(block, parentNode, parentNodes) {
            const { compiler } = this;
            if (this.name === 'slot') {
                const slotName = this.getStaticAttributeValue('name') || 'default';
                this.compiler.slots.add(slotName);
            }
            if (this.name === 'noscript')
                return;
            const childState = {
                parentNode: this.var,
                parentNodes: parentNodes && block.getUniqueName(`${this.var}_nodes`) // if we're in unclaimable territory, i.e. <head>, parentNodes is null
            };
            const name = this.var;
            const slot = this.attributes.find((attribute) => attribute.name === 'slot');
            const prop = slot && quotePropIfNecessary(slot.chunks[0].data);
            const initialMountNode = this.slotted ?
                `${this.findNearest(/^Component/).var}._slotted${prop}` : // TODO this looks bonkers
                parentNode;
            block.addVariable(name);
            const renderStatement = getRenderStatement(this.namespace, this.name);
            block.builders.create.addLine(`${name} = ${renderStatement};`);
            if (this.compiler.options.hydratable) {
                if (parentNodes) {
                    block.builders.claim.addBlock(deindent `
					${name} = ${getClaimStatement(compiler, this.namespace, parentNodes, this)};
					var ${childState.parentNodes} = @children(${name});
				`);
                }
                else {
                    block.builders.claim.addLine(`${name} = ${renderStatement};`);
                }
            }
            if (initialMountNode) {
                block.builders.mount.addLine(`@appendNode(${name}, ${initialMountNode});`);
                if (initialMountNode === 'document.head') {
                    block.builders.destroy.addLine(`@detachNode(${name});`);
                }
            }
            else {
                block.builders.mount.addLine(`@insertNode(${name}, #target, anchor);`);
                // TODO we eventually need to consider what happens to elements
                // that belong to the same outgroup as an outroing element...
                block.builders.destroy.addConditional('detach', `@detachNode(${name});`);
            }
            // TODO move this into a class as well?
            if (this._cssRefAttribute) {
                block.builders.hydrate.addLine(`@setAttribute(${name}, "svelte-ref-${this._cssRefAttribute}", "");`);
            }
            // insert static children with textContent or innerHTML
            if (!this.namespace && this.canUseInnerHTML && this.children.length > 0) {
                if (this.children.length === 1 && this.children[0].type === 'Text') {
                    block.builders.create.addLine(`${name}.textContent = ${stringify(this.children[0].data)};`);
                }
                else {
                    block.builders.create.addLine(`${name}.innerHTML = ${stringify(this.children.map(toHTML).join(''))};`);
                }
            }
            else {
                this.children.forEach((child) => {
                    child.build(block, childState.parentNode, childState.parentNodes);
                });
            }
            let hasHoistedEventHandlerOrBinding = (
            //(this.hasAncestor('EachBlock') && this.bindings.length > 0) ||
            this.handlers.some(handler => handler.shouldHoist));
            const eventHandlerOrBindingUsesComponent = (this.bindings.length > 0 ||
                this.handlers.some(handler => handler.usesComponent));
            const eventHandlerOrBindingUsesContext = (this.bindings.some(binding => binding.usesContext) ||
                this.handlers.some(handler => handler.usesContext));
            if (hasHoistedEventHandlerOrBinding) {
                const initialProps = [];
                if (eventHandlerOrBindingUsesComponent) {
                    const component = block.alias('component');
                    initialProps.push(component === 'component' ? 'component' : `component: ${component}`);
                }
                if (eventHandlerOrBindingUsesContext) {
                    initialProps.push(`ctx`);
                    block.builders.update.addLine(`${name}._svelte.ctx = ctx;`);
                }
                if (initialProps.length) {
                    block.builders.hydrate.addBlock(deindent `
					${name}._svelte = { ${initialProps.join(', ')} };
				`);
                }
            }
            else {
                if (eventHandlerOrBindingUsesContext) {
                    block.maintainContext = true;
                }
            }
            this.addBindings(block);
            this.addEventHandlers(block);
            if (this.ref)
                this.addRef(block);
            this.addAttributes(block);
            this.addTransitions(block);
            this.addAnimation(block);
            this.addActions(block);
            if (this.initialUpdate) {
                block.builders.mount.addBlock(this.initialUpdate);
            }
            if (childState.parentNodes) {
                block.builders.claim.addLine(`${childState.parentNodes}.forEach(@detachNode);`);
            }
            function toHTML(node) {
                if (node.type === 'Text') {
                    return node.parent &&
                        node.parent.type === 'Element' &&
                        (node.parent.name === 'script' || node.parent.name === 'style')
                        ? node.data
                        : escapeHTML(node.data);
                }
                if (node.name === 'noscript')
                    return '';
                let open = `<${node.name}`;
                if (node._cssRefAttribute) {
                    open += ` svelte-ref-${node._cssRefAttribute}`;
                }
                node.attributes.forEach((attr) => {
                    open += ` ${fixAttributeCasing(attr.name)}${stringifyAttributeValue(attr.chunks)}`;
                });
                if (isVoidElementName(node.name))
                    return open + '>';
                return `${open}>${node.children.map(toHTML).join('')}</${node.name}>`;
            }
        }
        addBindings(block) {
            if (this.bindings.length === 0)
                return;
            if (this.name === 'select' || this.isMediaNode())
                this.compiler.target.hasComplexBindings = true;
            const needsLock = this.name !== 'input' || !/radio|checkbox|range|color/.test(this.getStaticAttributeValue('type'));
            // TODO munge in constructor
            const mungedBindings = this.bindings.map(binding => binding.munge(block));
            const lock = mungedBindings.some(binding => binding.needsLock) ?
                block.getUniqueName(`${this.var}_updating`) :
                null;
            if (lock)
                block.addVariable(lock, 'false');
            const groups = events$1
                .map(event => {
                return {
                    events: event.eventNames,
                    bindings: mungedBindings.filter(binding => event.filter(this, binding.name))
                };
            })
                .filter(group => group.bindings.length);
            groups.forEach(group => {
                const handler = block.getUniqueName(`${this.var}_${group.events.join('_')}_handler`);
                const needsLock = group.bindings.some(binding => binding.needsLock);
                group.bindings.forEach(binding => {
                    if (!binding.updateDom)
                        return;
                    const updateConditions = needsLock ? [`!${lock}`] : [];
                    if (binding.updateCondition)
                        updateConditions.push(binding.updateCondition);
                    block.builders.update.addLine(updateConditions.length ? `if (${updateConditions.join(' && ')}) ${binding.updateDom}` : binding.updateDom);
                });
                const usesContext = group.bindings.some(binding => binding.handler.usesContext);
                const usesState = group.bindings.some(binding => binding.handler.usesState);
                const usesStore = group.bindings.some(binding => binding.handler.usesStore);
                const mutations = group.bindings.map(binding => binding.handler.mutation).filter(Boolean).join('\n');
                const props = new Set();
                const storeProps = new Set();
                group.bindings.forEach(binding => {
                    binding.handler.props.forEach(prop => {
                        props.add(prop);
                    });
                    binding.handler.storeProps.forEach(prop => {
                        storeProps.add(prop);
                    });
                }); // TODO use stringifyProps here, once indenting is fixed
                // media bindings — awkward special case. The native timeupdate events
                // fire too infrequently, so we need to take matters into our
                // own hands
                let animation_frame;
                if (group.events[0] === 'timeupdate') {
                    animation_frame = block.getUniqueName(`${this.var}_animationframe`);
                    block.addVariable(animation_frame);
                }
                block.builders.init.addBlock(deindent `
				function ${handler}() {
					${animation_frame && deindent `
							cancelAnimationFrame(${animation_frame});
							if (!${this.var}.paused) ${animation_frame} = requestAnimationFrame(${handler});`}
					${usesStore && `var $ = #component.store.get();`}
					${needsLock && `${lock} = true;`}
					${mutations.length > 0 && mutations}
					${props.size > 0 && `#component.set({ ${Array.from(props).join(', ')} });`}
					${storeProps.size > 0 && `#component.store.set({ ${Array.from(storeProps).join(', ')} });`}
					${needsLock && `${lock} = false;`}
				}
			`);
                group.events.forEach(name => {
                    if (name === 'resize') {
                        // special case
                        const resize_listener = block.getUniqueName(`${this.var}_resize_listener`);
                        block.addVariable(resize_listener);
                        block.builders.mount.addLine(`${resize_listener} = @addResizeListener(${this.var}, ${handler});`);
                        block.builders.destroy.addLine(`${resize_listener}.cancel();`);
                    }
                    else {
                        block.builders.hydrate.addLine(`@addListener(${this.var}, "${name}", ${handler});`);
                        block.builders.destroy.addLine(`@removeListener(${this.var}, "${name}", ${handler});`);
                    }
                });
                const allInitialStateIsDefined = group.bindings
                    .map(binding => `'${binding.object}' in ctx`)
                    .join(' && ');
                if (this.name === 'select' || group.bindings.find(binding => binding.name === 'indeterminate' || binding.isReadOnlyMediaAttribute)) {
                    this.compiler.target.hasComplexBindings = true;
                    block.builders.hydrate.addLine(`if (!(${allInitialStateIsDefined})) #component.root._beforecreate.push(${handler});`);
                }
                if (group.events[0] === 'resize') {
                    this.compiler.target.hasComplexBindings = true;
                    block.builders.hydrate.addLine(`#component.root._beforecreate.push(${handler});`);
                }
            });
            this.initialUpdate = mungedBindings.map(binding => binding.initialUpdate).filter(Boolean).join('\n');
        }
        addAttributes(block) {
            if (this.attributes.find(attr => attr.type === 'Spread')) {
                this.addSpreadAttributes(block);
                return;
            }
            this.attributes.forEach((attribute) => {
                attribute.render(block);
            });
        }
        addSpreadAttributes(block) {
            const levels = block.getUniqueName(`${this.var}_levels`);
            const data = block.getUniqueName(`${this.var}_data`);
            const initialProps = [];
            const updates = [];
            this.attributes
                .filter(attr => attr.type === 'Attribute' || attr.type === 'Spread')
                .forEach(attr => {
                const condition = attr.dependencies.size > 0
                    ? [...attr.dependencies].map(d => `changed.${d}`).join(' || ')
                    : null;
                if (attr.isSpread) {
                    const { snippet, dependencies } = attr.expression;
                    initialProps.push(snippet);
                    updates.push(condition ? `${condition} && ${snippet}` : snippet);
                }
                else {
                    const snippet = `{ ${quoteNameIfNecessary(attr.name)}: ${attr.getValue()} }`;
                    initialProps.push(snippet);
                    updates.push(condition ? `${condition} && ${snippet}` : snippet);
                }
            });
            block.builders.init.addBlock(deindent `
			var ${levels} = [
				${initialProps.join(',\n')}
			];

			var ${data} = {};
			for (var #i = 0; #i < ${levels}.length; #i += 1) {
				${data} = @assign(${data}, ${levels}[#i]);
			}
		`);
            block.builders.hydrate.addLine(`@setAttributes(${this.var}, ${data});`);
            block.builders.update.addBlock(deindent `
			@setAttributes(${this.var}, @getSpreadUpdate(${levels}, [
				${updates.join(',\n')}
			]));
		`);
        }
        addEventHandlers(block) {
            const { compiler } = this;
            this.handlers.forEach(handler => {
                const isCustomEvent = compiler.events.has(handler.name);
                if (handler.callee) {
                    handler.render(this.compiler, block, handler.shouldHoist);
                }
                const target = handler.shouldHoist ? 'this' : this.var;
                // get a name for the event handler that is globally unique
                // if hoisted, locally unique otherwise
                const handlerName = (handler.shouldHoist ? compiler : block).getUniqueName(`${handler.name.replace(/[^a-zA-Z0-9_$]/g, '_')}_handler`);
                const component = block.alias('component'); // can't use #component, might be hoisted
                // create the handler body
                const handlerBody = deindent `
				${handler.shouldHoist && (handler.usesComponent || handler.usesContext
                ? `const { ${[handler.usesComponent && 'component', handler.usesContext && 'ctx'].filter(Boolean).join(', ')} } = ${target}._svelte;`
                : null)}

				${handler.snippet ?
                handler.snippet :
                `${component}.fire("${handler.name}", event);`}
			`;
                if (isCustomEvent) {
                    block.addVariable(handlerName);
                    block.builders.hydrate.addBlock(deindent `
					${handlerName} = %events-${handler.name}.call(${component}, ${this.var}, function(event) {
						${handlerBody}
					});
				`);
                    block.builders.destroy.addLine(deindent `
					${handlerName}.destroy();
				`);
                }
                else {
                    const handlerFunction = deindent `
					function ${handlerName}(event) {
						${handlerBody}
					}
				`;
                    if (handler.shouldHoist) {
                        compiler.target.blocks.push(handlerFunction);
                    }
                    else {
                        block.builders.init.addBlock(handlerFunction);
                    }
                    block.builders.hydrate.addLine(`@addListener(${this.var}, "${handler.name}", ${handlerName});`);
                    block.builders.destroy.addLine(`@removeListener(${this.var}, "${handler.name}", ${handlerName});`);
                }
            });
        }
        addRef(block) {
            const ref = `#component.refs.${this.ref}`;
            block.builders.mount.addLine(`${ref} = ${this.var};`);
            block.builders.destroy.addLine(`if (${ref} === ${this.var}) ${ref} = null;`);
        }
        addTransitions(block) {
            const { intro, outro } = this;
            if (!intro && !outro)
                return;
            if (intro === outro) {
                const name = block.getUniqueName(`${this.var}_transition`);
                const snippet = intro.expression
                    ? intro.expression.snippet
                    : '{}';
                block.addVariable(name);
                const fn = `%transitions-${intro.name}`;
                block.builders.intro.addConditional(`#component.root._intro`, deindent `
				if (${name}) ${name}.invalidate();

				#component.root._aftercreate.push(() => {
					if (!${name}) ${name} = @wrapTransition(#component, ${this.var}, ${fn}, ${snippet}, true);
					${name}.run(1);
				});
			`);
                block.builders.outro.addBlock(deindent `
				if (!${name}) ${name} = @wrapTransition(#component, ${this.var}, ${fn}, ${snippet}, false);
				${name}.run(0, () => {
					#outrocallback();
					${name} = null;
				});
			`);
            }
            else {
                const introName = intro && block.getUniqueName(`${this.var}_intro`);
                const outroName = outro && block.getUniqueName(`${this.var}_outro`);
                if (intro) {
                    block.addVariable(introName);
                    const snippet = intro.expression
                        ? intro.expression.snippet
                        : '{}';
                    const fn = `%transitions-${intro.name}`; // TODO add built-in transitions?
                    if (outro) {
                        block.builders.intro.addBlock(deindent `
						if (${introName}) ${introName}.abort();
						if (${outroName}) ${outroName}.abort();
					`);
                    }
                    block.builders.intro.addConditional(`#component.root._intro`, deindent `
					#component.root._aftercreate.push(() => {
						${introName} = @wrapTransition(#component, ${this.var}, ${fn}, ${snippet}, true);
						${introName}.run(1);
					});
				`);
                }
                if (outro) {
                    block.addVariable(outroName);
                    const snippet = outro.expression
                        ? outro.expression.snippet
                        : '{}';
                    const fn = `%transitions-${outro.name}`;
                    block.builders.intro.addBlock(deindent `
					if (${outroName}) ${outroName}.abort();
				`);
                    // TODO hide elements that have outro'd (unless they belong to a still-outroing
                    // group) prior to their removal from the DOM
                    block.builders.outro.addBlock(deindent `
					${outroName} = @wrapTransition(#component, ${this.var}, ${fn}, ${snippet}, false);
					${outroName}.run(0, #outrocallback);
				`);
                }
            }
        }
        addAnimation(block) {
            if (!this.animation)
                return;
            const rect = block.getUniqueName('rect');
            const animation = block.getUniqueName('animation');
            block.addVariable(rect);
            block.addVariable(animation);
            block.builders.measure.addBlock(deindent `
			${rect} = ${this.var}.getBoundingClientRect();
		`);
            block.builders.fix.addBlock(deindent `
			@fixPosition(${this.var});
			if (${animation}) ${animation}.stop();
		`);
            const params = this.animation.expression ? this.animation.expression.snippet : '{}';
            block.builders.animate.addBlock(deindent `
			if (${animation}) ${animation}.stop();
			${animation} = @wrapAnimation(${this.var}, ${rect}, %animations-${this.animation.name}, ${params});
		`);
        }
        addActions(block) {
            this.actions.forEach(action => {
                const { expression } = action;
                let snippet, dependencies;
                if (expression) {
                    snippet = action.expression.snippet;
                    dependencies = action.expression.dependencies;
                }
                const name = block.getUniqueName(`${action.name.replace(/[^a-zA-Z0-9_$]/g, '_')}_action`);
                block.addVariable(name);
                const fn = `%actions-${action.name}`;
                block.builders.hydrate.addLine(`${name} = ${fn}.call(#component, ${this.var}${snippet ? `, ${snippet}` : ''}) || {};`);
                if (dependencies && dependencies.size > 0) {
                    let conditional = `typeof ${name}.update === 'function' && `;
                    const deps = [...dependencies].map(dependency => `changed.${dependency}`).join(' || ');
                    conditional += dependencies.size > 1 ? `(${deps})` : deps;
                    block.builders.update.addConditional(conditional, `${name}.update.call(#component, ${snippet});`);
                }
                block.builders.destroy.addLine(`if (typeof ${name}.destroy === 'function') ${name}.destroy.call(#component);`);
            });
        }
        getStaticAttributeValue(name) {
            const attribute = this.attributes.find((attr) => attr.type === 'Attribute' && attr.name.toLowerCase() === name);
            if (!attribute)
                return null;
            if (attribute.isTrue)
                return true;
            if (attribute.chunks.length === 0)
                return '';
            if (attribute.chunks.length === 1 && attribute.chunks[0].type === 'Text') {
                return attribute.chunks[0].data;
            }
            return null;
        }
        isMediaNode() {
            return this.name === 'audio' || this.name === 'video';
        }
        remount(name) {
            const slot = this.attributes.find(attribute => attribute.name === 'slot');
            if (slot) {
                const prop = quotePropIfNecessary(slot.chunks[0].data);
                return `@appendNode(${this.var}, ${name}._slotted${prop});`;
            }
            return `@appendNode(${this.var}, ${name}._slotted.default);`;
        }
        addCssClass() {
            const classAttribute = this.attributes.find(a => a.name === 'class');
            if (classAttribute && !classAttribute.isTrue) {
                if (classAttribute.chunks.length === 1 && classAttribute.chunks[0].type === 'Text') {
                    classAttribute.chunks[0].data += ` ${this.compiler.stylesheet.id}`;
                }
                else {
                    classAttribute.chunks.push(new Text(this.compiler, this, this.scope, {
                        type: 'Text',
                        data: ` ${this.compiler.stylesheet.id}`
                    })
                    // new Text({ type: 'Text', data: ` ${this.compiler.stylesheet.id}` })
                    );
                }
            }
            else {
                this.attributes.push(new Attribute(this.compiler, this, this.scope, {
                    type: 'Attribute',
                    name: 'class',
                    value: [{ type: 'Text', data: `${this.compiler.stylesheet.id}` }]
                }));
            }
        }
        ssr() {
            const { compiler } = this;
            let openingTag = `<${this.name}`;
            let textareaContents; // awkward special case
            const slot = this.getStaticAttributeValue('slot');
            if (slot && this.hasAncestor('Component')) {
                const slot = this.attributes.find((attribute) => attribute.name === 'slot');
                const slotName = slot.chunks[0].data;
                const appendTarget = compiler.target.appendTargets[compiler.target.appendTargets.length - 1];
                appendTarget.slotStack.push(slotName);
                appendTarget.slots[slotName] = '';
            }
            if (this.attributes.find(attr => attr.isSpread)) {
                // TODO dry this out
                const args = [];
                this.attributes.forEach(attribute => {
                    if (attribute.isSpread) {
                        args.push(attribute.expression.snippet);
                    }
                    else {
                        if (attribute.name === 'value' && this.name === 'textarea') {
                            textareaContents = attribute.stringifyForSsr();
                        }
                        else if (attribute.isTrue) {
                            args.push(`{ ${quoteNameIfNecessary(attribute.name)}: true }`);
                        }
                        else if (booleanAttributes.has(attribute.name) &&
                            attribute.chunks.length === 1 &&
                            attribute.chunks[0].type !== 'Text') {
                            // a boolean attribute with one non-Text chunk
                            args.push(`{ ${quoteNameIfNecessary(attribute.name)}: ${attribute.chunks[0].snippet} }`);
                        }
                        else {
                            args.push(`{ ${quoteNameIfNecessary(attribute.name)}: \`${attribute.stringifyForSsr()}\` }`);
                        }
                    }
                });
                openingTag += "${@spread([" + args.join(', ') + "])}";
            }
            else {
                this.attributes.forEach((attribute) => {
                    if (attribute.type !== 'Attribute')
                        return;
                    if (attribute.name === 'value' && this.name === 'textarea') {
                        textareaContents = attribute.stringifyForSsr();
                    }
                    else if (attribute.isTrue) {
                        openingTag += ` ${attribute.name}`;
                    }
                    else if (booleanAttributes.has(attribute.name) &&
                        attribute.chunks.length === 1 &&
                        attribute.chunks[0].type !== 'Text') {
                        // a boolean attribute with one non-Text chunk
                        openingTag += '${' + attribute.chunks[0].snippet + ' ? " ' + attribute.name + '" : "" }';
                    }
                    else {
                        openingTag += ` ${attribute.name}="${attribute.stringifyForSsr()}"`;
                    }
                });
            }
            if (this._cssRefAttribute) {
                openingTag += ` svelte-ref-${this._cssRefAttribute}`;
            }
            openingTag += '>';
            compiler.target.append(openingTag);
            if (this.name === 'textarea' && textareaContents !== undefined) {
                compiler.target.append(textareaContents);
            }
            else {
                this.children.forEach((child) => {
                    child.ssr();
                });
            }
            if (!isVoidElementName(this.name)) {
                compiler.target.append(`</${this.name}>`);
            }
        }
    }
    function getRenderStatement(namespace, name) {
        if (namespace === 'http://www.w3.org/2000/svg') {
            return `@createSvgElement("${name}")`;
        }
        if (namespace) {
            return `document.createElementNS("${namespace}", "${name}")`;
        }
        return `@createElement("${name}")`;
    }
    function getClaimStatement(compiler, namespace, nodes, node) {
        const attributes = node.attributes
            .filter((attr) => attr.type === 'Attribute')
            .map((attr) => `${quoteNameIfNecessary(attr.name)}: true`)
            .join(', ');
        const name = namespace ? node.name : node.name.toUpperCase();
        return `@claimElement(${nodes}, "${name}", ${attributes
        ? `{ ${attributes} }`
        : `{}`}, ${namespace === svg ? true : false})`;
    }
    function stringifyAttributeValue(value) {
        if (value === true)
            return '';
        if (value.length === 0)
            return `=""`;
        const data = value[0].data;
        return `=${JSON.stringify(data)}`;
    }
    const events$1 = [
        {
            eventNames: ['input'],
            filter: (node, name) => node.name === 'textarea' ||
                node.name === 'input' && !/radio|checkbox|range/.test(node.getStaticAttributeValue('type'))
        },
        {
            eventNames: ['change'],
            filter: (node, name) => node.name === 'select' ||
                node.name === 'input' && /radio|checkbox/.test(node.getStaticAttributeValue('type'))
        },
        {
            eventNames: ['change', 'input'],
            filter: (node, name) => node.name === 'input' && node.getStaticAttributeValue('type') === 'range'
        },
        {
            eventNames: ['resize'],
            filter: (node, name) => dimensions.test(name)
        },
        // media events
        {
            eventNames: ['timeupdate'],
            filter: (node, name) => node.isMediaNode() &&
                (name === 'currentTime' || name === 'played')
        },
        {
            eventNames: ['durationchange'],
            filter: (node, name) => node.isMediaNode() &&
                name === 'duration'
        },
        {
            eventNames: ['play', 'pause'],
            filter: (node, name) => node.isMediaNode() &&
                name === 'paused'
        },
        {
            eventNames: ['progress'],
            filter: (node, name) => node.isMediaNode() &&
                name === 'buffered'
        },
        {
            eventNames: ['loadedmetadata'],
            filter: (node, name) => node.isMediaNode() &&
                (name === 'buffered' || name === 'seekable')
        },
        {
            eventNames: ['volumechange'],
            filter: (node, name) => node.isMediaNode() &&
                name === 'volume'
        }
    ];

    class Head extends Node$1 {
        constructor(compiler, parent, scope, info) {
            super(compiler, parent, scope, info);
            this.children = mapChildren(compiler, parent, scope, info.children.filter(child => {
                return (child.type !== 'Text' || /\S/.test(child.data));
            }));
        }
        init(block, stripWhitespace, nextSibling) {
            this.initChildren(block, true, null);
        }
        build(block, parentNode, parentNodes) {
            this.var = 'document.head';
            this.children.forEach((child) => {
                child.build(block, 'document.head', null);
            });
        }
        ssr() {
            this.compiler.target.append('${(__result.head += `');
            this.children.forEach((child) => {
                child.ssr();
            });
            this.compiler.target.append('`, "")}');
        }
    }

    function isElseIf(node) {
        return (node && node.children.length === 1 && node.children[0].type === 'IfBlock');
    }
    function isElseBranch(branch) {
        return branch.block && !branch.condition;
    }
    class IfBlock extends Node$1 {
        constructor(compiler, parent, scope, info) {
            super(compiler, parent, scope, info);
            this.expression = new Expression(compiler, this, scope, info.expression);
            this.children = mapChildren(compiler, this, scope, info.children);
            this.else = info.else
                ? new ElseBlock(compiler, this, scope, info.else)
                : null;
        }
        init(block, stripWhitespace, nextSibling) {
            const { compiler } = this;
            this.cannotUseInnerHTML();
            const blocks = [];
            let dynamic = false;
            let hasIntros = false;
            let hasOutros = false;
            function attachBlocks(node) {
                node.var = block.getUniqueName(`if_block`);
                block.addDependencies(node.expression.dependencies);
                node.block = block.child({
                    comment: createDebuggingComment(node, compiler),
                    name: compiler.getUniqueName(`create_if_block`),
                });
                blocks.push(node.block);
                node.initChildren(node.block, stripWhitespace, nextSibling);
                if (node.block.dependencies.size > 0) {
                    dynamic = true;
                    block.addDependencies(node.block.dependencies);
                }
                if (node.block.hasIntros)
                    hasIntros = true;
                if (node.block.hasOutros)
                    hasOutros = true;
                if (isElseIf(node.else)) {
                    attachBlocks(node.else.children[0]);
                }
                else if (node.else) {
                    node.else.block = block.child({
                        comment: createDebuggingComment(node.else, compiler),
                        name: compiler.getUniqueName(`create_if_block`),
                    });
                    blocks.push(node.else.block);
                    node.else.initChildren(node.else.block, stripWhitespace, nextSibling);
                    if (node.else.block.dependencies.size > 0) {
                        dynamic = true;
                        block.addDependencies(node.else.block.dependencies);
                    }
                }
            }
            attachBlocks(this);
            if (compiler.options.nestedTransitions) {
                if (hasIntros)
                    block.addIntro();
                if (hasOutros)
                    block.addOutro();
            }
            blocks.forEach(block => {
                block.hasUpdateMethod = dynamic;
                block.hasIntroMethod = hasIntros;
                block.hasOutroMethod = hasOutros;
            });
            compiler.target.blocks.push(...blocks);
        }
        build(block, parentNode, parentNodes) {
            const name = this.var;
            const needsAnchor = this.next ? !this.next.isDomNode() : !parentNode || !this.parent.isDomNode();
            const anchor = needsAnchor
                ? block.getUniqueName(`${name}_anchor`)
                : (this.next && this.next.var) || 'null';
            const branches = this.getBranches(block, parentNode, parentNodes, this);
            const hasElse = isElseBranch(branches[branches.length - 1]);
            const if_name = hasElse ? '' : `if (${name}) `;
            const dynamic = branches[0].hasUpdateMethod; // can use [0] as proxy for all, since they necessarily have the same value
            const hasOutros = branches[0].hasOutroMethod;
            const vars = { name, anchor, if_name, hasElse };
            if (this.else) {
                if (hasOutros) {
                    this.buildCompoundWithOutros(block, parentNode, parentNodes, branches, dynamic, vars);
                    if (this.compiler.options.nestedTransitions) {
                        block.builders.outro.addLine(`${name}.o(#outrocallback);`);
                    }
                }
                else {
                    this.buildCompound(block, parentNode, parentNodes, branches, dynamic, vars);
                }
            }
            else {
                this.buildSimple(block, parentNode, parentNodes, branches[0], dynamic, vars);
                if (hasOutros && this.compiler.options.nestedTransitions) {
                    block.builders.outro.addLine(`if (${name}) ${name}.o(#outrocallback);`);
                }
            }
            block.builders.create.addLine(`${if_name}${name}.c();`);
            if (parentNodes) {
                block.builders.claim.addLine(`${if_name}${name}.l(${parentNodes});`);
            }
            if (needsAnchor) {
                block.addElement(anchor, `@createComment()`, parentNodes && `@createComment()`, parentNode);
            }
        }
        buildCompound(block, parentNode, parentNodes, branches, dynamic, { name, anchor, hasElse, if_name }) {
            const select_block_type = this.compiler.getUniqueName(`select_block_type`);
            const current_block_type = block.getUniqueName(`current_block_type`);
            const current_block_type_and = hasElse ? '' : `${current_block_type} && `;
            block.builders.init.addBlock(deindent `
			function ${select_block_type}(ctx) {
				${branches
            .map(({ condition, block }) => `${condition ? `if (${condition}) ` : ''}return ${block};`)
            .join('\n')}
			}
		`);
            block.builders.init.addBlock(deindent `
			var ${current_block_type} = ${select_block_type}(ctx);
			var ${name} = ${current_block_type_and}${current_block_type}(#component, ctx);
		`);
            const mountOrIntro = branches[0].hasIntroMethod ? 'i' : 'm';
            const initialMountNode = parentNode || '#target';
            const anchorNode = parentNode ? 'null' : 'anchor';
            block.builders.mount.addLine(`${if_name}${name}.${mountOrIntro}(${initialMountNode}, ${anchorNode});`);
            const updateMountNode = this.getUpdateMountNode(anchor);
            const changeBlock = deindent `
			${hasElse
            ? deindent `
					${name}.d(1);
				`
            : deindent `
					if (${name}) {
						${name}.d(1);
					}`}
			${name} = ${current_block_type_and}${current_block_type}(#component, ctx);
			${if_name}${name}.c();
			${if_name}${name}.${mountOrIntro}(${updateMountNode}, ${anchor});
		`;
            if (dynamic) {
                block.builders.update.addBlock(deindent `
				if (${current_block_type} === (${current_block_type} = ${select_block_type}(ctx)) && ${name}) {
					${name}.p(changed, ctx);
				} else {
					${changeBlock}
				}
			`);
            }
            else {
                block.builders.update.addBlock(deindent `
				if (${current_block_type} !== (${current_block_type} = ${select_block_type}(ctx))) {
					${changeBlock}
				}
			`);
            }
            block.builders.destroy.addLine(`${if_name}${name}.d(${parentNode ? '' : 'detach'});`);
        }
        // if any of the siblings have outros, we need to keep references to the blocks
        // (TODO does this only apply to bidi transitions?)
        buildCompoundWithOutros(block, parentNode, parentNodes, branches, dynamic, { name, anchor, hasElse }) {
            const select_block_type = block.getUniqueName(`select_block_type`);
            const current_block_type_index = block.getUniqueName(`current_block_type_index`);
            const previous_block_index = block.getUniqueName(`previous_block_index`);
            const if_block_creators = block.getUniqueName(`if_block_creators`);
            const if_blocks = block.getUniqueName(`if_blocks`);
            const if_current_block_type_index = hasElse
                ? ''
                : `if (~${current_block_type_index}) `;
            block.addVariable(current_block_type_index);
            block.addVariable(name);
            block.builders.init.addBlock(deindent `
			var ${if_block_creators} = [
				${branches.map(branch => branch.block).join(',\n')}
			];

			var ${if_blocks} = [];

			function ${select_block_type}(ctx) {
				${branches
            .map(({ condition, block }, i) => `${condition ? `if (${condition}) ` : ''}return ${block ? i : -1};`)
            .join('\n')}
			}
		`);
            if (hasElse) {
                block.builders.init.addBlock(deindent `
				${current_block_type_index} = ${select_block_type}(ctx);
				${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#component, ctx);
			`);
            }
            else {
                block.builders.init.addBlock(deindent `
				if (~(${current_block_type_index} = ${select_block_type}(ctx))) {
					${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#component, ctx);
				}
			`);
            }
            const mountOrIntro = branches[0].hasIntroMethod ? 'i' : 'm';
            const initialMountNode = parentNode || '#target';
            const anchorNode = parentNode ? 'null' : 'anchor';
            block.builders.mount.addLine(`${if_current_block_type_index}${if_blocks}[${current_block_type_index}].${mountOrIntro}(${initialMountNode}, ${anchorNode});`);
            const updateMountNode = this.getUpdateMountNode(anchor);
            const destroyOldBlock = deindent `
			@transitionManager.groupOutros();
			${name}.o(function() {
				${if_blocks}[${previous_block_index}].d(1);
				${if_blocks}[${previous_block_index}] = null;
			});
		`;
            const createNewBlock = deindent `
			${name} = ${if_blocks}[${current_block_type_index}];
			if (!${name}) {
				${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#component, ctx);
				${name}.c();
			}
			${name}.${mountOrIntro}(${updateMountNode}, ${anchor});
		`;
            const changeBlock = hasElse
                ? deindent `
				${destroyOldBlock}

				${createNewBlock}
			`
                : deindent `
				if (${name}) {
					${destroyOldBlock}
				}

				if (~${current_block_type_index}) {
					${createNewBlock}
				} else {
					${name} = null;
				}
			`;
            if (dynamic) {
                block.builders.update.addBlock(deindent `
				var ${previous_block_index} = ${current_block_type_index};
				${current_block_type_index} = ${select_block_type}(ctx);
				if (${current_block_type_index} === ${previous_block_index}) {
					${if_current_block_type_index}${if_blocks}[${current_block_type_index}].p(changed, ctx);
				} else {
					${changeBlock}
				}
			`);
            }
            else {
                block.builders.update.addBlock(deindent `
				var ${previous_block_index} = ${current_block_type_index};
				${current_block_type_index} = ${select_block_type}(ctx);
				if (${current_block_type_index} !== ${previous_block_index}) {
					${changeBlock}
				}
			`);
            }
            block.builders.destroy.addLine(deindent `
			${if_current_block_type_index}${if_blocks}[${current_block_type_index}].d(${parentNode ? '' : 'detach'});
		`);
        }
        buildSimple(block, parentNode, parentNodes, branch, dynamic, { name, anchor, if_name }) {
            block.builders.init.addBlock(deindent `
			var ${name} = (${branch.condition}) && ${branch.block}(#component, ctx);
		`);
            const mountOrIntro = branch.hasIntroMethod ? 'i' : 'm';
            const initialMountNode = parentNode || '#target';
            const anchorNode = parentNode ? 'null' : 'anchor';
            block.builders.mount.addLine(`if (${name}) ${name}.${mountOrIntro}(${initialMountNode}, ${anchorNode});`);
            const updateMountNode = this.getUpdateMountNode(anchor);
            const enter = dynamic
                ? (branch.hasIntroMethod || branch.hasOutroMethod)
                    ? deindent `
					if (${name}) {
						${name}.p(changed, ctx);
					} else {
						${name} = ${branch.block}(#component, ctx);
						if (${name}) ${name}.c();
					}

					${name}.i(${updateMountNode}, ${anchor});
				`
                    : deindent `
					if (${name}) {
						${name}.p(changed, ctx);
					} else {
						${name} = ${branch.block}(#component, ctx);
						${name}.c();
						${name}.m(${updateMountNode}, ${anchor});
					}
				`
                : (branch.hasIntroMethod || branch.hasOutroMethod)
                    ? deindent `
					if (!${name}) {
						${name} = ${branch.block}(#component, ctx);
						${name}.c();
					}
					${name}.i(${updateMountNode}, ${anchor});
				`
                    : deindent `
					if (!${name}) {
						${name} = ${branch.block}(#component, ctx);
						${name}.c();
						${name}.m(${updateMountNode}, ${anchor});
					}
				`;
            // no `p()` here — we don't want to update outroing nodes,
            // as that will typically result in glitching
            const exit = branch.hasOutroMethod
                ? deindent `
				@transitionManager.groupOutros();
				${name}.o(function() {
					${name}.d(1);
					${name} = null;
				});
			`
                : deindent `
				${name}.d(1);
				${name} = null;
			`;
            block.builders.update.addBlock(deindent `
			if (${branch.condition}) {
				${enter}
			} else if (${name}) {
				${exit}
			}
		`);
            block.builders.destroy.addLine(`${if_name}${name}.d(${parentNode ? '' : 'detach'});`);
        }
        getBranches(block, parentNode, parentNodes, node) {
            const branches = [
                {
                    condition: node.expression.snippet,
                    block: node.block.name,
                    hasUpdateMethod: node.block.hasUpdateMethod,
                    hasIntroMethod: node.block.hasIntroMethod,
                    hasOutroMethod: node.block.hasOutroMethod,
                },
            ];
            this.visitChildren(block, node);
            if (isElseIf(node.else)) {
                branches.push(...this.getBranches(block, parentNode, parentNodes, node.else.children[0]));
            }
            else {
                branches.push({
                    condition: null,
                    block: node.else ? node.else.block.name : null,
                    hasUpdateMethod: node.else ? node.else.block.hasUpdateMethod : false,
                    hasIntroMethod: node.else ? node.else.block.hasIntroMethod : false,
                    hasOutroMethod: node.else ? node.else.block.hasOutroMethod : false,
                });
                if (node.else) {
                    this.visitChildren(block, node.else);
                }
            }
            return branches;
        }
        ssr() {
            const { compiler } = this;
            const { snippet } = this.expression;
            compiler.target.append('${ ' + snippet + ' ? `');
            this.children.forEach((child) => {
                child.ssr();
            });
            compiler.target.append('` : `');
            if (this.else) {
                this.else.children.forEach((child) => {
                    child.ssr();
                });
            }
            compiler.target.append('` }');
        }
        visitChildren(block, node) {
            node.children.forEach((child) => {
                child.build(node.block, null, 'nodes');
            });
        }
    }

    class Tag extends Node$1 {
        constructor(compiler, parent, scope, info) {
            super(compiler, parent, scope, info);
            this.expression = new Expression(compiler, this, scope, info.expression);
            this.shouldCache = (info.expression.type !== 'Identifier' ||
                (this.expression.dependencies.size && scope.names.has(info.expression.name)));
        }
        init(block) {
            this.cannotUseInnerHTML();
            this.var = block.getUniqueName(this.type === 'MustacheTag' ? 'text' : 'raw');
            block.addDependencies(this.expression.dependencies);
        }
        renameThisMethod(block, update) {
            const { snippet, dependencies } = this.expression;
            const value = this.shouldCache && block.getUniqueName(`${this.var}_value`);
            const content = this.shouldCache ? value : snippet;
            if (this.shouldCache)
                block.addVariable(value, snippet);
            if (dependencies.size) {
                const changedCheck = ((block.hasOutros ? `#outroing || ` : '') +
                    [...dependencies].map((dependency) => `changed.${dependency}`).join(' || '));
                const updateCachedValue = `${value} !== (${value} = ${snippet})`;
                const condition = this.shouldCache ?
                    (dependencies.size ? `(${changedCheck}) && ${updateCachedValue}` : updateCachedValue) :
                    changedCheck;
                block.builders.update.addConditional(condition, update(content));
            }
            return { init: content };
        }
    }

    class MustacheTag extends Tag {
        build(block, parentNode, parentNodes) {
            const { init } = this.renameThisMethod(block, value => `${this.var}.data = ${value};`);
            block.addElement(this.var, `@createText(${init})`, parentNodes && `@claimText(${parentNodes}, ${init})`, parentNode);
        }
        remount(name) {
            return `@appendNode(${this.var}, ${name}._slotted.default);`;
        }
        ssr() {
            this.compiler.target.append(this.parent &&
                this.parent.type === 'Element' &&
                this.parent.name === 'style'
                ? '${' + this.expression.snippet + '}'
                : '${@escape(' + this.expression.snippet + ')}');
        }
    }

    class RawMustacheTag extends Tag {
        build(block, parentNode, parentNodes) {
            const name = this.var;
            const needsAnchorBefore = this.prev ? this.prev.type !== 'Element' : !parentNode;
            const needsAnchorAfter = this.next ? this.next.type !== 'Element' : !parentNode;
            const anchorBefore = needsAnchorBefore
                ? block.getUniqueName(`${name}_before`)
                : (this.prev && this.prev.var) || 'null';
            const anchorAfter = needsAnchorAfter
                ? block.getUniqueName(`${name}_after`)
                : (this.next && this.next.var) || 'null';
            let detach;
            let insert;
            let useInnerHTML = false;
            if (anchorBefore === 'null' && anchorAfter === 'null') {
                useInnerHTML = true;
                detach = `${parentNode}.innerHTML = '';`;
                insert = content => `${parentNode}.innerHTML = ${content};`;
            }
            else if (anchorBefore === 'null') {
                detach = `@detachBefore(${anchorAfter});`;
                insert = content => `${anchorAfter}.insertAdjacentHTML("beforebegin", ${content});`;
            }
            else if (anchorAfter === 'null') {
                detach = `@detachAfter(${anchorBefore});`;
                insert = content => `${anchorBefore}.insertAdjacentHTML("afterend", ${content});`;
            }
            else {
                detach = `@detachBetween(${anchorBefore}, ${anchorAfter});`;
                insert = content => `${anchorBefore}.insertAdjacentHTML("afterend", ${content});`;
            }
            const { init } = this.renameThisMethod(block, content => deindent `
				${!useInnerHTML && detach}
				${insert(content)}
			`);
            // we would have used comments here, but the `insertAdjacentHTML` api only
            // exists for `Element`s.
            if (needsAnchorBefore) {
                block.addElement(anchorBefore, `@createElement('noscript')`, parentNodes && `@createElement('noscript')`, parentNode, true);
            }
            function addAnchorAfter() {
                block.addElement(anchorAfter, `@createElement('noscript')`, parentNodes && `@createElement('noscript')`, parentNode);
            }
            if (needsAnchorAfter && anchorBefore === 'null') {
                // anchorAfter needs to be in the DOM before we
                // insert the HTML...
                addAnchorAfter();
            }
            block.builders.mount.addLine(insert(init));
            if (!parentNode) {
                block.builders.destroy.addConditional('detach', needsAnchorBefore
                    ? `${detach}\n@detachNode(${anchorBefore});`
                    : detach);
            }
            if (needsAnchorAfter && anchorBefore !== 'null') {
                // ...otherwise it should go afterwards
                addAnchorAfter();
            }
        }
        remount(name) {
            return `@appendNode(${this.var}, ${name}._slotted.default);`;
        }
        ssr() {
            this.compiler.target.append('${' + this.expression.snippet + '}');
        }
    }

    function sanitize(name) {
        return name.replace(/[^a-zA-Z]+/g, '_').replace(/^_/, '').replace(/_$/, '');
    }
    class Slot extends Element {
        init(block, stripWhitespace, nextSibling) {
            this.cannotUseInnerHTML();
            this.var = block.getUniqueName('slot');
            if (this.children.length) {
                this.initChildren(block, stripWhitespace, nextSibling);
            }
        }
        build(block, parentNode, parentNodes) {
            const { compiler } = this;
            const slotName = this.getStaticAttributeValue('name') || 'default';
            compiler.slots.add(slotName);
            const content_name = block.getUniqueName(`slot_content_${sanitize(slotName)}`);
            const prop = quotePropIfNecessary(slotName);
            block.addVariable(content_name, `#component._slotted${prop}`);
            const needsAnchorBefore = this.prev ? this.prev.type !== 'Element' : !parentNode;
            const needsAnchorAfter = this.next ? this.next.type !== 'Element' : !parentNode;
            const anchorBefore = needsAnchorBefore
                ? block.getUniqueName(`${content_name}_before`)
                : (this.prev && this.prev.var) || 'null';
            const anchorAfter = needsAnchorAfter
                ? block.getUniqueName(`${content_name}_after`)
                : (this.next && this.next.var) || 'null';
            if (needsAnchorBefore)
                block.addVariable(anchorBefore);
            if (needsAnchorAfter)
                block.addVariable(anchorAfter);
            let mountBefore = block.builders.mount.toString();
            let destroyBefore = block.builders.destroy.toString();
            block.builders.create.pushCondition(`!${content_name}`);
            block.builders.hydrate.pushCondition(`!${content_name}`);
            block.builders.mount.pushCondition(`!${content_name}`);
            block.builders.update.pushCondition(`!${content_name}`);
            block.builders.destroy.pushCondition(`!${content_name}`);
            this.children.forEach((child) => {
                child.build(block, parentNode, parentNodes);
            });
            block.builders.create.popCondition();
            block.builders.hydrate.popCondition();
            block.builders.mount.popCondition();
            block.builders.update.popCondition();
            block.builders.destroy.popCondition();
            const mountLeadin = block.builders.mount.toString() !== mountBefore
                ? `else`
                : `if (${content_name})`;
            if (parentNode) {
                block.builders.mount.addBlock(deindent `
				${mountLeadin} {
					${needsAnchorBefore && `@appendNode(${anchorBefore} || (${anchorBefore} = @createComment()), ${parentNode});`}
					@appendNode(${content_name}, ${parentNode});
					${needsAnchorAfter && `@appendNode(${anchorAfter} || (${anchorAfter} = @createComment()), ${parentNode});`}
				}
			`);
            }
            else {
                block.builders.mount.addBlock(deindent `
				${mountLeadin} {
					${needsAnchorBefore && `@insertNode(${anchorBefore} || (${anchorBefore} = @createComment()), #target, anchor);`}
					@insertNode(${content_name}, #target, anchor);
					${needsAnchorAfter && `@insertNode(${anchorAfter} || (${anchorAfter} = @createComment()), #target, anchor);`}
				}
			`);
            }
            // if the slot is unmounted, move nodes back into the document fragment,
            // so that it can be reinserted later
            // TODO so that this can work with public API, component._slotted should
            // be all fragments, derived from options.slots. Not === options.slots
            const unmountLeadin = block.builders.destroy.toString() !== destroyBefore
                ? `else`
                : `if (${content_name})`;
            if (anchorBefore === 'null' && anchorAfter === 'null') {
                block.builders.destroy.addBlock(deindent `
				${unmountLeadin} {
					@reinsertChildren(${parentNode}, ${content_name});
				}
			`);
            }
            else if (anchorBefore === 'null') {
                block.builders.destroy.addBlock(deindent `
				${unmountLeadin} {
					@reinsertBefore(${anchorAfter}, ${content_name});
				}
			`);
            }
            else if (anchorAfter === 'null') {
                block.builders.destroy.addBlock(deindent `
				${unmountLeadin} {
					@reinsertAfter(${anchorBefore}, ${content_name});
				}
			`);
            }
            else {
                block.builders.destroy.addBlock(deindent `
				${unmountLeadin} {
					@reinsertBetween(${anchorBefore}, ${anchorAfter}, ${content_name});
					@detachNode(${anchorBefore});
					@detachNode(${anchorAfter});
				}
			`);
            }
        }
        getStaticAttributeValue(name) {
            const attribute = this.attributes.find(attr => attr.name.toLowerCase() === name);
            if (!attribute)
                return null;
            if (attribute.isTrue)
                return true;
            if (attribute.chunks.length === 0)
                return '';
            if (attribute.chunks.length === 1 && attribute.chunks[0].type === 'Text') {
                return attribute.chunks[0].data;
            }
            return null;
        }
        ssr() {
            const name = this.attributes.find(attribute => attribute.name === 'name');
            const slotName = name && name.chunks[0].data || 'default';
            const prop = quotePropIfNecessary(slotName);
            this.compiler.target.append(`\${options && options.slotted && options.slotted${prop} ? options.slotted${prop}() : \``);
            this.children.forEach((child) => {
                child.ssr();
            });
            this.compiler.target.append(`\`}`);
        }
    }

    class Title extends Node$1 {
        constructor(compiler, parent, scope, info) {
            super(compiler, parent, scope, info);
            this.children = mapChildren(compiler, parent, scope, info.children);
            this.shouldCache = info.children.length === 1
                ? (info.children[0].type !== 'Identifier' ||
                    scope.names.has(info.children[0].name))
                : true;
        }
        build(block, parentNode, parentNodes) {
            const isDynamic = !!this.children.find(node => node.type !== 'Text');
            if (isDynamic) {
                let value;
                const allDependencies = new Set();
                // TODO some of this code is repeated in Tag.ts — would be good to
                // DRY it out if that's possible without introducing crazy indirection
                if (this.children.length === 1) {
                    // single {{tag}} — may be a non-string
                    const { expression } = this.children[0];
                    const { dependencies, snippet } = this.children[0].expression;
                    value = snippet;
                    dependencies.forEach(d => {
                        allDependencies.add(d);
                    });
                }
                else {
                    // '{foo} {bar}' — treat as string concatenation
                    value =
                        (this.children[0].type === 'Text' ? '' : `"" + `) +
                            this.children
                                .map((chunk) => {
                                if (chunk.type === 'Text') {
                                    return stringify(chunk.data);
                                }
                                else {
                                    const { dependencies, snippet } = chunk.expression;
                                    dependencies.forEach(d => {
                                        allDependencies.add(d);
                                    });
                                    return chunk.expression.getPrecedence() <= 13 ? `(${snippet})` : snippet;
                                }
                            })
                                .join(' + ');
                }
                const last = this.shouldCache && block.getUniqueName(`title_value`);
                if (this.shouldCache)
                    block.addVariable(last);
                let updater;
                const init = this.shouldCache ? `${last} = ${value}` : value;
                block.builders.init.addLine(`document.title = ${init};`);
                updater = `document.title = ${this.shouldCache ? last : value};`;
                if (allDependencies.size) {
                    const dependencies = Array.from(allDependencies);
                    const changedCheck = ((block.hasOutros ? `#outroing || ` : '') +
                        dependencies.map(dependency => `changed.${dependency}`).join(' || '));
                    const updateCachedValue = `${last} !== (${last} = ${value})`;
                    const condition = this.shouldCache ?
                        (dependencies.length ? `(${changedCheck}) && ${updateCachedValue}` : updateCachedValue) :
                        changedCheck;
                    block.builders.update.addConditional(condition, updater);
                }
            }
            else {
                const value = stringify(this.children[0].data);
                block.builders.hydrate.addLine(`document.title = ${value};`);
            }
        }
        ssr() {
            this.compiler.target.append(`<title>`);
            this.children.forEach((child) => {
                child.ssr();
            });
            this.compiler.target.append(`</title>`);
        }
    }

    const associatedEvents = {
        innerWidth: 'resize',
        innerHeight: 'resize',
        outerWidth: 'resize',
        outerHeight: 'resize',
        scrollX: 'scroll',
        scrollY: 'scroll',
    };
    const properties = {
        scrollX: 'pageXOffset',
        scrollY: 'pageYOffset'
    };
    const readonly = new Set([
        'innerWidth',
        'innerHeight',
        'outerWidth',
        'outerHeight',
        'online',
    ]);
    class Window extends Node$1 {
        constructor(compiler, parent, scope, info) {
            super(compiler, parent, scope, info);
            this.handlers = [];
            this.bindings = [];
            info.attributes.forEach(node => {
                if (node.type === 'EventHandler') {
                    this.handlers.push(new EventHandler(compiler, this, scope, node));
                }
                else if (node.type === 'Binding') {
                    this.bindings.push(new Binding(compiler, this, scope, node));
                }
            });
        }
        build(block, parentNode, parentNodes) {
            const { compiler } = this;
            const events = {};
            const bindings = {};
            this.handlers.forEach(handler => {
                // TODO verify that it's a valid callee (i.e. built-in or declared method)
                compiler.addSourcemapLocations(handler.expression);
                const isCustomEvent = compiler.events.has(handler.name);
                let usesState = handler.dependencies.size > 0;
                handler.render(compiler, block, false); // TODO hoist?
                const handlerName = block.getUniqueName(`onwindow${handler.name}`);
                const handlerBody = deindent `
				${usesState && `var ctx = #component.get();`}
				${handler.snippet};
			`;
                if (isCustomEvent) {
                    // TODO dry this out
                    block.addVariable(handlerName);
                    block.builders.hydrate.addBlock(deindent `
					${handlerName} = %events-${handler.name}.call(#component, window, function(event) {
						${handlerBody}
					});
				`);
                    block.builders.destroy.addLine(deindent `
					${handlerName}.destroy();
				`);
                }
                else {
                    block.builders.init.addBlock(deindent `
					function ${handlerName}(event) {
						${handlerBody}
					}
					window.addEventListener("${handler.name}", ${handlerName});
				`);
                    block.builders.destroy.addBlock(deindent `
					window.removeEventListener("${handler.name}", ${handlerName});
				`);
                }
            });
            this.bindings.forEach(binding => {
                // in dev mode, throw if read-only values are written to
                if (readonly.has(binding.name)) {
                    compiler.target.readonly.add(binding.value.node.name);
                }
                bindings[binding.name] = binding.value.node.name;
                // bind:online is a special case, we need to listen for two separate events
                if (binding.name === 'online')
                    return;
                const associatedEvent = associatedEvents[binding.name];
                const property = properties[binding.name] || binding.name;
                if (!events[associatedEvent])
                    events[associatedEvent] = [];
                events[associatedEvent].push(`${binding.value.node.name}: this.${property}`);
                // add initial value
                compiler.target.metaBindings.push(`this._state.${binding.value.node.name} = window.${property};`);
            });
            const lock = block.getUniqueName(`window_updating`);
            const clear = block.getUniqueName(`clear_window_updating`);
            const timeout = block.getUniqueName(`window_updating_timeout`);
            Object.keys(events).forEach(event => {
                const handlerName = block.getUniqueName(`onwindow${event}`);
                const props = events[event].join(',\n');
                if (event === 'scroll') {
                    // TODO other bidirectional bindings...
                    block.addVariable(lock, 'false');
                    block.addVariable(clear, `function() { ${lock} = false; }`);
                    block.addVariable(timeout);
                }
                const handlerBody = deindent `
				${event === 'scroll' && deindent `
					if (${lock}) return;
					${lock} = true;
				`}
				${compiler.options.dev && `component._updatingReadonlyProperty = true;`}

				#component.set({
					${props}
				});

				${compiler.options.dev && `component._updatingReadonlyProperty = false;`}
				${event === 'scroll' && `${lock} = false;`}
			`;
                block.builders.init.addBlock(deindent `
				function ${handlerName}(event) {
					${handlerBody}
				}
				window.addEventListener("${event}", ${handlerName});
			`);
                block.builders.destroy.addBlock(deindent `
				window.removeEventListener("${event}", ${handlerName});
			`);
            });
            // special case... might need to abstract this out if we add more special cases
            if (bindings.scrollX || bindings.scrollY) {
                block.builders.init.addBlock(deindent `
				#component.on("state", ({ changed, current }) => {
					if (${[bindings.scrollX, bindings.scrollY].map(binding => binding && `changed["${binding}"]`).filter(Boolean).join(' || ')}) {
						${lock} = true;
						clearTimeout(${timeout});
						window.scrollTo(${bindings.scrollX ? `current["${bindings.scrollX}"]` : `window.pageXOffset`}, ${bindings.scrollY ? `current["${bindings.scrollY}"]` : `window.pageYOffset`});
						${timeout} = setTimeout(${clear}, 100);
					}
				});
			`);
            }
            // another special case. (I'm starting to think these are all special cases.)
            if (bindings.online) {
                const handlerName = block.getUniqueName(`onlinestatuschanged`);
                block.builders.init.addBlock(deindent `
				function ${handlerName}(event) {
					#component.set({ ${bindings.online}: navigator.onLine });
				}
				window.addEventListener("online", ${handlerName});
				window.addEventListener("offline", ${handlerName});
			`);
                // add initial value
                compiler.target.metaBindings.push(`this._state.${bindings.online} = navigator.onLine;`);
                block.builders.destroy.addBlock(deindent `
				window.removeEventListener("online", ${handlerName});
				window.removeEventListener("offline", ${handlerName});
			`);
            }
        }
        ssr() {
            // noop
        }
    }

    function getConstructor(type) {
        switch (type) {
            case 'AwaitBlock': return AwaitBlock;
            case 'Comment': return Comment$2;
            case 'Component': return Component;
            case 'EachBlock': return EachBlock;
            case 'Element': return Element;
            case 'Head': return Head;
            case 'IfBlock': return IfBlock;
            case 'MustacheTag': return MustacheTag;
            case 'RawMustacheTag': return RawMustacheTag;
            case 'Slot': return Slot;
            case 'Text': return Text;
            case 'Title': return Title;
            case 'Window': return Window;
            default: throw new Error(`Not implemented: ${type}`);
        }
    }
    function mapChildren(compiler, parent, scope, children) {
        let last = null;
        return children.map(child => {
            const constructor = getConstructor(child.type);
            const node = new constructor(compiler, parent, scope, child);
            if (last)
                last.next = node;
            node.prev = last;
            last = node;
            return node;
        });
    }

    class Block$2 {
        constructor(options) {
            this.parent = options.parent;
            this.compiler = options.compiler;
            this.name = options.name;
            this.comment = options.comment;
            // for keyed each blocks
            this.key = options.key;
            this.first = null;
            this.dependencies = new Set();
            this.bindings = options.bindings;
            this.builders = {
                init: new CodeBuilder(),
                create: new CodeBuilder(),
                claim: new CodeBuilder(),
                hydrate: new CodeBuilder(),
                mount: new CodeBuilder(),
                measure: new CodeBuilder(),
                fix: new CodeBuilder(),
                animate: new CodeBuilder(),
                intro: new CodeBuilder(),
                update: new CodeBuilder(),
                outro: new CodeBuilder(),
                destroy: new CodeBuilder(),
            };
            this.hasAnimation = false;
            this.hasIntroMethod = false; // a block could have an intro method but not intro transitions, e.g. if a sibling block has intros
            this.hasOutroMethod = false;
            this.outros = 0;
            this.getUniqueName = this.compiler.getUniqueNameMaker();
            this.variables = new Map();
            this.aliases = new Map()
                .set('component', this.getUniqueName('component'))
                .set('ctx', this.getUniqueName('ctx'));
            if (this.key)
                this.aliases.set('key', this.getUniqueName('key'));
            this.hasUpdateMethod = false; // determined later
        }
        addDependencies(dependencies) {
            dependencies.forEach(dependency => {
                this.dependencies.add(dependency);
            });
        }
        addElement(name, renderStatement, claimStatement, parentNode, noDetach) {
            this.addVariable(name);
            this.builders.create.addLine(`${name} = ${renderStatement};`);
            this.builders.claim.addLine(`${name} = ${claimStatement || renderStatement};`);
            if (parentNode) {
                this.builders.mount.addLine(`@appendNode(${name}, ${parentNode});`);
                if (parentNode === 'document.head')
                    this.builders.destroy.addLine(`@detachNode(${name});`);
            }
            else {
                this.builders.mount.addLine(`@insertNode(${name}, #target, anchor);`);
                if (!noDetach)
                    this.builders.destroy.addConditional('detach', `@detachNode(${name});`);
            }
        }
        addIntro() {
            this.hasIntros = this.hasIntroMethod = this.compiler.target.hasIntroTransitions = true;
        }
        addOutro() {
            this.hasOutros = this.hasOutroMethod = this.compiler.target.hasOutroTransitions = true;
            this.outros += 1;
        }
        addAnimation() {
            this.hasAnimation = true;
        }
        addVariable(name, init) {
            if (this.variables.has(name) && this.variables.get(name) !== init) {
                throw new Error(`Variable '${name}' already initialised with a different value`);
            }
            this.variables.set(name, init);
        }
        alias(name) {
            if (!this.aliases.has(name)) {
                this.aliases.set(name, this.getUniqueName(name));
            }
            return this.aliases.get(name);
        }
        child(options) {
            return new Block$2(Object.assign({}, this, { key: null }, options, { parent: this }));
        }
        toString() {
            const { dev } = this.compiler.options;
            let introing;
            const hasIntros = !this.builders.intro.isEmpty();
            if (hasIntros) {
                introing = this.getUniqueName('introing');
                this.addVariable(introing);
            }
            let outroing;
            const hasOutros = !this.builders.outro.isEmpty();
            if (hasOutros) {
                outroing = this.alias('outroing');
                this.addVariable(outroing);
            }
            if (this.autofocus) {
                this.builders.mount.addLine(`${this.autofocus}.focus();`);
            }
            const properties = new CodeBuilder();
            let localKey;
            if (this.key) {
                localKey = this.getUniqueName('key');
                properties.addBlock(`key: ${localKey},`);
            }
            if (this.first) {
                properties.addBlock(`first: null,`);
                this.builders.hydrate.addLine(`this.first = ${this.first};`);
            }
            if (this.builders.create.isEmpty() && this.builders.hydrate.isEmpty()) {
                properties.addBlock(`c: @noop,`);
            }
            else {
                const hydrate = !this.builders.hydrate.isEmpty() && (this.compiler.options.hydratable
                    ? `this.h()`
                    : this.builders.hydrate);
                properties.addBlock(deindent `
				${dev ? 'c: function create' : 'c'}() {
					${this.builders.create}
					${hydrate}
				},
			`);
            }
            if (this.compiler.options.hydratable) {
                if (this.builders.claim.isEmpty() && this.builders.hydrate.isEmpty()) {
                    properties.addBlock(`l: @noop,`);
                }
                else {
                    properties.addBlock(deindent `
					${dev ? 'l: function claim' : 'l'}(nodes) {
						${this.builders.claim}
						${!this.builders.hydrate.isEmpty() && `this.h();`}
					},
				`);
                }
            }
            if (this.compiler.options.hydratable && !this.builders.hydrate.isEmpty()) {
                properties.addBlock(deindent `
				${dev ? 'h: function hydrate' : 'h'}() {
					${this.builders.hydrate}
				},
			`);
            }
            if (this.builders.mount.isEmpty()) {
                properties.addBlock(`m: @noop,`);
            }
            else {
                properties.addBlock(deindent `
				${dev ? 'm: function mount' : 'm'}(#target, anchor) {
					${this.builders.mount}
				},
			`);
            }
            if (this.hasUpdateMethod || this.maintainContext) {
                if (this.builders.update.isEmpty() && !this.maintainContext) {
                    properties.addBlock(`p: @noop,`);
                }
                else {
                    properties.addBlock(deindent `
					${dev ? 'p: function update' : 'p'}(changed, ${this.maintainContext ? '_ctx' : 'ctx'}) {
						${this.maintainContext && `ctx = _ctx;`}
						${this.builders.update}
					},
				`);
                }
            }
            if (this.hasAnimation) {
                properties.addBlock(deindent `
				${dev ? `r: function measure` : `r`}() {
					${this.builders.measure}
				},

				${dev ? `f: function fix` : `f`}() {
					${this.builders.fix}
				},

				${dev ? `a: function animate` : `a`}() {
					${this.builders.animate}
				},
			`);
            }
            if (this.hasIntroMethod || this.hasOutroMethod) {
                if (hasIntros) {
                    properties.addBlock(deindent `
					${dev ? 'i: function intro' : 'i'}(#target, anchor) {
						if (${introing}) return;
						${introing} = true;
						${hasOutros && `${outroing} = false;`}

						${this.builders.intro}

						this.m(#target, anchor);
					},
				`);
                }
                else {
                    if (this.builders.mount.isEmpty()) {
                        properties.addBlock(`i: @noop,`);
                    }
                    else {
                        properties.addBlock(deindent `
						${dev ? 'i: function intro' : 'i'}(#target, anchor) {
							this.m(#target, anchor);
						},
					`);
                    }
                }
                if (hasOutros) {
                    properties.addBlock(deindent `
					${dev ? 'o: function outro' : 'o'}(#outrocallback) {
						if (${outroing}) return;
						${outroing} = true;
						${hasIntros && `${introing} = false;`}

						${this.outros > 1 && `#outrocallback = @callAfter(#outrocallback, ${this.outros});`}

						${this.builders.outro}
					},
				`);
                }
                else {
                    properties.addBlock(deindent `
					o: @run,
				`);
                }
            }
            if (this.builders.destroy.isEmpty()) {
                properties.addBlock(`d: @noop`);
            }
            else {
                properties.addBlock(deindent `
				${dev ? 'd: function destroy' : 'd'}(detach) {
					${this.builders.destroy}
				}
			`);
            }
            return deindent `
			${this.comment && `// ${escape(this.comment)}`}
			function ${this.name}(#component${this.key ? `, ${localKey}` : ''}, ctx) {
				${this.variables.size > 0 &&
            `var ${Array.from(this.variables.keys())
                .map(key => {
                const init = this.variables.get(key);
                return init !== undefined ? `${key} = ${init}` : key;
            })
                .join(', ')};`}

				${!this.builders.init.isEmpty() && this.builders.init}

				return {
					${properties}
				};
			}
		`.replace(/(#+)(\w*)/g, (match, sigil, name) => {
                return sigil === '#' ? this.alias(name) : sigil.slice(1) + name;
            });
        }
    }

    class TemplateScope {
        constructor(parent) {
            this.names = new Set(parent ? parent.names : []);
            this.dependenciesForName = new Map(parent ? parent.dependenciesForName : []);
        }
        add(name, dependencies) {
            this.names.add(name);
            this.dependenciesForName.set(name, dependencies);
            return this;
        }
        child() {
            return new TemplateScope(this);
        }
    }

    class Fragment extends Node$1 {
        constructor(compiler, info) {
            const scope = new TemplateScope();
            super(compiler, null, scope, info);
            this.scope = scope;
            this.children = mapChildren(compiler, this, scope, info.children);
        }
        init() {
            this.block = new Block$2({
                compiler: this.compiler,
                name: '@create_main_fragment',
                key: null,
                bindings: new Map(),
                dependencies: new Set(),
            });
            this.compiler.target.blocks.push(this.block);
            this.initChildren(this.block, true, null);
            this.block.hasUpdateMethod = true;
        }
        build() {
            this.init();
            this.children.forEach(child => {
                child.build(this.block, null, 'nodes');
            });
        }
    }

    // this file is auto-generated, do not edit it
    const shared = {
        "wrapAnimation": "function wrapAnimation(node, from, fn, params) {\n\tif (!from) return;\n\n\tconst to = node.getBoundingClientRect();\n\tif (from.left === to.left && from.right === to.right && from.top === to.top && from.bottom === to.bottom) return;\n\n\tconst info = fn(node, { from, to }, params);\n\n\tconst duration = 'duration' in info ? info.duration : 300;\n\tconst delay = 'delay' in info ? info.delay : 0;\n\tconst ease = info.easing || linear;\n\tconst start = window.performance.now() + delay;\n\tconst end = start + duration;\n\n\tconst program = {\n\t\ta: 0,\n\t\tt: 0,\n\t\tb: 1,\n\t\tdelta: 1,\n\t\tduration,\n\t\tstart,\n\t\tend\n\t};\n\n\tconst cssText = node.style.cssText;\n\n\tconst animation = {\n\t\tpending: delay ? program : null,\n\t\tprogram: delay ? null : program,\n\t\trunning: true,\n\n\t\tstart() {\n\t\t\tif (info.css) {\n\t\t\t\tif (delay) node.style.cssText = cssText;\n\n\t\t\t\tconst rule = generateRule(program, ease, info.css);\n\t\t\t\tprogram.name = `__svelte_${hash(rule)}`;\n\n\t\t\t\ttransitionManager.addRule(rule, program.name);\n\n\t\t\t\tnode.style.animation = (node.style.animation || '')\n\t\t\t\t\t.split(', ')\n\t\t\t\t\t.filter(anim => anim && (program.delta < 0 || !/__svelte/.test(anim)))\n\t\t\t\t\t.concat(`${program.name} ${program.duration}ms linear 1 forwards`)\n\t\t\t\t\t.join(', ');\n\t\t\t}\n\n\t\t\tanimation.program = program;\n\t\t\tanimation.pending = null;\n\t\t},\n\n\t\tupdate: now => {\n\t\t\tconst p = now - program.start;\n\t\t\tconst t = program.a + program.delta * ease(p / program.duration);\n\t\t\tif (info.tick) info.tick(t, 1 - t);\n\t\t},\n\n\t\tdone() {\n\t\t\tif (info.tick) info.tick(1, 0);\n\t\t\tanimation.stop();\n\t\t},\n\n\t\tstop() {\n\t\t\tif (info.css) transitionManager.deleteRule(node, program.name);\n\t\t\tanimation.running = false;\n\t\t}\n\t};\n\n\ttransitionManager.add(animation);\n\n\tif (info.tick) info.tick(0, 1);\n\n\tif (delay) {\n\t\tif (info.css) node.style.cssText += info.css(0, 1);\n\t} else {\n\t\tanimation.start();\n\t}\n\n\treturn animation;\n}",
        "fixPosition": "function fixPosition(node) {\n\tconst style = getComputedStyle(node);\n\n\tif (style.position !== 'absolute' && style.position !== 'fixed') {\n\t\tconst { width, height } = style;\n\t\tconst a = node.getBoundingClientRect();\n\t\tnode.style.position = 'absolute';\n\t\tnode.style.width = width;\n\t\tnode.style.height = height;\n\t\tconst b = node.getBoundingClientRect();\n\n\t\tif (a.left !== b.left || a.top !== b.top) {\n\t\t\tconst style = getComputedStyle(node);\n\t\t\tconst transform = style.transform === 'none' ? '' : style.transform;\n\n\t\t\tnode.style.transform = `${transform} translate(${a.left - b.left}px, ${a.top - b.top}px)`;\n\t\t}\n\t}\n}",
        "handlePromise": "function handlePromise(promise, info) {\n\tvar token = info.token = {};\n\n\tfunction update(type, index, key, value) {\n\t\tif (info.token !== token) return;\n\n\t\tinfo.resolved = key && { [key]: value };\n\n\t\tconst child_ctx = assign(assign({}, info.ctx), info.resolved);\n\t\tconst block = type && (info.current = type)(info.component, child_ctx);\n\n\t\tif (info.block) {\n\t\t\tif (info.blocks) {\n\t\t\t\tinfo.blocks.forEach((block, i) => {\n\t\t\t\t\tif (i !== index && block) {\n\t\t\t\t\t\ttransitionManager.groupOutros();\n\t\t\t\t\t\tblock.o(() => {\n\t\t\t\t\t\t\tblock.d(1);\n\t\t\t\t\t\t\tinfo.blocks[i] = null;\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tinfo.block.d(1);\n\t\t\t}\n\n\t\t\tblock.c();\n\t\t\tblock[block.i ? 'i' : 'm'](info.mount(), info.anchor);\n\n\t\t\tinfo.component.root.set({}); // flush any handlers that were created\n\t\t}\n\n\t\tinfo.block = block;\n\t\tif (info.blocks) info.blocks[index] = block;\n\t}\n\n\tif (isPromise(promise)) {\n\t\tpromise.then(value => {\n\t\t\tupdate(info.then, 1, info.value, value);\n\t\t}, error => {\n\t\t\tupdate(info.catch, 2, info.error, error);\n\t\t});\n\n\t\t// if we previously had a then/catch block, destroy it\n\t\tif (info.current !== info.pending) {\n\t\t\tupdate(info.pending, 0);\n\t\t\treturn true;\n\t\t}\n\t} else {\n\t\tif (info.current !== info.then) {\n\t\t\tupdate(info.then, 1, info.value, promise);\n\t\t\treturn true;\n\t\t}\n\n\t\tinfo.resolved = { [info.value]: promise };\n\t}\n}",
        "appendNode": "function appendNode(node, target) {\n\ttarget.appendChild(node);\n}",
        "insertNode": "function insertNode(node, target, anchor) {\n\ttarget.insertBefore(node, anchor);\n}",
        "detachNode": "function detachNode(node) {\n\tnode.parentNode.removeChild(node);\n}",
        "detachBetween": "function detachBetween(before, after) {\n\twhile (before.nextSibling && before.nextSibling !== after) {\n\t\tbefore.parentNode.removeChild(before.nextSibling);\n\t}\n}",
        "detachBefore": "function detachBefore(after) {\n\twhile (after.previousSibling) {\n\t\tafter.parentNode.removeChild(after.previousSibling);\n\t}\n}",
        "detachAfter": "function detachAfter(before) {\n\twhile (before.nextSibling) {\n\t\tbefore.parentNode.removeChild(before.nextSibling);\n\t}\n}",
        "reinsertBetween": "function reinsertBetween(before, after, target) {\n\twhile (before.nextSibling && before.nextSibling !== after) {\n\t\ttarget.appendChild(before.parentNode.removeChild(before.nextSibling));\n\t}\n}",
        "reinsertChildren": "function reinsertChildren(parent, target) {\n\twhile (parent.firstChild) target.appendChild(parent.firstChild);\n}",
        "reinsertAfter": "function reinsertAfter(before, target) {\n\twhile (before.nextSibling) target.appendChild(before.nextSibling);\n}",
        "reinsertBefore": "function reinsertBefore(after, target) {\n\tvar parent = after.parentNode;\n\twhile (parent.firstChild !== after) target.appendChild(parent.firstChild);\n}",
        "destroyEach": "function destroyEach(iterations, detach) {\n\tfor (var i = 0; i < iterations.length; i += 1) {\n\t\tif (iterations[i]) iterations[i].d(detach);\n\t}\n}",
        "createFragment": "function createFragment() {\n\treturn document.createDocumentFragment();\n}",
        "createElement": "function createElement(name) {\n\treturn document.createElement(name);\n}",
        "createSvgElement": "function createSvgElement(name) {\n\treturn document.createElementNS('http://www.w3.org/2000/svg', name);\n}",
        "createText": "function createText(data) {\n\treturn document.createTextNode(data);\n}",
        "createComment": "function createComment() {\n\treturn document.createComment('');\n}",
        "addListener": "function addListener(node, event, handler) {\n\tnode.addEventListener(event, handler, false);\n}",
        "removeListener": "function removeListener(node, event, handler) {\n\tnode.removeEventListener(event, handler, false);\n}",
        "setAttribute": "function setAttribute(node, attribute, value) {\n\tnode.setAttribute(attribute, value);\n}",
        "setAttributes": "function setAttributes(node, attributes) {\n\tfor (var key in attributes) {\n\t\tif (key in node) {\n\t\t\tnode[key] = attributes[key];\n\t\t} else {\n\t\t\tif (attributes[key] === undefined) removeAttribute(node, key);\n\t\t\telse setAttribute(node, key, attributes[key]);\n\t\t}\n\t}\n}",
        "removeAttribute": "function removeAttribute(node, attribute) {\n\tnode.removeAttribute(attribute);\n}",
        "setXlinkAttribute": "function setXlinkAttribute(node, attribute, value) {\n\tnode.setAttributeNS('http://www.w3.org/1999/xlink', attribute, value);\n}",
        "getBindingGroupValue": "function getBindingGroupValue(group) {\n\tvar value = [];\n\tfor (var i = 0; i < group.length; i += 1) {\n\t\tif (group[i].checked) value.push(group[i].__value);\n\t}\n\treturn value;\n}",
        "toNumber": "function toNumber(value) {\n\treturn value === '' ? undefined : +value;\n}",
        "timeRangesToArray": "function timeRangesToArray(ranges) {\n\tvar array = [];\n\tfor (var i = 0; i < ranges.length; i += 1) {\n\t\tarray.push({ start: ranges.start(i), end: ranges.end(i) });\n\t}\n\treturn array;\n}",
        "children": "function children (element) {\n\treturn Array.from(element.childNodes);\n}",
        "claimElement": "function claimElement (nodes, name, attributes, svg) {\n\tfor (var i = 0; i < nodes.length; i += 1) {\n\t\tvar node = nodes[i];\n\t\tif (node.nodeName === name) {\n\t\t\tfor (var j = 0; j < node.attributes.length; j += 1) {\n\t\t\t\tvar attribute = node.attributes[j];\n\t\t\t\tif (!attributes[attribute.name]) node.removeAttribute(attribute.name);\n\t\t\t}\n\t\t\treturn nodes.splice(i, 1)[0]; // TODO strip unwanted attributes\n\t\t}\n\t}\n\n\treturn svg ? createSvgElement(name) : createElement(name);\n}",
        "claimText": "function claimText (nodes, data) {\n\tfor (var i = 0; i < nodes.length; i += 1) {\n\t\tvar node = nodes[i];\n\t\tif (node.nodeType === 3) {\n\t\t\tnode.data = data;\n\t\t\treturn nodes.splice(i, 1)[0];\n\t\t}\n\t}\n\n\treturn createText(data);\n}",
        "setInputType": "function setInputType(input, type) {\n\ttry {\n\t\tinput.type = type;\n\t} catch (e) {}\n}",
        "setStyle": "function setStyle(node, key, value) {\n\tnode.style.setProperty(key, value);\n}",
        "selectOption": "function selectOption(select, value) {\n\tfor (var i = 0; i < select.options.length; i += 1) {\n\t\tvar option = select.options[i];\n\n\t\tif (option.__value === value) {\n\t\t\toption.selected = true;\n\t\t\treturn;\n\t\t}\n\t}\n}",
        "selectOptions": "function selectOptions(select, value) {\n\tfor (var i = 0; i < select.options.length; i += 1) {\n\t\tvar option = select.options[i];\n\t\toption.selected = ~value.indexOf(option.__value);\n\t}\n}",
        "selectValue": "function selectValue(select) {\n\tvar selectedOption = select.querySelector(':checked') || select.options[0];\n\treturn selectedOption && selectedOption.__value;\n}",
        "selectMultipleValue": "function selectMultipleValue(select) {\n\treturn [].map.call(select.querySelectorAll(':checked'), function(option) {\n\t\treturn option.__value;\n\t});\n}",
        "addResizeListener": "function addResizeListener(element, fn) {\n\tif (getComputedStyle(element).position === 'static') {\n\t\telement.style.position = 'relative';\n\t}\n\n\tconst object = document.createElement('object');\n\tobject.setAttribute('style', 'display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; pointer-events: none; z-index: -1;');\n\tobject.type = 'text/html';\n\n\tlet win;\n\n\tobject.onload = () => {\n\t\twin = object.contentDocument.defaultView;\n\t\twin.addEventListener('resize', fn);\n\t};\n\n\tif (/Trident/.test(navigator.userAgent)) {\n\t\telement.appendChild(object);\n\t\tobject.data = 'about:blank';\n\t} else {\n\t\tobject.data = 'about:blank';\n\t\telement.appendChild(object);\n\t}\n\n\treturn {\n\t\tcancel: () => {\n\t\t\twin.removeEventListener('resize', fn);\n\t\t\telement.removeChild(object);\n\t\t}\n\t};\n}",
        "blankObject": "function blankObject() {\n\treturn Object.create(null);\n}",
        "destroy": "function destroy(detach) {\n\tthis.destroy = noop;\n\tthis.fire('destroy');\n\tthis.set = noop;\n\n\tthis._fragment.d(detach !== false);\n\tthis._fragment = null;\n\tthis._state = {};\n}",
        "destroyDev": "function destroyDev(detach) {\n\tdestroy.call(this, detach);\n\tthis.destroy = function() {\n\t\tconsole.warn('Component was already destroyed');\n\t};\n}",
        "_differs": "function _differs(a, b) {\n\treturn a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function');\n}",
        "_differsImmutable": "function _differsImmutable(a, b) {\n\treturn a != a ? b == b : a !== b;\n}",
        "fire": "function fire(eventName, data) {\n\tvar handlers =\n\t\teventName in this._handlers && this._handlers[eventName].slice();\n\tif (!handlers) return;\n\n\tfor (var i = 0; i < handlers.length; i += 1) {\n\t\tvar handler = handlers[i];\n\n\t\tif (!handler.__calling) {\n\t\t\thandler.__calling = true;\n\t\t\thandler.call(this, data);\n\t\t\thandler.__calling = false;\n\t\t}\n\t}\n}",
        "get": "function get() {\n\treturn this._state;\n}",
        "init": "function init(component, options) {\n\tcomponent._handlers = blankObject();\n\tcomponent._bind = options._bind;\n\n\tcomponent.options = options;\n\tcomponent.root = options.root || component;\n\tcomponent.store = component.root.store || options.store;\n}",
        "on": "function on(eventName, handler) {\n\tvar handlers = this._handlers[eventName] || (this._handlers[eventName] = []);\n\thandlers.push(handler);\n\n\treturn {\n\t\tcancel: function() {\n\t\t\tvar index = handlers.indexOf(handler);\n\t\t\tif (~index) handlers.splice(index, 1);\n\t\t}\n\t};\n}",
        "run": "function run(fn) {\n\tfn();\n}",
        "set": "function set(newState) {\n\tthis._set(assign({}, newState));\n\tif (this.root._lock) return;\n\tthis.root._lock = true;\n\tcallAll(this.root._beforecreate);\n\tcallAll(this.root._oncreate);\n\tcallAll(this.root._aftercreate);\n\tthis.root._lock = false;\n}",
        "_set": "function _set(newState) {\n\tvar oldState = this._state,\n\t\tchanged = {},\n\t\tdirty = false;\n\n\tfor (var key in newState) {\n\t\tif (this._differs(newState[key], oldState[key])) changed[key] = dirty = true;\n\t}\n\tif (!dirty) return;\n\n\tthis._state = assign(assign({}, oldState), newState);\n\tthis._recompute(changed, this._state);\n\tif (this._bind) this._bind(changed, this._state);\n\n\tif (this._fragment) {\n\t\tthis.fire(\"state\", { changed: changed, current: this._state, previous: oldState });\n\t\tthis._fragment.p(changed, this._state);\n\t\tthis.fire(\"update\", { changed: changed, current: this._state, previous: oldState });\n\t}\n}",
        "setDev": "function setDev(newState) {\n\tif (typeof newState !== 'object') {\n\t\tthrow new Error(\n\t\t\tthis._debugName + '.set was called without an object of data key-values to update.'\n\t\t);\n\t}\n\n\tthis._checkReadOnly(newState);\n\tset.call(this, newState);\n}",
        "callAll": "function callAll(fns) {\n\twhile (fns && fns.length) fns.shift()();\n}",
        "_mount": "function _mount(target, anchor) {\n\tthis._fragment[this._fragment.i ? 'i' : 'm'](target, anchor || null);\n}",
        "PENDING": "{}",
        "SUCCESS": "{}",
        "FAILURE": "{}",
        "removeFromStore": "function removeFromStore() {\n\tthis.store._remove(this);\n}",
        "proto": "{\n\tdestroy,\n\tget,\n\tfire,\n\ton,\n\tset,\n\t_recompute: noop,\n\t_set,\n\t_mount,\n\t_differs\n}",
        "protoDev": "{\n\tdestroy: destroyDev,\n\tget,\n\tfire,\n\ton,\n\tset: setDev,\n\t_recompute: noop,\n\t_set,\n\t_mount,\n\t_differs\n}",
        "destroyBlock": "function destroyBlock(block, lookup) {\n\tblock.d(1);\n\tlookup[block.key] = null;\n}",
        "outroAndDestroyBlock": "function outroAndDestroyBlock(block, lookup) {\n\tblock.o(function() {\n\t\tdestroyBlock(block, lookup);\n\t});\n}",
        "fixAndOutroAndDestroyBlock": "function fixAndOutroAndDestroyBlock(block, lookup) {\n\tblock.f();\n\toutroAndDestroyBlock(block, lookup);\n}",
        "updateKeyedEach": "function updateKeyedEach(old_blocks, component, changed, get_key, dynamic, ctx, list, lookup, node, destroy, create_each_block, intro_method, next, get_context) {\n\tvar o = old_blocks.length;\n\tvar n = list.length;\n\n\tvar i = o;\n\tvar old_indexes = {};\n\twhile (i--) old_indexes[old_blocks[i].key] = i;\n\n\tvar new_blocks = [];\n\tvar new_lookup = {};\n\tvar deltas = {};\n\n\tvar i = n;\n\twhile (i--) {\n\t\tvar child_ctx = get_context(ctx, list, i);\n\t\tvar key = get_key(child_ctx);\n\t\tvar block = lookup[key];\n\n\t\tif (!block) {\n\t\t\tblock = create_each_block(component, key, child_ctx);\n\t\t\tblock.c();\n\t\t} else if (dynamic) {\n\t\t\tblock.p(changed, child_ctx);\n\t\t}\n\n\t\tnew_blocks[i] = new_lookup[key] = block;\n\n\t\tif (key in old_indexes) deltas[key] = Math.abs(i - old_indexes[key]);\n\t}\n\n\tvar will_move = {};\n\tvar did_move = {};\n\n\tfunction insert(block) {\n\t\tblock[intro_method](node, next);\n\t\tlookup[block.key] = block;\n\t\tnext = block.first;\n\t\tn--;\n\t}\n\n\twhile (o && n) {\n\t\tvar new_block = new_blocks[n - 1];\n\t\tvar old_block = old_blocks[o - 1];\n\t\tvar new_key = new_block.key;\n\t\tvar old_key = old_block.key;\n\n\t\tif (new_block === old_block) {\n\t\t\t// do nothing\n\t\t\tnext = new_block.first;\n\t\t\to--;\n\t\t\tn--;\n\t\t}\n\n\t\telse if (!new_lookup[old_key]) {\n\t\t\t// remove old block\n\t\t\tdestroy(old_block, lookup);\n\t\t\to--;\n\t\t}\n\n\t\telse if (!lookup[new_key] || will_move[new_key]) {\n\t\t\tinsert(new_block);\n\t\t}\n\n\t\telse if (did_move[old_key]) {\n\t\t\to--;\n\n\t\t} else if (deltas[new_key] > deltas[old_key]) {\n\t\t\tdid_move[new_key] = true;\n\t\t\tinsert(new_block);\n\n\t\t} else {\n\t\t\twill_move[old_key] = true;\n\t\t\to--;\n\t\t}\n\t}\n\n\twhile (o--) {\n\t\tvar old_block = old_blocks[o];\n\t\tif (!new_lookup[old_block.key]) destroy(old_block, lookup);\n\t}\n\n\twhile (n) insert(new_blocks[n - 1]);\n\n\treturn new_blocks;\n}",
        "measure": "function measure(blocks) {\n\tconst rects = {};\n\tlet i = blocks.length;\n\twhile (i--) rects[blocks[i].key] = blocks[i].node.getBoundingClientRect();\n\treturn rects;\n}",
        "animate": "function animate(blocks, rects, fn, params) {\n\tlet i = blocks.length;\n\twhile (i--) {\n\t\tconst block = blocks[i];\n\t\tconst from = rects[block.key];\n\n\t\tif (!from) continue;\n\t\tconst to = block.node.getBoundingClientRect();\n\n\t\tif (from.left === to.left && from.right === to.right && from.top === to.top && from.bottom === to.bottom) continue;\n\n\n\t}\n}",
        "getSpreadUpdate": "function getSpreadUpdate(levels, updates) {\n\tvar update = {};\n\n\tvar to_null_out = {};\n\tvar accounted_for = {};\n\n\tvar i = levels.length;\n\twhile (i--) {\n\t\tvar o = levels[i];\n\t\tvar n = updates[i];\n\n\t\tif (n) {\n\t\t\tfor (var key in o) {\n\t\t\t\tif (!(key in n)) to_null_out[key] = 1;\n\t\t\t}\n\n\t\t\tfor (var key in n) {\n\t\t\t\tif (!accounted_for[key]) {\n\t\t\t\t\tupdate[key] = n[key];\n\t\t\t\t\taccounted_for[key] = 1;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlevels[i] = n;\n\t\t} else {\n\t\t\tfor (var key in o) {\n\t\t\t\taccounted_for[key] = 1;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (var key in to_null_out) {\n\t\tif (!(key in update)) update[key] = undefined;\n\t}\n\n\treturn update;\n}",
        "spread": "function spread(args) {\n\tconst attributes = Object.assign({}, ...args);\n\tlet str = '';\n\n\tObject.keys(attributes).forEach(name => {\n\t\tconst value = attributes[name];\n\t\tif (value === undefined) return;\n\t\tif (value === true) str += \" \" + name;\n\t\tstr += \" \" + name + \"=\" + JSON.stringify(value);\n\t});\n\n\treturn str;\n}",
        "escaped": "{\n\t'\"': '&quot;',\n\t\"'\": '&#39;',\n\t'&': '&amp;',\n\t'<': '&lt;',\n\t'>': '&gt;'\n}",
        "escape": "function escape(html) {\n\treturn String(html).replace(/[\"'&<>]/g, match => escaped[match]);\n}",
        "each": "function each(items, assign, fn) {\n\tlet str = '';\n\tfor (let i = 0; i < items.length; i += 1) {\n\t\tstr += fn(assign(items[i], i));\n\t}\n\treturn str;\n}",
        "missingComponent": "{\n\t_render: () => ''\n}",
        "linear": "function linear(t) {\n\treturn t;\n}",
        "generateRule": "function generateRule({ a, b, delta, duration }, ease, fn) {\n\tconst step = 16.666 / duration;\n\tlet keyframes = '{\\n';\n\n\tfor (let p = 0; p <= 1; p += step) {\n\t\tconst t = a + delta * ease(p);\n\t\tkeyframes += p * 100 + `%{${fn(t, 1 - t)}}\\n`;\n\t}\n\n\treturn keyframes + `100% {${fn(b, 1 - b)}}\\n}`;\n}",
        "hash": "function hash(str) {\n\tlet hash = 5381;\n\tlet i = str.length;\n\n\twhile (i--) hash = ((hash << 5) - hash) ^ str.charCodeAt(i);\n\treturn hash >>> 0;\n}",
        "wrapTransition": "function wrapTransition(component, node, fn, params, intro) {\n\tlet obj = fn(node, params);\n\tlet duration;\n\tlet ease;\n\tlet cssText;\n\n\tlet initialised = false;\n\n\treturn {\n\t\tt: intro ? 0 : 1,\n\t\trunning: false,\n\t\tprogram: null,\n\t\tpending: null,\n\n\t\trun(b, callback) {\n\t\t\tif (typeof obj === 'function') {\n\t\t\t\ttransitionManager.wait().then(() => {\n\t\t\t\t\tobj = obj();\n\t\t\t\t\tthis._run(b, callback);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tthis._run(b, callback);\n\t\t\t}\n\t\t},\n\n\t\t_run(b, callback) {\n\t\t\tduration = obj.duration || 300;\n\t\t\tease = obj.easing || linear;\n\n\t\t\tconst program = {\n\t\t\t\tstart: window.performance.now() + (obj.delay || 0),\n\t\t\t\tb,\n\t\t\t\tcallback: callback || noop\n\t\t\t};\n\n\t\t\tif (intro && !initialised) {\n\t\t\t\tif (obj.css && obj.delay) {\n\t\t\t\t\tcssText = node.style.cssText;\n\t\t\t\t\tnode.style.cssText += obj.css(0, 1);\n\t\t\t\t}\n\n\t\t\t\tif (obj.tick) obj.tick(0, 1);\n\t\t\t\tinitialised = true;\n\t\t\t}\n\n\t\t\tif (!b) {\n\t\t\t\tprogram.group = transitionManager.outros;\n\t\t\t\ttransitionManager.outros.remaining += 1;\n\t\t\t}\n\n\t\t\tif (obj.delay) {\n\t\t\t\tthis.pending = program;\n\t\t\t} else {\n\t\t\t\tthis.start(program);\n\t\t\t}\n\n\t\t\tif (!this.running) {\n\t\t\t\tthis.running = true;\n\t\t\t\ttransitionManager.add(this);\n\t\t\t}\n\t\t},\n\n\t\tstart(program) {\n\t\t\tcomponent.fire(`${program.b ? 'intro' : 'outro'}.start`, { node });\n\n\t\t\tprogram.a = this.t;\n\t\t\tprogram.delta = program.b - program.a;\n\t\t\tprogram.duration = duration * Math.abs(program.b - program.a);\n\t\t\tprogram.end = program.start + program.duration;\n\n\t\t\tif (obj.css) {\n\t\t\t\tif (obj.delay) node.style.cssText = cssText;\n\n\t\t\t\tconst rule = generateRule(program, ease, obj.css);\n\t\t\t\ttransitionManager.addRule(rule, program.name = '__svelte_' + hash(rule));\n\n\t\t\t\tnode.style.animation = (node.style.animation || '')\n\t\t\t\t\t.split(', ')\n\t\t\t\t\t.filter(anim => anim && (program.delta < 0 || !/__svelte/.test(anim)))\n\t\t\t\t\t.concat(`${program.name} ${program.duration}ms linear 1 forwards`)\n\t\t\t\t\t.join(', ');\n\t\t\t}\n\n\t\t\tthis.program = program;\n\t\t\tthis.pending = null;\n\t\t},\n\n\t\tupdate(now) {\n\t\t\tconst program = this.program;\n\t\t\tif (!program) return;\n\n\t\t\tconst p = now - program.start;\n\t\t\tthis.t = program.a + program.delta * ease(p / program.duration);\n\t\t\tif (obj.tick) obj.tick(this.t, 1 - this.t);\n\t\t},\n\n\t\tdone() {\n\t\t\tconst program = this.program;\n\t\t\tthis.t = program.b;\n\n\t\t\tif (obj.tick) obj.tick(this.t, 1 - this.t);\n\n\t\t\tcomponent.fire(`${program.b ? 'intro' : 'outro'}.end`, { node });\n\n\t\t\tif (!program.b && !program.invalidated) {\n\t\t\t\tprogram.group.callbacks.push(() => {\n\t\t\t\t\tprogram.callback();\n\t\t\t\t\tif (obj.css) transitionManager.deleteRule(node, program.name);\n\t\t\t\t});\n\n\t\t\t\tif (--program.group.remaining === 0) {\n\t\t\t\t\tprogram.group.callbacks.forEach(fn => {\n\t\t\t\t\t\tfn();\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (obj.css) transitionManager.deleteRule(node, program.name);\n\t\t\t}\n\n\t\t\tthis.running = !!this.pending;\n\t\t},\n\n\t\tabort() {\n\t\t\tif (this.program) {\n\t\t\t\tif (obj.tick) obj.tick(1, 0);\n\t\t\t\tif (obj.css) transitionManager.deleteRule(node, this.program.name);\n\t\t\t\tthis.program = this.pending = null;\n\t\t\t\tthis.running = false;\n\t\t\t}\n\t\t},\n\n\t\tinvalidate() {\n\t\t\tif (this.program) {\n\t\t\t\tthis.program.invalidated = true;\n\t\t\t}\n\t\t}\n\t};\n}",
        "transitionManager": "{\n\trunning: false,\n\ttransitions: [],\n\tbound: null,\n\tstylesheet: null,\n\tactiveRules: {},\n\tpromise: null,\n\n\tadd(transition) {\n\t\tthis.transitions.push(transition);\n\n\t\tif (!this.running) {\n\t\t\tthis.running = true;\n\t\t\trequestAnimationFrame(this.bound || (this.bound = this.next.bind(this)));\n\t\t}\n\t},\n\n\taddRule(rule, name) {\n\t\tif (!this.stylesheet) {\n\t\t\tconst style = createElement('style');\n\t\t\tdocument.head.appendChild(style);\n\t\t\ttransitionManager.stylesheet = style.sheet;\n\t\t}\n\n\t\tif (!this.activeRules[name]) {\n\t\t\tthis.activeRules[name] = true;\n\t\t\tthis.stylesheet.insertRule(`@keyframes ${name} ${rule}`, this.stylesheet.cssRules.length);\n\t\t}\n\t},\n\n\tnext() {\n\t\tthis.running = false;\n\n\t\tconst now = window.performance.now();\n\t\tlet i = this.transitions.length;\n\n\t\twhile (i--) {\n\t\t\tconst transition = this.transitions[i];\n\n\t\t\tif (transition.program && now >= transition.program.end) {\n\t\t\t\ttransition.done();\n\t\t\t}\n\n\t\t\tif (transition.pending && now >= transition.pending.start) {\n\t\t\t\ttransition.start(transition.pending);\n\t\t\t}\n\n\t\t\tif (transition.running) {\n\t\t\t\ttransition.update(now);\n\t\t\t\tthis.running = true;\n\t\t\t} else if (!transition.pending) {\n\t\t\t\tthis.transitions.splice(i, 1);\n\t\t\t}\n\t\t}\n\n\t\tif (this.running) {\n\t\t\trequestAnimationFrame(this.bound);\n\t\t} else if (this.stylesheet) {\n\t\t\tlet i = this.stylesheet.cssRules.length;\n\t\t\twhile (i--) this.stylesheet.deleteRule(i);\n\t\t\tthis.activeRules = {};\n\t\t}\n\t},\n\n\tdeleteRule(node, name) {\n\t\tnode.style.animation = node.style.animation\n\t\t\t.split(', ')\n\t\t\t.filter(anim => anim && anim.indexOf(name) === -1)\n\t\t\t.join(', ');\n\t},\n\n\tgroupOutros() {\n\t\tthis.outros = {\n\t\t\tremaining: 0,\n\t\t\tcallbacks: []\n\t\t};\n\t},\n\n\twait() {\n\t\tif (!transitionManager.promise) {\n\t\t\ttransitionManager.promise = Promise.resolve();\n\t\t\ttransitionManager.promise.then(() => {\n\t\t\t\ttransitionManager.promise = null;\n\t\t\t});\n\t\t}\n\n\t\treturn transitionManager.promise;\n\t}\n}",
        "noop": "function noop() {}",
        "assign": "function assign(tar, src) {\n\tfor (var k in src) tar[k] = src[k];\n\treturn tar;\n}",
        "assignTrue": "function assignTrue(tar, src) {\n\tfor (var k in src) tar[k] = 1;\n\treturn tar;\n}",
        "isPromise": "function isPromise(value) {\n\treturn value && typeof value.then === 'function';\n}",
        "callAfter": "function callAfter(fn, i) {\n\treturn () => {\n\t\tif (!--i) fn();\n\t};\n}"
    };

    function detectIndentation(str) {
        const pattern = /^[\t\s]{1,4}/gm;
        let match;
        while (match = pattern.exec(str)) {
            if (match[0][0] === '\t')
                return '\t';
            if (match[0].length === 2)
                return '  ';
        }
        return '    ';
    }
    function getIndentationLevel(str, b) {
        let a = b;
        while (a > 0 && str[a - 1] !== '\n')
            a -= 1;
        return /^\s*/.exec(str.slice(a, b))[0];
    }
    function getIndentExclusionRanges(node) {
        const ranges = [];
        walk(node, {
            enter(node) {
                if (node.type === 'TemplateElement')
                    ranges.push(node);
            }
        });
        return ranges;
    }
    function removeIndentation(code, start, end, indentationLevel, ranges) {
        const str = code.original.slice(start, end);
        const pattern = new RegExp(`^${indentationLevel}`, 'gm');
        let match;
        while (match = pattern.exec(str)) {
            // TODO bail if we're inside an exclusion range
            code.remove(start + match.index, start + match.index + indentationLevel.length);
        }
    }
    // We need to tell estree-walker that it should always
    // look for an `else` block, otherwise it might get
    // the wrong idea about the shape of each/if blocks
    childKeys.EachBlock = childKeys.IfBlock = ['children', 'else'];
    childKeys.Attribute = ['value'];
    class Compiler {
        constructor(ast, source, name, stylesheet, options, stats, dom, target) {
            stats.start('compile');
            this.stats = stats;
            this.ast = ast;
            this.source = source;
            this.options = options;
            this.target = target;
            this.imports = [];
            this.shorthandImports = [];
            this.helpers = new Set();
            this.components = new Set();
            this.events = new Set();
            this.methods = new Set();
            this.animations = new Set();
            this.transitions = new Set();
            this.actions = new Set();
            this.importedComponents = new Map();
            this.slots = new Set();
            this.bindingGroups = [];
            this.indirectDependencies = new Map();
            this.locate = getLocator(this.source);
            // track which properties are needed, so we can provide useful info
            // in dev mode
            this.expectedProperties = new Set();
            this.code = new MagicString(source);
            this.usesRefs = false;
            // styles
            this.stylesheet = stylesheet;
            // allow compiler to deconflict user's `import { get } from 'whatever'` and
            // Svelte's builtin `import { get, ... } from 'svelte/shared.ts'`;
            this.userVars = new Set();
            this.templateVars = new Map();
            this.aliases = new Map();
            this.usedNames = new Set();
            this.computations = [];
            this.templateProperties = {};
            this.walkJs(dom);
            this.name = this.alias(name);
            if (options.customElement === true) {
                this.customElement = {
                    tag: this.tag,
                    props: this.props
                };
            }
            else {
                this.customElement = options.customElement;
            }
            if (this.customElement && !this.customElement.tag) {
                throw new Error(`No tag name specified`); // TODO better error
            }
            this.fragment = new Fragment(this, ast.html);
            // this.walkTemplate();
            if (!this.customElement)
                this.stylesheet.reify();
            stylesheet.warnOnUnusedSelectors(options.onwarn);
        }
        addSourcemapLocations(node) {
            walk(node, {
                enter: (node) => {
                    this.code.addSourcemapLocation(node.start);
                    this.code.addSourcemapLocation(node.end);
                },
            });
        }
        alias(name) {
            if (!this.aliases.has(name)) {
                this.aliases.set(name, this.getUniqueName(name));
            }
            return this.aliases.get(name);
        }
        generate(result, options, { banner = '', name, format }) {
            const pattern = /\[✂(\d+)-(\d+)$/;
            const helpers = new Set();
            // TODO use same regex for both
            result = result.replace(options.generate === 'ssr' ? /(@+|#+|%+)(\w*(?:-\w*)?)/g : /(%+|@+)(\w*(?:-\w*)?)/g, (match, sigil, name) => {
                if (sigil === '@') {
                    if (name in shared) {
                        if (options.dev && `${name}Dev` in shared)
                            name = `${name}Dev`;
                        helpers.add(name);
                    }
                    return this.alias(name);
                }
                if (sigil === '%') {
                    return this.templateVars.get(name);
                }
                return sigil.slice(1) + name;
            });
            let importedHelpers;
            if (options.shared) {
                if (format !== 'es' && format !== 'cjs') {
                    throw new Error(`Components with shared helpers must be compiled with \`format: 'es'\` or \`format: 'cjs'\``);
                }
                importedHelpers = Array.from(helpers).sort().map(name => {
                    const alias = this.alias(name);
                    return { name, alias };
                });
            }
            else {
                let inlineHelpers = '';
                const compiler = this;
                importedHelpers = [];
                helpers.forEach(name => {
                    const str = shared[name];
                    const code = new MagicString(str);
                    const expression = parseExpressionAt(str, 0);
                    let { scope } = annotateWithScopes(expression);
                    walk(expression, {
                        enter(node, parent) {
                            if (node._scope)
                                scope = node._scope;
                            if (node.type === 'Identifier' &&
                                isReference(node, parent) &&
                                !scope.has(node.name)) {
                                if (node.name in shared) {
                                    // this helper function depends on another one
                                    const dependency = node.name;
                                    helpers.add(dependency);
                                    const alias = compiler.alias(dependency);
                                    if (alias !== node.name) {
                                        code.overwrite(node.start, node.end, alias);
                                    }
                                }
                            }
                        },
                        leave(node) {
                            if (node._scope)
                                scope = scope.parent;
                        },
                    });
                    if (name === 'transitionManager') {
                        // special case
                        const global = `_svelteTransitionManager`;
                        inlineHelpers += `\n\nvar ${this.alias('transitionManager')} = window.${global} || (window.${global} = ${code});\n\n`;
                    }
                    else if (name === 'escaped' || name === 'missingComponent') {
                        // vars are an awkward special case... would be nice to avoid this
                        const alias = this.alias(name);
                        inlineHelpers += `\n\nconst ${alias} = ${code};`;
                    }
                    else {
                        const alias = this.alias(expression.id.name);
                        if (alias !== expression.id.name) {
                            code.overwrite(expression.id.start, expression.id.end, alias);
                        }
                        inlineHelpers += `\n\n${code}`;
                    }
                });
                result += inlineHelpers;
            }
            const sharedPath = options.shared === true
                ? 'svelte/shared.js'
                : options.shared || '';
            const module = wrapModule(result, format, name, options, banner, sharedPath, importedHelpers, this.imports, this.shorthandImports, this.source);
            const parts = module.split('✂]');
            const finalChunk = parts.pop();
            const compiled = new Bundle({ separator: '' });
            function addString(str) {
                compiled.addSource({
                    content: new MagicString(str),
                });
            }
            const { filename } = options;
            // special case — the source file doesn't actually get used anywhere. we need
            // to add an empty file to populate map.sources and map.sourcesContent
            if (!parts.length) {
                compiled.addSource({
                    filename,
                    content: new MagicString(this.source).remove(0, this.source.length),
                });
            }
            parts.forEach((str) => {
                const chunk = str.replace(pattern, '');
                if (chunk)
                    addString(chunk);
                const match = pattern.exec(str);
                const snippet = this.code.snip(+match[1], +match[2]);
                compiled.addSource({
                    filename,
                    content: snippet,
                });
            });
            addString(finalChunk);
            const css = this.customElement ?
                { code: null, map: null } :
                this.stylesheet.render(options.cssOutputFilename, true);
            const js = {
                code: compiled.toString(),
                map: compiled.generateMap({
                    includeContent: true,
                    file: options.outputFilename,
                })
            };
            this.stats.stop('compile');
            return {
                ast: this.ast,
                js,
                css,
                stats: this.stats.render(this)
            };
        }
        getUniqueName(name) {
            if (test)
                name = `${name}$`;
            let alias = name;
            for (let i = 1; reservedNames.has(alias) ||
                this.userVars.has(alias) ||
                this.usedNames.has(alias); alias = `${name}_${i++}`)
                ;
            this.usedNames.add(alias);
            return alias;
        }
        getUniqueNameMaker() {
            const localUsedNames = new Set();
            function add(name) {
                localUsedNames.add(name);
            }
            reservedNames.forEach(add);
            this.userVars.forEach(add);
            return (name) => {
                if (test)
                    name = `${name}$`;
                let alias = name;
                for (let i = 1; this.usedNames.has(alias) ||
                    localUsedNames.has(alias); alias = `${name}_${i++}`)
                    ;
                localUsedNames.add(alias);
                return alias;
            };
        }
        walkJs(dom) {
            const { code, source, computations, methods, templateProperties, imports } = this;
            const { js } = this.ast;
            const componentDefinition = new CodeBuilder();
            if (js) {
                this.addSourcemapLocations(js.content);
                const indentation = detectIndentation(source.slice(js.start, js.end));
                const indentationLevel = getIndentationLevel(source, js.content.body[0].start);
                const indentExclusionRanges = getIndentExclusionRanges(js.content);
                const { scope, globals } = annotateWithScopes(js.content);
                scope.declarations.forEach(name => {
                    this.userVars.add(name);
                });
                globals.forEach(name => {
                    this.userVars.add(name);
                });
                const body = js.content.body.slice(); // slice, because we're going to be mutating the original
                // imports need to be hoisted out of the IIFE
                for (let i = 0; i < body.length; i += 1) {
                    const node = body[i];
                    if (node.type === 'ImportDeclaration') {
                        removeNode(code, js.content, node);
                        imports.push(node);
                        node.specifiers.forEach((specifier) => {
                            this.userVars.add(specifier.local.name);
                        });
                    }
                }
                const defaultExport = this.defaultExport = body.find((node) => node.type === 'ExportDefaultDeclaration');
                if (defaultExport) {
                    defaultExport.declaration.properties.forEach((prop) => {
                        templateProperties[getMethodName(prop.key)] = prop;
                    });
                    ['helpers', 'events', 'components', 'transitions', 'actions', 'animations'].forEach(key => {
                        if (templateProperties[key]) {
                            templateProperties[key].value.properties.forEach((prop) => {
                                this[key].add(getMethodName(prop.key));
                            });
                        }
                    });
                    const addArrowFunctionExpression = (name, node) => {
                        const { body, params, async } = node;
                        const fnKeyword = async ? 'async function' : 'function';
                        const paramString = params.length ?
                            `[✂${params[0].start}-${params[params.length - 1].end}✂]` :
                            ``;
                        if (body.type === 'BlockStatement') {
                            componentDefinition.addBlock(deindent `
							${fnKeyword} ${name}(${paramString}) [✂${body.start}-${body.end}✂]
						`);
                        }
                        else {
                            componentDefinition.addBlock(deindent `
							${fnKeyword} ${name}(${paramString}) {
								return [✂${body.start}-${body.end}✂];
							}
						`);
                        }
                    };
                    const addFunctionExpression = (name, node) => {
                        const { async } = node;
                        const fnKeyword = async ? 'async function' : 'function';
                        let c = node.start;
                        while (this.source[c] !== '(')
                            c += 1;
                        componentDefinition.addBlock(deindent `
						${fnKeyword} ${name}[✂${c}-${node.end}✂];
					`);
                    };
                    const addValue = (name, node) => {
                        componentDefinition.addBlock(deindent `
						var ${name} = [✂${node.start}-${node.end}✂];
					`);
                    };
                    const addDeclaration = (key, node, allowShorthandImport, disambiguator, conflicts) => {
                        const qualified = disambiguator ? `${disambiguator}-${key}` : key;
                        if (node.type === 'Identifier' && node.name === key) {
                            this.templateVars.set(qualified, key);
                            return;
                        }
                        let deconflicted = key;
                        if (conflicts)
                            while (deconflicted in conflicts)
                                deconflicted += '_';
                        let name = this.getUniqueName(deconflicted);
                        this.templateVars.set(qualified, name);
                        if (allowShorthandImport && node.type === 'Literal' && typeof node.value === 'string') {
                            this.shorthandImports.push({ name, source: node.value });
                            return;
                        }
                        // deindent
                        const indentationLevel = getIndentationLevel(source, node.start);
                        if (indentationLevel) {
                            removeIndentation(code, node.start, node.end, indentationLevel, indentExclusionRanges);
                        }
                        if (node.type === 'ArrowFunctionExpression') {
                            addArrowFunctionExpression(name, node);
                        }
                        else if (node.type === 'FunctionExpression') {
                            addFunctionExpression(name, node);
                        }
                        else {
                            addValue(name, node);
                        }
                    };
                    if (templateProperties.components) {
                        templateProperties.components.value.properties.forEach((property) => {
                            addDeclaration(getMethodName(property.key), property.value, true, 'components');
                        });
                    }
                    if (templateProperties.computed) {
                        const dependencies = new Map();
                        const fullStateComputations = [];
                        templateProperties.computed.value.properties.forEach((prop) => {
                            const key = getMethodName(prop.key);
                            const value = prop.value;
                            addDeclaration(key, value, false, 'computed', {
                                state: true,
                                changed: true
                            });
                            const param = value.params[0];
                            if (param.type === 'ObjectPattern') {
                                const deps = param.properties.map(prop => prop.key.name);
                                deps.forEach(dep => {
                                    this.expectedProperties.add(dep);
                                });
                                dependencies.set(key, deps);
                            }
                            else {
                                fullStateComputations.push({ key, deps: null });
                            }
                        });
                        const visited = new Set();
                        const visit = (key) => {
                            if (!dependencies.has(key))
                                return; // not a computation
                            if (visited.has(key))
                                return;
                            visited.add(key);
                            const deps = dependencies.get(key);
                            deps.forEach(visit);
                            computations.push({ key, deps });
                            const prop = templateProperties.computed.value.properties.find((prop) => getMethodName(prop.key) === key);
                        };
                        templateProperties.computed.value.properties.forEach((prop) => visit(getMethodName(prop.key)));
                        if (fullStateComputations.length > 0) {
                            computations.push(...fullStateComputations);
                        }
                    }
                    if (templateProperties.data) {
                        addDeclaration('data', templateProperties.data.value);
                    }
                    if (templateProperties.events && dom) {
                        templateProperties.events.value.properties.forEach((property) => {
                            addDeclaration(getMethodName(property.key), property.value, false, 'events');
                        });
                    }
                    if (templateProperties.helpers) {
                        templateProperties.helpers.value.properties.forEach((property) => {
                            addDeclaration(getMethodName(property.key), property.value, false, 'helpers');
                        });
                    }
                    if (templateProperties.methods && dom) {
                        addDeclaration('methods', templateProperties.methods.value);
                        templateProperties.methods.value.properties.forEach(prop => {
                            this.methods.add(prop.key.name);
                        });
                    }
                    if (templateProperties.namespace) {
                        const ns = nodeToString(templateProperties.namespace.value);
                        this.namespace = namespaces[ns] || ns;
                    }
                    if (templateProperties.oncreate && dom) {
                        addDeclaration('oncreate', templateProperties.oncreate.value);
                    }
                    if (templateProperties.ondestroy && dom) {
                        addDeclaration('ondestroy', templateProperties.ondestroy.value);
                    }
                    if (templateProperties.onstate && dom) {
                        addDeclaration('onstate', templateProperties.onstate.value);
                    }
                    if (templateProperties.onupdate && dom) {
                        addDeclaration('onupdate', templateProperties.onupdate.value);
                    }
                    if (templateProperties.preload) {
                        addDeclaration('preload', templateProperties.preload.value);
                    }
                    if (templateProperties.props) {
                        this.props = templateProperties.props.value.elements.map((element) => nodeToString(element));
                    }
                    if (templateProperties.setup) {
                        addDeclaration('setup', templateProperties.setup.value);
                    }
                    if (templateProperties.store) {
                        addDeclaration('store', templateProperties.store.value);
                    }
                    if (templateProperties.tag) {
                        this.tag = nodeToString(templateProperties.tag.value);
                    }
                    if (templateProperties.transitions) {
                        templateProperties.transitions.value.properties.forEach((property) => {
                            addDeclaration(getMethodName(property.key), property.value, false, 'transitions');
                        });
                    }
                    if (templateProperties.animations) {
                        templateProperties.animations.value.properties.forEach((property) => {
                            addDeclaration(getMethodName(property.key), property.value, false, 'animations');
                        });
                    }
                    if (templateProperties.actions) {
                        templateProperties.actions.value.properties.forEach((property) => {
                            addDeclaration(getMethodName(property.key), property.value, false, 'actions');
                        });
                    }
                }
                if (indentationLevel) {
                    if (defaultExport) {
                        removeIndentation(code, js.content.start, defaultExport.start, indentationLevel, indentExclusionRanges);
                        removeIndentation(code, defaultExport.end, js.content.end, indentationLevel, indentExclusionRanges);
                    }
                    else {
                        removeIndentation(code, js.content.start, js.content.end, indentationLevel, indentExclusionRanges);
                    }
                }
                let a = js.content.start;
                while (/\s/.test(source[a]))
                    a += 1;
                let b = js.content.end;
                while (/\s/.test(source[b - 1]))
                    b -= 1;
                if (defaultExport) {
                    this.javascript = '';
                    if (a !== defaultExport.start)
                        this.javascript += `[✂${a}-${defaultExport.start}✂]`;
                    if (!componentDefinition.isEmpty())
                        this.javascript += componentDefinition;
                    if (defaultExport.end !== b)
                        this.javascript += `[✂${defaultExport.end}-${b}✂]`;
                }
                else {
                    this.javascript = a === b ? null : `[✂${a}-${b}✂]`;
                }
            }
        }
    }

    class DomTarget {
        constructor() {
            this.blocks = [];
            this.readonly = new Set();
            // initial values for e.g. window.innerWidth, if there's a <svelte:window> meta tag
            this.metaBindings = [];
        }
    }
    function dom(ast, source, stylesheet, options, stats) {
        const format = options.format || 'es';
        const target = new DomTarget();
        const compiler = new Compiler(ast, source, options.name || 'SvelteComponent', stylesheet, options, stats, true, target);
        const { computations, name, templateProperties, namespace, } = compiler;
        compiler.fragment.build();
        const { block } = compiler.fragment;
        if (compiler.options.nestedTransitions) {
            block.hasOutroMethod = true;
        }
        // prevent fragment being created twice (#1063)
        if (options.customElement)
            block.builders.create.addLine(`this.c = @noop;`);
        const builder = new CodeBuilder();
        const computationBuilder = new CodeBuilder();
        const computationDeps = new Set();
        if (computations.length) {
            computations.forEach(({ key, deps }) => {
                if (target.readonly.has(key)) {
                    // <svelte:window> bindings
                    throw new Error(`Cannot have a computed value '${key}' that clashes with a read-only property`);
                }
                target.readonly.add(key);
                if (deps) {
                    deps.forEach(dep => {
                        computationDeps.add(dep);
                    });
                    const condition = `${deps.map(dep => `changed.${dep}`).join(' || ')}`;
                    const statement = `if (this._differs(state.${key}, (state.${key} = %computed-${key}(state)))) changed.${key} = true;`;
                    computationBuilder.addConditional(condition, statement);
                }
                else {
                    // computed property depends on entire state object —
                    // these must go at the end
                    computationBuilder.addLine(`if (this._differs(state.${key}, (state.${key} = %computed-${key}(state)))) changed.${key} = true;`);
                }
            });
        }
        if (compiler.javascript) {
            builder.addBlock(compiler.javascript);
        }
        const css = compiler.stylesheet.render(options.filename, !compiler.customElement);
        const styles = compiler.stylesheet.hasStyles && stringify(options.dev ?
            `${css.code}\n/*# sourceMappingURL=${css.map.toUrl()} */` :
            css.code, { onlyEscapeAtSymbol: true });
        if (styles && compiler.options.css !== false && !compiler.customElement) {
            builder.addBlock(deindent `
			function @add_css() {
				var style = @createElement("style");
				style.id = '${compiler.stylesheet.id}-style';
				style.textContent = ${styles};
				@appendNode(style, document.head);
			}
		`);
        }
        target.blocks.forEach(block => {
            builder.addBlock(block.toString());
        });
        const sharedPath = options.shared === true
            ? 'svelte/shared.js'
            : options.shared || '';
        const proto = sharedPath
            ? `@proto`
            : deindent `
		{
			${['destroy', 'get', 'fire', 'on', 'set', '_set', '_mount', '_differs']
            .map(n => `${n}: @${n}`)
            .join(',\n')}
		}`;
        const debugName = `<${compiler.customElement ? compiler.tag : name}>`;
        // generate initial state object
        const expectedProperties = Array.from(compiler.expectedProperties);
        const globals = expectedProperties.filter(prop => globalWhitelist.has(prop));
        const storeProps = expectedProperties.filter(prop => prop[0] === '$');
        const initialState = [];
        if (globals.length > 0) {
            initialState.push(`{ ${globals.map(prop => `${prop} : ${prop}`).join(', ')} }`);
        }
        if (storeProps.length > 0) {
            initialState.push(`this.store._init([${storeProps.map(prop => `"${prop.slice(1)}"`)}])`);
        }
        if (templateProperties.data) {
            initialState.push(`%data()`);
        }
        else if (globals.length === 0 && storeProps.length === 0) {
            initialState.push('{}');
        }
        initialState.push(`options.data`);
        const hasInitHooks = !!(templateProperties.oncreate || templateProperties.onstate || templateProperties.onupdate);
        const constructorBody = deindent `
		${options.dev && `this._debugName = '${debugName}';`}
		${options.dev && !compiler.customElement &&
        `if (!options || (!options.target && !options.root)) throw new Error("'target' is a required option");`}
		@init(this, options);
		${templateProperties.store && `this.store = %store();`}
		${compiler.usesRefs && `this.refs = {};`}
		this._state = ${initialState.reduce((state, piece) => `@assign(${state}, ${piece})`)};
		${storeProps.length > 0 && `this.store._add(this, [${storeProps.map(prop => `"${prop.slice(1)}"`)}]);`}
		${target.metaBindings}
		${computations.length && `this._recompute({ ${Array.from(computationDeps).map(dep => `${dep}: 1`).join(', ')} }, this._state);`}
		${options.dev &&
        Array.from(compiler.expectedProperties).map(prop => {
            if (globalWhitelist.has(prop))
                return;
            if (computations.find(c => c.key === prop))
                return;
            const message = compiler.components.has(prop) ?
                `${debugName} expected to find '${prop}' in \`data\`, but found it in \`components\` instead` :
                `${debugName} was created without expected data property '${prop}'`;
            const conditions = [`!('${prop}' in this._state)`];
            if (compiler.customElement)
                conditions.push(`!('${prop}' in this.attributes)`);
            return `if (${conditions.join(' && ')}) console.warn("${message}");`;
        })}
		${compiler.bindingGroups.length &&
        `this._bindingGroups = [${Array(compiler.bindingGroups.length).fill('[]').join(', ')}];`}
		this._intro = ${compiler.options.skipIntroByDefault ? '!!options.intro' : 'true'};

		${templateProperties.onstate && `this._handlers.state = [%onstate];`}
		${templateProperties.onupdate && `this._handlers.update = [%onupdate];`}

		${(templateProperties.ondestroy || storeProps.length) && (`this._handlers.destroy = [${[templateProperties.ondestroy && `%ondestroy`, storeProps.length && `@removeFromStore`].filter(Boolean).join(', ')}];`)}

		${compiler.slots.size && `this._slotted = options.slots || {};`}

		${compiler.customElement ?
        deindent `
				this.attachShadow({ mode: 'open' });
				${css.code && `this.shadowRoot.innerHTML = \`<style>${escape(css.code, { onlyEscapeAtSymbol: true }).replace(/\\/g, '\\\\')}${options.dev ? `\n/*# sourceMappingURL=${css.map.toUrl()} */` : ''}</style>\`;`}
			` :
        (compiler.stylesheet.hasStyles && options.css !== false &&
            `if (!document.getElementById("${compiler.stylesheet.id}-style")) @add_css();`)}

		${(hasInitHooks || compiler.hasComponents || target.hasComplexBindings || target.hasIntroTransitions) && deindent `
			if (!options.root) {
				this._oncreate = [];
				${(compiler.hasComponents || target.hasComplexBindings) && `this._beforecreate = [];`}
				${(compiler.hasComponents || target.hasIntroTransitions) && `this._aftercreate = [];`}
			}
		`}

		${compiler.slots.size && `this.slots = {};`}

		this._fragment = @create_main_fragment(this, this._state);

		${hasInitHooks && deindent `
			this.root._oncreate.push(() => {
				${templateProperties.onstate && `%onstate.call(this, { changed: @assignTrue({}, this._state), current: this._state });`}
				${templateProperties.oncreate && `%oncreate.call(this);`}
				this.fire("update", { changed: @assignTrue({}, this._state), current: this._state });
			});
		`}

		${compiler.customElement ? deindent `
			this._fragment.c();
			this._fragment.${block.hasIntroMethod ? 'i' : 'm'}(this.shadowRoot, null);

			if (options.target) this._mount(options.target, options.anchor);
		` : deindent `
			if (options.target) {
				${compiler.options.hydratable
        ? deindent `
						var nodes = @children(options.target);
						options.hydrate ? this._fragment.l(nodes) : this._fragment.c();
						nodes.forEach(@detachNode);
					` :
        deindent `
						${options.dev && `if (options.hydrate) throw new Error("options.hydrate only works if the component was compiled with the \`hydratable: true\` option");`}
						this._fragment.c();
					`}
				this._mount(options.target, options.anchor);

				${(compiler.hasComponents || target.hasComplexBindings || hasInitHooks || target.hasIntroTransitions) && deindent `
					${compiler.hasComponents && `this._lock = true;`}
					${(compiler.hasComponents || target.hasComplexBindings) && `@callAll(this._beforecreate);`}
					${(compiler.hasComponents || hasInitHooks) && `@callAll(this._oncreate);`}
					${(compiler.hasComponents || target.hasIntroTransitions) && `@callAll(this._aftercreate);`}
					${compiler.hasComponents && `this._lock = false;`}
				`}
			}
		`}

		${compiler.options.skipIntroByDefault && `this._intro = true;`}
	`;
        if (compiler.customElement) {
            const props = compiler.props || Array.from(compiler.expectedProperties);
            builder.addBlock(deindent `
			class ${name} extends HTMLElement {
				constructor(options = {}) {
					super();
					${constructorBody}
				}

				static get observedAttributes() {
					return ${JSON.stringify(props)};
				}

				${props.map(prop => deindent `
					get ${prop}() {
						return this.get().${prop};
					}

					set ${prop}(value) {
						this.set({ ${prop}: value });
					}
				`).join('\n\n')}

				${compiler.slots.size && deindent `
					connectedCallback() {
						Object.keys(this._slotted).forEach(key => {
							this.appendChild(this._slotted[key]);
						});
					}`}

				attributeChangedCallback(attr, oldValue, newValue) {
					this.set({ [attr]: newValue });
				}

				${(compiler.hasComponents || target.hasComplexBindings || templateProperties.oncreate || target.hasIntroTransitions) && deindent `
					connectedCallback() {
						${compiler.hasComponents && `this._lock = true;`}
						${(compiler.hasComponents || target.hasComplexBindings) && `@callAll(this._beforecreate);`}
						${(compiler.hasComponents || templateProperties.oncreate) && `@callAll(this._oncreate);`}
						${(compiler.hasComponents || target.hasIntroTransitions) && `@callAll(this._aftercreate);`}
						${compiler.hasComponents && `this._lock = false;`}
					}
				`}
			}

			@assign(${name}.prototype, ${proto});
			${templateProperties.methods && `@assign(${name}.prototype, %methods);`}
			@assign(${name}.prototype, {
				_mount(target, anchor) {
					target.insertBefore(this, anchor);
				}
			});

			customElements.define("${compiler.tag}", ${name});
		`);
        }
        else {
            builder.addBlock(deindent `
			function ${name}(options) {
				${constructorBody}
			}

			@assign(${name}.prototype, ${proto});
			${templateProperties.methods && `@assign(${name}.prototype, %methods);`}
		`);
        }
        const immutable = templateProperties.immutable ? templateProperties.immutable.value.value : options.immutable;
        builder.addBlock(deindent `
		${options.dev && deindent `
			${name}.prototype._checkReadOnly = function _checkReadOnly(newState) {
				${Array.from(target.readonly).map(prop => `if ('${prop}' in newState && !this._updatingReadonlyProperty) throw new Error("${debugName}: Cannot set read-only property '${prop}'");`)}
			};
		`}

		${computations.length ? deindent `
			${name}.prototype._recompute = function _recompute(changed, state) {
				${computationBuilder}
			}
		` : (!sharedPath && `${name}.prototype._recompute = @noop;`)}

		${templateProperties.setup && `%setup(${name});`}

		${templateProperties.preload && `${name}.preload = %preload;`}

		${immutable && `${name}.prototype._differs = @_differsImmutable;`}
	`);
        let result = builder.toString();
        const filename = options.filename && (typeof process !== 'undefined' ? options.filename.replace(process.cwd(), '').replace(/^[\/\\]/, '') : options.filename);
        return compiler.generate(result, options, {
            banner: `/* ${filename ? `${filename} ` : ``}generated by Svelte v${"2.6.5"} */`,
            sharedPath,
            name,
            format,
        });
    }

    class SsrTarget {
        constructor() {
            this.bindings = [];
            this.renderCode = '';
            this.appendTargets = [];
        }
        append(code) {
            if (this.appendTargets.length) {
                const appendTarget = this.appendTargets[this.appendTargets.length - 1];
                const slotName = appendTarget.slotStack[appendTarget.slotStack.length - 1];
                appendTarget.slots[slotName] += code;
            }
            else {
                this.renderCode += code;
            }
        }
    }
    function ssr(ast, source, stylesheet, options, stats) {
        const format = options.format || 'cjs';
        const target = new SsrTarget();
        const compiler = new Compiler(ast, source, options.name || 'SvelteComponent', stylesheet, options, stats, false, target);
        const { computations, name, templateProperties } = compiler;
        // create main render() function
        trim(compiler.fragment.children).forEach((node) => {
            node.ssr();
        });
        const css = compiler.customElement ?
            { code: null, map: null } :
            compiler.stylesheet.render(options.filename, true);
        // generate initial state object
        const expectedProperties = Array.from(compiler.expectedProperties);
        const globals = expectedProperties.filter(prop => globalWhitelist.has(prop));
        const storeProps = expectedProperties.filter(prop => prop[0] === '$');
        const initialState = [];
        if (globals.length > 0) {
            initialState.push(`{ ${globals.map(prop => `${prop} : ${prop}`).join(', ')} }`);
        }
        if (storeProps.length > 0) {
            const initialize = `_init([${storeProps.map(prop => `"${prop.slice(1)}"`)}])`;
            initialState.push(`options.store.${initialize}`);
        }
        if (templateProperties.data) {
            initialState.push(`%data()`);
        }
        else if (globals.length === 0 && storeProps.length === 0) {
            initialState.push('{}');
        }
        initialState.push('ctx');
        // TODO concatenate CSS maps
        const result = deindent `
		${compiler.javascript}

		var ${name} = {};

		${options.filename && `${name}.filename = ${stringify(options.filename)}`};

		${name}.data = function() {
			return ${templateProperties.data ? `%data()` : `{}`};
		};

		${name}.render = function(state, options = {}) {
			var components = new Set();

			function addComponent(component) {
				components.add(component);
			}

			var result = { head: '', addComponent };
			var html = ${name}._render(result, state, options);

			var cssCode = Array.from(components).map(c => c.css && c.css.code).filter(Boolean).join('\\n');

			return {
				html,
				head: result.head,
				css: { code: cssCode, map: null },
				toString() {
					return html;
				}
			};
		}

		${name}._render = function(__result, ctx, options) {
			${templateProperties.store && `options.store = %store();`}
			__result.addComponent(${name});

			ctx = Object.assign(${initialState.join(', ')});

			${computations.map(({ key }) => `ctx.${key} = %computed-${key}(ctx);`)}

			${target.bindings.length &&
        deindent `
				var settled = false;
				var tmp;

				while (!settled) {
					settled = true;

					${target.bindings.join('\n\n')}
				}
			`}

			return \`${target.renderCode}\`;
		};

		${name}.css = {
			code: ${css.code ? stringify(css.code) : `''`},
			map: ${css.map ? stringify(css.map.toString()) : 'null'}
		};

		var warned = false;

		${templateProperties.preload && `${name}.preload = %preload;`}
	`;
        return compiler.generate(result, options, { name, format });
    }
    function trim(nodes) {
        let start = 0;
        for (; start < nodes.length; start += 1) {
            const node = nodes[start];
            if (node.type !== 'Text')
                break;
            node.data = node.data.replace(/^\s+/, '');
            if (node.data)
                break;
        }
        let end = nodes.length;
        for (; end > start; end -= 1) {
            const node = nodes[end - 1];
            if (node.type !== 'Text')
                break;
            node.data = node.data.replace(/\s+$/, '');
            if (node.data)
                break;
        }
        return nodes.slice(start, end);
    }

    const now = (typeof process !== 'undefined' && process.hrtime)
        ? () => {
            const t = process.hrtime();
            return t[0] * 1e3 + t[1] / 1e6;
        }
        : () => self.performance.now();
    function collapseTimings(timings) {
        const result = {};
        timings.forEach(timing => {
            result[timing.label] = Object.assign({
                total: timing.end - timing.start
            }, timing.children && collapseTimings(timing.children));
        });
        return result;
    }
    class Stats {
        constructor({ onwarn }) {
            this.startTime = now();
            this.stack = [];
            this.currentChildren = this.timings = [];
            this.onwarn = onwarn;
            this.warnings = [];
        }
        start(label) {
            const timing = {
                label,
                start: now(),
                end: null,
                children: []
            };
            this.currentChildren.push(timing);
            this.stack.push(timing);
            this.currentTiming = timing;
            this.currentChildren = timing.children;
        }
        stop(label) {
            if (label !== this.currentTiming.label) {
                throw new Error(`Mismatched timing labels`);
            }
            this.currentTiming.end = now();
            this.stack.pop();
            this.currentTiming = this.stack[this.stack.length - 1];
            this.currentChildren = this.currentTiming ? this.currentTiming.children : this.timings;
        }
        render(compiler) {
            const timings = Object.assign({
                total: now() - this.startTime
            }, collapseTimings(this.timings));
            // TODO would be good to have this info even
            // if options.generate is false
            const imports = compiler && compiler.imports.map(node => {
                return {
                    source: node.source.value,
                    specifiers: node.specifiers.map(specifier => {
                        return {
                            name: (specifier.type === 'ImportDefaultSpecifier' ? 'default' :
                                specifier.type === 'ImportNamespaceSpecifier' ? '*' :
                                    specifier.imported.name),
                            as: specifier.local.name
                        };
                    })
                };
            });
            const hooks = compiler && {
                oncreate: !!compiler.templateProperties.oncreate,
                ondestroy: !!compiler.templateProperties.ondestroy,
                onstate: !!compiler.templateProperties.onstate,
                onupdate: !!compiler.templateProperties.onupdate
            };
            return {
                timings,
                warnings: this.warnings,
                imports,
                hooks
            };
        }
        warn(warning) {
            this.warnings.push(warning);
            this.onwarn(warning);
        }
    }

    function assign$1(tar, src) {
    	for (var k in src) tar[k] = src[k];
    	return tar;
    }

    const UNKNOWN = {};
    function gatherPossibleValues(node, set) {
        if (node.type === 'Literal') {
            set.add(node.value);
        }
        else if (node.type === 'ConditionalExpression') {
            gatherPossibleValues(node.consequent, set);
            gatherPossibleValues(node.alternate, set);
        }
        else {
            set.add(UNKNOWN);
        }
    }

    class Selector$2 {
        constructor(node, stylesheet) {
            this.node = node;
            this.stylesheet = stylesheet;
            this.blocks = groupSelectors(node);
            // take trailing :global(...) selectors out of consideration
            let i = this.blocks.length;
            while (i > 0) {
                if (!this.blocks[i - 1].global)
                    break;
                i -= 1;
            }
            this.localBlocks = this.blocks.slice(0, i);
            this.used = this.blocks[0].global;
        }
        apply(node, stack) {
            const toEncapsulate = [];
            applySelector(this.localBlocks.slice(), node, stack.slice(), toEncapsulate);
            if (toEncapsulate.length > 0) {
                toEncapsulate.filter((_, i) => i === 0 || i === toEncapsulate.length - 1).forEach(({ node, block }) => {
                    this.stylesheet.nodesWithCssClass.add(node);
                    block.shouldEncapsulate = true;
                });
                this.used = true;
            }
        }
        minify(code) {
            let c = null;
            this.blocks.forEach((block, i) => {
                if (i > 0) {
                    if (block.start - c > 1) {
                        code.overwrite(c, block.start, block.combinator.name || ' ');
                    }
                }
                c = block.end;
            });
        }
        transform(code, attr) {
            function encapsulateBlock(block) {
                let i = block.selectors.length;
                while (i--) {
                    const selector = block.selectors[i];
                    if (selector.type === 'PseudoElementSelector' || selector.type === 'PseudoClassSelector')
                        continue;
                    if (selector.type === 'TypeSelector' && selector.name === '*') {
                        code.overwrite(selector.start, selector.end, attr);
                    }
                    else {
                        code.appendLeft(selector.end, attr);
                    }
                    break;
                }
                i = block.selectors.length;
                while (i--) {
                    const selector = block.selectors[i];
                    if (selector.type === 'RefSelector') {
                        code.overwrite(selector.start, selector.end, `[svelte-ref-${selector.name}]`, {
                            contentOnly: true,
                            storeName: false
                        });
                    }
                }
            }
            this.blocks.forEach((block, i) => {
                if (block.global) {
                    const selector = block.selectors[0];
                    const first = selector.children[0];
                    const last = selector.children[selector.children.length - 1];
                    code.remove(selector.start, first.start).remove(last.end, selector.end);
                }
                if (block.shouldEncapsulate)
                    encapsulateBlock(block);
            });
        }
        validate(validator) {
            this.blocks.forEach((block) => {
                let i = block.selectors.length;
                while (i-- > 1) {
                    const selector = block.selectors[i];
                    if (selector.type === 'PseudoClassSelector' && selector.name === 'global') {
                        validator.error(selector, {
                            code: `css-invalid-global`,
                            message: `:global(...) must be the first element in a compound selector`
                        });
                    }
                }
            });
            let start = 0;
            let end = this.blocks.length;
            for (; start < end; start += 1) {
                if (!this.blocks[start].global)
                    break;
            }
            for (; end > start; end -= 1) {
                if (!this.blocks[end - 1].global)
                    break;
            }
            for (let i = start; i < end; i += 1) {
                if (this.blocks[i].global) {
                    validator.error(this.blocks[i].selectors[0], {
                        code: `css-invalid-global`,
                        message: `:global(...) can be at the start or end of a selector sequence, but not in the middle`
                    });
                }
            }
        }
    }
    function applySelector(blocks, node, stack, toEncapsulate) {
        const block = blocks.pop();
        if (!block)
            return false;
        if (!node) {
            return blocks.every(block => block.global);
        }
        let i = block.selectors.length;
        let j = stack.length;
        while (i--) {
            const selector = block.selectors[i];
            if (selector.type === 'PseudoClassSelector' && selector.name === 'global') {
                // TODO shouldn't see this here... maybe we should enforce that :global(...)
                // cannot be sandwiched between non-global selectors?
                return false;
            }
            if (selector.type === 'PseudoClassSelector' || selector.type === 'PseudoElementSelector') {
                continue;
            }
            if (selector.type === 'ClassSelector') {
                if (!attributeMatches(node, 'class', selector.name, '~=', false))
                    return false;
            }
            else if (selector.type === 'IdSelector') {
                if (!attributeMatches(node, 'id', selector.name, '=', false))
                    return false;
            }
            else if (selector.type === 'AttributeSelector') {
                if (!attributeMatches(node, selector.name.name, selector.value && unquote(selector.value), selector.matcher, selector.flags))
                    return false;
            }
            else if (selector.type === 'TypeSelector') {
                // remove toLowerCase() in v2, when uppercase elements will be forbidden
                if (node.name.toLowerCase() !== selector.name.toLowerCase() && selector.name !== '*')
                    return false;
            }
            else if (selector.type === 'RefSelector') {
                if (node.ref === selector.name) {
                    node._cssRefAttribute = selector.name;
                    toEncapsulate.push({ node, block });
                    return true;
                }
                return;
            }
            else {
                // bail. TODO figure out what these could be
                toEncapsulate.push({ node, block });
                return true;
            }
        }
        if (block.combinator) {
            if (block.combinator.type === 'WhiteSpace') {
                while (stack.length) {
                    if (applySelector(blocks.slice(), stack.pop(), stack, toEncapsulate)) {
                        toEncapsulate.push({ node, block });
                        return true;
                    }
                }
                return false;
            }
            else if (block.combinator.name === '>') {
                if (applySelector(blocks, stack.pop(), stack, toEncapsulate)) {
                    toEncapsulate.push({ node, block });
                    return true;
                }
                return false;
            }
            // TODO other combinators
            toEncapsulate.push({ node, block });
            return true;
        }
        toEncapsulate.push({ node, block });
        return true;
    }
    const operators = {
        '=': (value, flags) => new RegExp(`^${value}$`, flags),
        '~=': (value, flags) => new RegExp(`\\b${value}\\b`, flags),
        '|=': (value, flags) => new RegExp(`^${value}(-.+)?$`, flags),
        '^=': (value, flags) => new RegExp(`^${value}`, flags),
        '$=': (value, flags) => new RegExp(`${value}$`, flags),
        '*=': (value, flags) => new RegExp(value, flags)
    };
    function attributeMatches(node, name, expectedValue, operator, caseInsensitive) {
        const spread = node.attributes.find(attr => attr.type === 'Spread');
        if (spread)
            return true;
        const attr = node.attributes.find((attr) => attr.name === name);
        if (!attr)
            return false;
        if (attr.isTrue)
            return operator === null;
        if (attr.chunks.length > 1)
            return true;
        if (!expectedValue)
            return true;
        const pattern = operators[operator](expectedValue, caseInsensitive ? 'i' : '');
        const value = attr.chunks[0];
        if (!value)
            return false;
        if (value.type === 'Text')
            return pattern.test(value.data);
        const possibleValues = new Set();
        gatherPossibleValues(value.node, possibleValues);
        if (possibleValues.has(UNKNOWN))
            return true;
        for (const x of Array.from(possibleValues)) { // TypeScript for-of is slightly unlike JS
            if (pattern.test(x))
                return true;
        }
        return false;
    }
    function unquote(value) {
        if (value.type === 'Identifier')
            return value.name;
        const str = value.value;
        if (str[0] === str[str.length - 1] && str[0] === "'" || str[0] === '"') {
            return str.slice(1, str.length - 1);
        }
        return str;
    }
    class Block$3 {
        constructor(combinator) {
            this.combinator = combinator;
            this.global = false;
            this.selectors = [];
            this.start = null;
            this.end = null;
            this.shouldEncapsulate = false;
        }
        add(selector) {
            if (this.selectors.length === 0) {
                this.start = selector.start;
                this.global = selector.type === 'PseudoClassSelector' && selector.name === 'global';
            }
            this.selectors.push(selector);
            this.end = selector.end;
        }
    }
    function groupSelectors(selector) {
        let block = new Block$3(null);
        const blocks = [block];
        selector.children.forEach((child, i) => {
            if (child.type === 'WhiteSpace' || child.type === 'Combinator') {
                block = new Block$3(child);
                blocks.push(block);
            }
            else {
                block.add(child);
            }
        });
        return blocks;
    }

    // https://github.com/darkskyapp/string-hash/blob/master/index.js
    function hash$1(str) {
        let hash = 5381;
        let i = str.length;
        while (i--)
            hash = ((hash << 5) - hash) ^ str.charCodeAt(i);
        return (hash >>> 0).toString(36);
    }

    class Rule$2 {
        constructor(node, stylesheet, parent) {
            this.node = node;
            this.parent = parent;
            this.selectors = node.selector.children.map((node) => new Selector$2(node, stylesheet));
            this.declarations = node.block.children.map((node) => new Declaration$2(node));
        }
        apply(node, stack) {
            this.selectors.forEach(selector => selector.apply(node, stack)); // TODO move the logic in here?
        }
        isUsed(dev) {
            if (this.parent && this.parent.node.type === 'Atrule' && this.parent.node.name === 'keyframes')
                return true;
            if (this.declarations.length === 0)
                return dev;
            return this.selectors.some(s => s.used);
        }
        minify(code, dev) {
            let c = this.node.start;
            let started = false;
            this.selectors.forEach((selector, i) => {
                if (selector.used) {
                    const separator = started ? ',' : '';
                    if ((selector.node.start - c) > separator.length) {
                        code.overwrite(c, selector.node.start, separator);
                    }
                    selector.minify(code);
                    c = selector.node.end;
                    started = true;
                }
            });
            code.remove(c, this.node.block.start);
            c = this.node.block.start + 1;
            this.declarations.forEach((declaration, i) => {
                const separator = i > 0 ? ';' : '';
                if ((declaration.node.start - c) > separator.length) {
                    code.overwrite(c, declaration.node.start, separator);
                }
                declaration.minify(code);
                c = declaration.node.end;
            });
            code.remove(c, this.node.block.end - 1);
        }
        transform(code, id, keyframes) {
            if (this.parent && this.parent.node.type === 'Atrule' && this.parent.node.name === 'keyframes')
                return true;
            const attr = `.${id}`;
            this.selectors.forEach(selector => selector.transform(code, attr));
            this.declarations.forEach(declaration => declaration.transform(code, keyframes));
        }
        validate(validator) {
            this.selectors.forEach(selector => {
                selector.validate(validator);
            });
        }
        warnOnUnusedSelector(handler) {
            this.selectors.forEach(selector => {
                if (!selector.used)
                    handler(selector);
            });
        }
    }
    class Declaration$2 {
        constructor(node) {
            this.node = node;
        }
        transform(code, keyframes) {
            const property = this.node.property && this.node.property.toLowerCase();
            if (property === 'animation' || property === 'animation-name') {
                this.node.value.children.forEach((block) => {
                    if (block.type === 'Identifier') {
                        const name = block.name;
                        if (keyframes.has(name)) {
                            code.overwrite(block.start, block.end, keyframes.get(name));
                        }
                    }
                });
            }
        }
        minify(code) {
            if (!this.node.property)
                return; // @apply, and possibly other weird cases?
            const c = this.node.start + this.node.property.length;
            const first = this.node.value.children ?
                this.node.value.children[0] :
                this.node.value;
            let start = first.start;
            while (/\s/.test(code.original[start]))
                start += 1;
            if (start - c > 1) {
                code.overwrite(c, start, ':');
            }
        }
    }
    class Atrule$2 {
        constructor(node) {
            this.node = node;
            this.children = [];
        }
        apply(node, stack) {
            if (this.node.name === 'media' || this.node.name === 'supports') {
                this.children.forEach(child => {
                    child.apply(node, stack);
                });
            }
            else if (this.node.name === 'keyframes') {
                this.children.forEach((rule) => {
                    rule.selectors.forEach(selector => {
                        selector.used = true;
                    });
                });
            }
        }
        isUsed(dev) {
            return true; // TODO
        }
        minify(code, dev) {
            if (this.node.name === 'media') {
                const expressionChar = code.original[this.node.expression.start];
                let c = this.node.start + (expressionChar === '(' ? 6 : 7);
                if (this.node.expression.start > c)
                    code.remove(c, this.node.expression.start);
                this.node.expression.children.forEach((query) => {
                    // TODO minify queries
                    c = query.end;
                });
                code.remove(c, this.node.block.start);
            }
            else if (this.node.name === 'keyframes') {
                let c = this.node.start + 10;
                if (this.node.expression.start - c > 1)
                    code.overwrite(c, this.node.expression.start, ' ');
                c = this.node.expression.end;
                if (this.node.block.start - c > 0)
                    code.remove(c, this.node.block.start);
            }
            else if (this.node.name === 'supports') {
                let c = this.node.start + 9;
                if (this.node.expression.start - c > 1)
                    code.overwrite(c, this.node.expression.start, ' ');
                this.node.expression.children.forEach((query) => {
                    // TODO minify queries
                    c = query.end;
                });
                code.remove(c, this.node.block.start);
            }
            // TODO other atrules
            if (this.node.block) {
                let c = this.node.block.start + 1;
                this.children.forEach(child => {
                    if (child.isUsed(dev)) {
                        code.remove(c, child.node.start);
                        child.minify(code, dev);
                        c = child.node.end;
                    }
                });
                code.remove(c, this.node.block.end - 1);
            }
        }
        transform(code, id, keyframes) {
            if (this.node.name === 'keyframes') {
                this.node.expression.children.forEach(({ type, name, start, end }) => {
                    if (type === 'Identifier') {
                        if (name.startsWith('-global-')) {
                            code.remove(start, start + 8);
                        }
                        else {
                            code.overwrite(start, end, keyframes.get(name));
                        }
                    }
                });
            }
            this.children.forEach(child => {
                child.transform(code, id, keyframes);
            });
        }
        validate(validator) {
            this.children.forEach(child => {
                child.validate(validator);
            });
        }
        warnOnUnusedSelector(handler) {
            if (this.node.name !== 'media')
                return;
            this.children.forEach(child => {
                child.warnOnUnusedSelector(handler);
            });
        }
    }
    class Stylesheet {
        constructor(source, ast, filename, dev) {
            this.source = source;
            this.ast = ast;
            this.filename = filename;
            this.dev = dev;
            this.children = [];
            this.keyframes = new Map();
            this.nodesWithCssClass = new Set();
            if (ast.css && ast.css.children.length) {
                this.id = `svelte-${hash$1(ast.css.content.styles)}`;
                this.hasStyles = true;
                const stack = [];
                let currentAtrule = null;
                walk(this.ast.css, {
                    enter: (node) => {
                        if (node.type === 'Atrule') {
                            const last = stack[stack.length - 1];
                            const atrule = new Atrule$2(node);
                            stack.push(atrule);
                            // this is an awkward special case — @apply (and
                            // possibly other future constructs)
                            if (last && !(last instanceof Atrule$2))
                                return;
                            if (currentAtrule) {
                                currentAtrule.children.push(atrule);
                            }
                            else {
                                this.children.push(atrule);
                            }
                            if (node.name === 'keyframes') {
                                node.expression.children.forEach((expression) => {
                                    if (expression.type === 'Identifier' && !expression.name.startsWith('-global-')) {
                                        this.keyframes.set(expression.name, `${this.id}-${expression.name}`);
                                    }
                                });
                            }
                            currentAtrule = atrule;
                        }
                        if (node.type === 'Rule') {
                            const rule = new Rule$2(node, this, currentAtrule);
                            stack.push(rule);
                            if (currentAtrule) {
                                currentAtrule.children.push(rule);
                            }
                            else {
                                this.children.push(rule);
                            }
                        }
                    },
                    leave: (node) => {
                        if (node.type === 'Rule' || node.type === 'Atrule')
                            stack.pop();
                        if (node.type === 'Atrule')
                            currentAtrule = stack[stack.length - 1];
                    }
                });
            }
            else {
                this.hasStyles = false;
            }
        }
        apply(node) {
            if (!this.hasStyles)
                return;
            const stack = [];
            let parent = node;
            while (parent = parent.parent) {
                if (parent.type === 'Element')
                    stack.unshift(parent);
            }
            for (let i = 0; i < this.children.length; i += 1) {
                const child = this.children[i];
                child.apply(node, stack);
            }
        }
        reify() {
            this.nodesWithCssClass.forEach((node) => {
                node.addCssClass();
            });
        }
        render(cssOutputFilename, shouldTransformSelectors) {
            if (!this.hasStyles) {
                return { code: null, map: null };
            }
            const code = new MagicString(this.source);
            walk(this.ast.css, {
                enter: (node) => {
                    code.addSourcemapLocation(node.start);
                    code.addSourcemapLocation(node.end);
                }
            });
            if (shouldTransformSelectors) {
                this.children.forEach((child) => {
                    child.transform(code, this.id, this.keyframes);
                });
            }
            let c = 0;
            this.children.forEach(child => {
                if (child.isUsed(this.dev)) {
                    code.remove(c, child.node.start);
                    child.minify(code, this.dev);
                    c = child.node.end;
                }
            });
            code.remove(c, this.source.length);
            return {
                code: code.toString(),
                map: code.generateMap({
                    includeContent: true,
                    source: this.filename,
                    file: cssOutputFilename
                })
            };
        }
        validate(validator) {
            this.children.forEach(child => {
                child.validate(validator);
            });
        }
        warnOnUnusedSelectors(onwarn) {
            let locator;
            const handler = (selector) => {
                const pos = selector.node.start;
                if (!locator)
                    locator = getLocator(this.source, { offsetLine: 1 });
                const start = locator(pos);
                const end = locator(selector.node.end);
                const frame = getCodeFrame(this.source, start.line - 1, start.column);
                const message = `Unused CSS selector`;
                onwarn({
                    code: `css-unused-selector`,
                    message,
                    frame,
                    start,
                    end,
                    pos,
                    filename: this.filename,
                    toString: () => `${message} (${start.line}:${start.column})\n${frame}`,
                });
            };
            this.children.forEach(child => {
                child.warnOnUnusedSelector(handler);
            });
        }
    }

    const version$1 = '2.6.5';
    function normalizeOptions(options) {
        let normalizedOptions = assign$1({ generate: 'dom' }, options);
        const { onwarn, onerror } = normalizedOptions;
        normalizedOptions.onwarn = onwarn
            ? (warning) => onwarn(warning, defaultOnwarn)
            : defaultOnwarn;
        normalizedOptions.onerror = onerror
            ? (error) => onerror(error, defaultOnerror)
            : defaultOnerror;
        return normalizedOptions;
    }
    function defaultOnwarn(warning) {
        if (warning.start) {
            console.warn(`(${warning.start.line}:${warning.start.column}) – ${warning.message}`); // eslint-disable-line no-console
        }
        else {
            console.warn(warning.message); // eslint-disable-line no-console
        }
    }
    function defaultOnerror(error) {
        throw error;
    }
    function parseAttributeValue(value) {
        return /^['"]/.test(value) ?
            value.slice(1, -1) :
            value;
    }
    function parseAttributes(str) {
        const attrs = {};
        str.split(/\s+/).filter(Boolean).forEach(attr => {
            const [name, value] = attr.split('=');
            attrs[name] = value ? parseAttributeValue(value) : true;
        });
        return attrs;
    }
    function replaceTagContents(source, type, preprocessor, options) {
        return __awaiter(this, void 0, void 0, function* () {
            const exp = new RegExp(`<${type}([\\S\\s]*?)>([\\S\\s]*?)<\\/${type}>`, 'ig');
            const match = exp.exec(source);
            if (match) {
                const attributes = parseAttributes(match[1]);
                const content = match[2];
                const processed = yield preprocessor({
                    content,
                    attributes,
                    filename: options.filename
                });
                if (processed && processed.code) {
                    return (source.slice(0, match.index) +
                        `<${type}>${processed.code}</${type}>` +
                        source.slice(match.index + match[0].length));
                }
            }
            return source;
        });
    }
    function preprocess(source, options) {
        return __awaiter(this, void 0, void 0, function* () {
            const { markup, style, script } = options;
            if (!!markup) {
                const processed = yield markup({
                    content: source,
                    filename: options.filename
                });
                source = processed.code;
            }
            if (!!style) {
                source = yield replaceTagContents(source, 'style', style, options);
            }
            if (!!script) {
                source = yield replaceTagContents(source, 'script', script, options);
            }
            return {
                // TODO return separated output, in future version where svelte.compile supports it:
                // style: { code: styleCode, map: styleMap },
                // script { code: scriptCode, map: scriptMap },
                // markup { code: markupCode, map: markupMap },
                toString() {
                    return source;
                }
            };
        });
    }
    function compile(source, _options) {
        const options = normalizeOptions(_options);
        let ast;
        const stats = new Stats({
            onwarn: options.onwarn
        });
        try {
            stats.start('parse');
            ast = parse$1(source, options);
            stats.stop('parse');
        }
        catch (err) {
            options.onerror(err);
            return;
        }
        stats.start('stylesheet');
        const stylesheet = new Stylesheet(source, ast, options.filename, options.dev);
        stats.stop('stylesheet');
        stats.start('validate');
        validate(ast, source, stylesheet, stats, options);
        stats.stop('validate');
        if (options.generate === false) {
            return { ast, stats: stats.render(null), js: null, css: null };
        }
        const compiler = options.generate === 'ssr' ? ssr : dom;
        return compiler(ast, source, stylesheet, options, stats);
    }
    function create$2(source, _options = {}) {
        _options.format = 'eval';
        const compiled = compile(source, _options);
        if (!compiled || !compiled.js.code) {
            return;
        }
        try {
            return (new Function(`return ${compiled.js.code}`))();
        }
        catch (err) {
            if (_options.onerror) {
                _options.onerror(err);
                return;
            }
            else {
                throw err;
            }
        }
    }

    exports.preprocess = preprocess;
    exports.parse = parse$1;
    exports.create = create$2;
    exports.compile = compile;
    exports.VERSION = version$1;

    Object.defineProperty(exports, '__esModule', { value: true });

})));
//# sourceMappingURL=svelte.js.map
